Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

arena: fix orbit distance drift during swivel

Capture the XZ orbit distance when right-click starts and maintain it
throughout the orbit. Previously the distance would change as cam.rotX
varied, causing the camera to drift from the player center.

Simplify orbit calculation to use constant captured distance and angle
directly, avoiding drift from repeated offset calculations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+18 -19
+18 -19
system/public/aesthetic.computer/disks/arena.mjs
··· 81 81 // without changing player body rotation. Orbits by modifying XZ offset. 82 82 let orbitAngle = 0; // extra Y rotation for camera only (degrees) 83 83 let orbiting = false; // currently dragging with right button 84 + let orbitDistance = 0; // captured XZ distance when orbit starts, stays constant 84 85 let appliedOrbitOffset = [0, 0]; // track X,Z offset we applied so we can undo it 85 86 let baseRotY = 0; // cam.rotY when orbit started, to prevent player spinning 86 87 let orbitSnapped = false; // true if orbit was released; reset on next left-click ··· 691 692 // modifying the XZ offset without changing cam.rotY (so player body stays put). 692 693 // Orbit angle persists after release until left-click is pressed. 693 694 694 - if (zoomLevel > 0 && Math.abs(orbitAngle) > 0.01) { 695 + if (zoomLevel > 0 && Math.abs(orbitAngle) > 0.01 && orbitDistance > 0) { 695 696 const pCamX = phys?.playerCamX ?? cam.x; 696 697 const pCamZ = phys?.playerCamZ ?? cam.z; 697 - // Current XZ offset from logical player pos to render camera pos 698 - const dx = cam.x - pCamX; 699 - const dz = cam.z - pCamZ; 700 - const dist = Math.sqrt(dx * dx + dz * dz); 701 - if (dist > 0) { 702 - // Compute current angle in XZ plane using atan2(X, Z) convention for cam-space 703 - const baseAngle = Math.atan2(dx, dz); 704 - const orbitRad = orbitAngle * Math.PI / 180; 705 - const newAngle = baseAngle + orbitRad; 706 - // Keep the distance constant by using the magnitude of the XZ offset 707 - const newX = pCamX + dist * Math.sin(newAngle); 708 - const newZ = pCamZ + dist * Math.cos(newAngle); 709 - // Track the total change we're making so we can undo it next frame 710 - appliedOrbitOffset[0] = newX - cam.x; 711 - appliedOrbitOffset[1] = newZ - cam.z; 712 - cam.x = newX; 713 - cam.z = newZ; 714 - } 698 + // Use captured orbit distance (constant throughout orbit) to maintain radius 699 + const orbitRad = orbitAngle * Math.PI / 180; 700 + const newX = pCamX + orbitDistance * Math.sin(orbitRad); 701 + const newZ = pCamZ + orbitDistance * Math.cos(orbitRad); 702 + // Track the total change we're making so we can undo it next frame 703 + appliedOrbitOffset[0] = newX - cam.x; 704 + appliedOrbitOffset[1] = newZ - cam.z; 705 + cam.x = newX; 706 + cam.z = newZ; 715 707 } 716 708 } 717 709 ··· 968 960 orbiting = true; 969 961 baseRotY = cam.rotY; // lock player rotation to current heading 970 962 orbitSnapped = false; // start orbiting fresh 963 + // Capture current XZ distance to maintain constant orbit radius 964 + const phys = system?.fps?.doll?.physics; 965 + const pCamX = phys?.playerCamX ?? cam.x; 966 + const pCamZ = phys?.playerCamZ ?? cam.z; 967 + const dx = cam.x - pCamX; 968 + const dz = cam.z - pCamZ; 969 + orbitDistance = Math.sqrt(dx * dx + dz * dz); 971 970 } else if (e.is("lift") && e.button === 2) { 972 971 orbiting = false; 973 972 orbitSnapped = true; // mark that orbit was released; wait for left-click to reset