Walk and fly through the city

Adds walk and fly cameras alongside the helicopter view, switched with
1/2/3 or the city toolbar. Walking uses mouse-look with pointer lock
(or drag), WASD, Shift to run and circle-vs-footprint collision with
sub-stepping so long frames cannot tunnel through buildings; flying
follows the view pitch with Space/C for altitude and clears low roofs.
Double-clicking a street drops you there with an animated descent,
facing the longest open street. A crosshair names the building ahead
(E or click inspects it), the address bar shows the folder you are in,
and a minimap shows your heading and teleports on click.
This commit is contained in:
Andy Dixon
2026-05-23 14:33:00 +01:00
parent 3036763d08
commit 76c846fdce
6 changed files with 310 additions and 9 deletions
+2 -2
View File
@@ -165,7 +165,7 @@ export class LandscapeRenderer {
this.landscape = this.boxLayer(); this.cityLayer = this.boxLayer();
this.camera = { x: 500, y: 350, zoom: 1, yaw: -.1, pitch: .78, distance: 3.5 };
// City camera: 'heli' orbits a ground target; 'walk' and 'fly' look out from an eye position.
this.city = { view: 'heli', x: 0, y: 0, yaw: -.12, pitch: .8, distance: 500, eye: [0, 0, EYE_HEIGHT], lookYaw: 0, lookPitch: 0 };
this.city = { view: 'heli', x: 0, y: 0, yaw: -.12, pitch: .8, distance: 500, ex: 0, ey: 0, ez: EYE_HEIGHT, lookYaw: 0, lookPitch: 0 };
this.mode = '2d';
this.resize();
}
@@ -251,7 +251,7 @@ export class LandscapeRenderer {
const eye = [c.x + sy * cp * c.distance, c.y + cy * cp * c.distance, sp * c.distance];
return { eye, forward: [-sy * cp, -cy * cp, -sp] };
}
return { eye: c.eye, forward: direction(c.lookYaw, c.lookPitch) };
return { eye: [c.ex, c.ey, c.ez], forward: direction(c.lookYaw, c.lookPitch) };
}
// Recomputes the 3D view-projection from the active camera; runs on every resize check.