Spaces:
Running
Running
Download src/camera.js from cloudronin/astara: direct link, hf CLI and curl.
- Browser
- Download file 1.93 kB
-
https://huggingface.co/spaces/cloudronin/astara/resolve/main/src/camera.js
- Command line
-
hf download hf://spaces/cloudronin/astara/src/camera.js
-
curl -L -o camera.js https://huggingface.co/spaces/cloudronin/astara/resolve/main/src/camera.js
1.93 kB
| // Follows the prince horizontally with a dead zone across the middle third. | |
| // No vertical movement. No easing, no overshoot. Spec 2.2: "It should be | |
| // boring." | |
| // | |
| // This is the only place world coordinates become screen coordinates. | |
| import { TUNING } from './tuning.js'; | |
| export function createCamera(viewportW, worldMin, worldMax) { | |
| const halfDead = (viewportW * TUNING.CAMERA_DEAD_ZONE) / 2; | |
| // Mutable, because the village changes them exactly once. On the road the | |
| // camera follows forever; at the mouth it stops following and starts being | |
| // bounded, and that one switch IS the transition between the two modes. | |
| let minX = worldMin; | |
| let maxX = Math.max(worldMin, worldMax - viewportW); | |
| return { | |
| x: worldMin, prevX: worldMin, | |
| snapshot() { this.prevX = this.x; }, | |
| reset(targetX) { | |
| this.x = this.prevX = this.clamp(targetX - viewportW / 2); | |
| }, | |
| /** | |
| * Re-bound the view. Takes CAMERA positions, not world edges — the mouth of | |
| * the village fixes where the view may go, not where the world stops, and | |
| * passing world edges through the viewport subtraction twice is exactly the | |
| * off-by-a-half-screen this file has already produced once. | |
| */ | |
| setBounds(minCamX, maxCamX) { | |
| minX = minCamX; | |
| maxX = Math.max(minCamX, maxCamX); | |
| this.x = this.clamp(this.x); | |
| }, | |
| clamp(x) { | |
| return Math.min(maxX, Math.max(minX, x)); | |
| }, | |
| /** Move only when the target leaves the middle third. */ | |
| follow(targetX) { | |
| const centre = this.x + viewportW / 2; | |
| const offset = targetX - centre; | |
| if (offset > halfDead) this.x += offset - halfDead; | |
| else if (offset < -halfDead) this.x += offset + halfDead; | |
| this.x = this.clamp(this.x); | |
| }, | |
| /** World x -> screen x at a given parallax rate. 1.0 is the actor layer. */ | |
| toScreen(worldX, rate = 1) { | |
| return worldX - this.x * rate; | |
| }, | |
| }; | |
| } | |