Skip to content

Commit 5d4fc7a

Browse files
committed
fix camera zooming
1 parent 131b1f8 commit 5d4fc7a

File tree

3 files changed

+32
-5
lines changed

3 files changed

+32
-5
lines changed

client/src/camera/CameraController.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export class CameraController {
3333
private readonly camera: THREE.PerspectiveCamera;
3434
private rotation: CameraRotation = { theta: 0, phi: 0.5 };
3535
private distance: number = 10;
36+
private targetDistance: number = 10;
3637
private anchored: boolean = false;
3738
private focusPoint: THREE.Vector3 | null = null;
3839

@@ -41,6 +42,8 @@ export class CameraController {
4142
private readonly maxDistance: number = 50;
4243
private readonly rotationSpeed: number = 0.02;
4344
private readonly freeMoveSpeed: number = 0.5;
45+
private readonly zoomSpeed: number = 0.0025;
46+
private readonly zoomLerp: number = 0.18;
4447

4548
constructor(aspectRatio: number) {
4649
this.camera = new THREE.PerspectiveCamera(75, aspectRatio, 0.1, 10000);
@@ -75,8 +78,11 @@ export class CameraController {
7578
}
7679

7780
public adjustZoom(delta: number): void {
78-
this.distance += delta;
79-
this.distance = Math.max(this.minDistance, Math.min(this.maxDistance, this.distance));
81+
// Use exponential scaling for consistent feel across small/large wheel deltas:
82+
// delta > 0 => zoom out (increase distance), delta < 0 => zoom in.
83+
const factor = Math.exp(delta * this.zoomSpeed);
84+
this.targetDistance *= factor;
85+
this.targetDistance = Math.max(this.minDistance, Math.min(this.maxDistance, this.targetDistance));
8086
}
8187

8288
public adjustRotation(deltaTheta: number, deltaPhi: number): void {
@@ -90,6 +96,9 @@ export class CameraController {
9096
public update(player: Player | null, input: InputManager): void {
9197
if (!player) return;
9298

99+
// Smoothly approach the zoom target each frame.
100+
this.distance = THREE.MathUtils.lerp(this.distance, this.targetDistance, this.zoomLerp);
101+
93102
// Handle arrow keys and Q/E for horizontal camera rotation
94103
if (input.isKeyPressed('arrowleft') || input.isKeyPressed('q')) {
95104
this.rotation.theta += this.rotationSpeed;
@@ -159,5 +168,8 @@ export class CameraController {
159168
public setInitialPosition(player: Player): void {
160169
const pos = player.mesh.position;
161170
this.camera.position.set(pos.x, pos.y + 5, pos.z + 10);
171+
// Keep zoom state consistent with initial placement.
172+
this.distance = this.camera.position.distanceTo(new THREE.Vector3(pos.x, pos.y, pos.z));
173+
this.targetDistance = this.distance;
162174
}
163175
}

client/src/commit_time.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2026-01-14T20:41:29.540Z
1+
2026-01-14T20:48:25.803Z

client/src/input/InputManager.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ export class InputManager {
8787
document.addEventListener('mousedown', this.handleMouseDown);
8888
document.addEventListener('mousemove', this.handleMouseMove);
8989
document.addEventListener('mouseup', this.handleMouseUp);
90-
document.addEventListener('wheel', this.handleWheel);
90+
// Note: wheel listeners are often passive by default in browsers; set passive:false so we can prevent scrolling.
91+
document.addEventListener('wheel', this.handleWheel, { passive: false });
9192
document.addEventListener('contextmenu', this.handleContextMenu);
9293
}
9394

@@ -131,8 +132,22 @@ export class InputManager {
131132
};
132133

133134
private handleWheel = (e: WheelEvent): void => {
135+
// Prevent the page from scrolling while zooming the camera.
136+
e.preventDefault();
137+
138+
// Normalize wheel delta to roughly "pixels" across devices:
139+
// - DOM_DELTA_PIXEL (0): already pixels
140+
// - DOM_DELTA_LINE (1): convert lines to pixels
141+
// - DOM_DELTA_PAGE (2): convert pages to viewport height
142+
let delta = e.deltaY;
143+
if (e.deltaMode === 1) {
144+
delta *= 16;
145+
} else if (e.deltaMode === 2) {
146+
delta *= window.innerHeight;
147+
}
148+
134149
for (const callback of this.onWheelCallbacks) {
135-
callback(e.deltaY);
150+
callback(delta);
136151
}
137152
};
138153

0 commit comments

Comments
 (0)