Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

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

arena: right-click drag to orbit camera around player (3P)

Implements camera orbit by tracking a separate orbitAngle that modifies
the XZ camera offset without changing cam.rotY. This keeps the player
body rotation fixed while the camera swivels around them.

Logic:
- Accumulate orbitAngle from right-click drag (delta.x * 0.4)
- In sim, convert current XZ offset to polar, add orbitAngle, convert back
- Decay orbitAngle back to 0 when right-click releases
- Only applies in 3P mode (zoomLevel > 0)
- Don't penLock on button 2

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

+41 -2
+41 -2
system/public/aesthetic.computer/disks/arena.mjs
··· 74 74 const ZOOM_DISTANCES = [0, 0.5, 1, 1.5, 2, 3, 4.5, 6, 9]; 75 75 let zoomLevel = 2; // Start at 1 unit back (shoulder camera) 76 76 77 + // 🎥 Right-click camera orbit (3P mode only): rotate camera around player 78 + // without changing player body rotation. Orbits by modifying XZ offset. 79 + let orbitAngle = 0; // extra Y rotation for camera only (degrees) 80 + let orbiting = false; // currently dragging with right button 81 + 77 82 function applyZoom(doll) { 78 83 if (!doll) return; 79 84 const d = ZOOM_DISTANCES[zoomLevel]; ··· 664 669 }, null, 2), 665 670 ); 666 671 } 672 + 673 + // 🎥 Camera orbit effect (3P mode only): rotate camera around player by 674 + // modifying the XZ offset without changing cam.rotY (so player body stays put). 675 + if (!orbiting) { 676 + orbitAngle *= 0.85; // decay back to 0 on release 677 + if (Math.abs(orbitAngle) < 0.5) orbitAngle = 0; 678 + } 679 + 680 + if (zoomLevel > 0 && Math.abs(orbitAngle) > 0.01) { 681 + const pCamX = phys?.playerCamX ?? cam.x; 682 + const pCamZ = phys?.playerCamZ ?? cam.z; 683 + // Current XZ offset from logical player pos to render camera pos 684 + const dx = cam.x - pCamX; 685 + const dz = cam.z - pCamZ; 686 + const dist = Math.sqrt(dx * dx + dz * dz); 687 + if (dist > 0) { 688 + // Compute current angle in XZ plane, add orbit angle, recompute position 689 + const baseAngle = Math.atan2(dx, dz); 690 + const orbitRad = orbitAngle * Math.PI / 180; 691 + const newAngle = baseAngle + orbitRad; 692 + cam.x = pCamX + dist * Math.sin(newAngle); 693 + cam.z = pCamZ + dist * Math.cos(newAngle); 694 + } 695 + } 667 696 } 668 697 669 698 function paint({ wipe, ink, screen, write, box, system, pen }) { ··· 913 942 applyZoom(system?.fps?.doll); 914 943 } 915 944 945 + // 🎥 Right-click drag to orbit camera around player (3P mode only). 946 + if (e.is("touch") && e.button === 2) { 947 + orbiting = true; 948 + } else if (e.is("lift") && e.button === 2) { 949 + orbiting = false; 950 + } else if (e.is("draw") && e.button === 2) { 951 + // Drag: accumulate orbit angle (1px ≈ 0.4° per frame) 952 + orbitAngle += e.delta.x * 0.4; 953 + } 954 + 916 955 // While dead, any touch respawns; otherwise the first touch re-locks the pen. 917 956 if (e.is("touch")) { 918 957 if (!playerAlive && deathTickAge > 30) { ··· 923 962 system?.fps?.doll?.respawn?.(0, 0); 924 963 return; 925 964 } 926 - // Don't re-lock on middle-click — user is using it for 3P toggle. 927 - if (!penLocked && e.button !== 1) penLock(); 965 + // Don't re-lock on middle-click (1) or right-click (2) — reserved for camera control. 966 + if (!penLocked && e.button !== 1 && e.button !== 2) penLock(); 928 967 } 929 968 } 930 969