From c3a5e58be673eacee531c76df75dc62f0229e6a9 Mon Sep 17 00:00:00 2001 From: Evan Date: Tue, 11 Feb 2025 18:01:26 -0800 Subject: [PATCH] add zoom and pan keyboard shortcuts --- src/client/InputHandler.ts | 124 +++++++++++++++++++++++++++---------- 1 file changed, 92 insertions(+), 32 deletions(-) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index b2394a48e..9748d5fef 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -2,46 +2,31 @@ import { EventBus, GameEvent } from "../core/EventBus"; import { Game } from "../core/game/Game"; export class MouseUpEvent implements GameEvent { - constructor( - public readonly x: number, - public readonly y: number, - ) {} + constructor(public readonly x: number, public readonly y: number) {} } export class MouseDownEvent implements GameEvent { - constructor( - public readonly x: number, - public readonly y: number, - ) {} + constructor(public readonly x: number, public readonly y: number) {} } export class MouseMoveEvent implements GameEvent { - constructor( - public readonly x: number, - public readonly y: number, - ) {} + constructor(public readonly x: number, public readonly y: number) {} } export class ContextMenuEvent implements GameEvent { - constructor( - public readonly x: number, - public readonly y: number, - ) {} + constructor(public readonly x: number, public readonly y: number) {} } export class ZoomEvent implements GameEvent { constructor( public readonly x: number, public readonly y: number, - public readonly delta: number, + public readonly delta: number ) {} } export class DragEvent implements GameEvent { - constructor( - public readonly deltaX: number, - public readonly deltaY: number, - ) {} + constructor(public readonly deltaX: number, public readonly deltaY: number) {} } export class AlternateViewEvent implements GameEvent { @@ -51,10 +36,7 @@ export class AlternateViewEvent implements GameEvent { export class RefreshGraphicsEvent implements GameEvent {} export class ShowBuildMenuEvent implements GameEvent { - constructor( - public readonly x: number, - public readonly y: number, - ) {} + constructor(public readonly x: number, public readonly y: number) {} } export class InputHandler { @@ -72,10 +54,13 @@ export class InputHandler { private alternateView = false; - constructor( - private canvas: HTMLCanvasElement, - private eventBus: EventBus, - ) {} + private moveInterval: any = null; + private activeKeys = new Set(); + + private readonly PAN_SPEED = 5; + private readonly ZOOM_SPEED = 10; + + constructor(private canvas: HTMLCanvasElement, private eventBus: EventBus) {} initialize() { this.canvas.addEventListener("pointerdown", (e) => this.onPointerDown(e)); @@ -95,14 +80,67 @@ export class InputHandler { }); this.pointers.clear(); + // Initialize the combined movement interval + this.moveInterval = setInterval(() => { + let deltaX = 0; + let deltaY = 0; + + // Handle both WASD and arrow keys + if (this.activeKeys.has("KeyW") || this.activeKeys.has("ArrowUp")) + deltaY += this.PAN_SPEED; + if (this.activeKeys.has("KeyS") || this.activeKeys.has("ArrowDown")) + deltaY -= this.PAN_SPEED; + if (this.activeKeys.has("KeyA") || this.activeKeys.has("ArrowLeft")) + deltaX += this.PAN_SPEED; + if (this.activeKeys.has("KeyD") || this.activeKeys.has("ArrowRight")) + deltaX -= this.PAN_SPEED; + + if (deltaX !== 0 || deltaY !== 0) { + this.eventBus.emit(new DragEvent(deltaX, deltaY)); + } + + // Handle zooming + const screenCenterX = window.innerWidth / 2; + const screenCenterY = window.innerHeight / 2; + + if (this.activeKeys.has("Minus")) { + this.eventBus.emit( + new ZoomEvent(screenCenterX, screenCenterY, this.ZOOM_SPEED) + ); + } + if (this.activeKeys.has("Equal")) { + this.eventBus.emit( + new ZoomEvent(screenCenterX, screenCenterY, -this.ZOOM_SPEED) + ); + } + }, 1); + window.addEventListener("keydown", (e) => { if (e.code === "Space") { - e.preventDefault(); // Prevent page scrolling + e.preventDefault(); if (!this.alternateView) { this.alternateView = true; this.eventBus.emit(new AlternateViewEvent(true)); } } + + // Add all movement keys to activeKeys + if ( + [ + "KeyW", + "KeyA", + "KeyS", + "KeyD", + "ArrowUp", + "ArrowLeft", + "ArrowDown", + "ArrowRight", + "Minus", + "Equal", + ].includes(e.code) + ) { + this.activeKeys.add(e.code); + } }); window.addEventListener("keyup", (e) => { @@ -115,6 +153,24 @@ export class InputHandler { e.preventDefault(); this.eventBus.emit(new RefreshGraphicsEvent()); } + + // Remove all movement keys from activeKeys + if ( + [ + "KeyW", + "KeyA", + "KeyS", + "KeyD", + "ArrowUp", + "ArrowLeft", + "ArrowDown", + "ArrowRight", + "Minus", + "Equal", + ].includes(e.code) + ) { + this.activeKeys.delete(e.code); + } }); } @@ -193,10 +249,9 @@ export class InputHandler { const pinchDelta = currentPinchDistance - this.lastPinchDistance; if (Math.abs(pinchDelta) > 1) { - // Threshold to avoid tiny zoom adjustments const zoomCenter = this.getPinchCenter(); this.eventBus.emit( - new ZoomEvent(zoomCenter.x, zoomCenter.y, -pinchDelta * 2), + new ZoomEvent(zoomCenter.x, zoomCenter.y, -pinchDelta * 2) ); this.lastPinchDistance = currentPinchDistance; } @@ -222,4 +277,9 @@ export class InputHandler { y: (pointerEvents[0].clientY + pointerEvents[1].clientY) / 2, }; } + + destroy() { + clearInterval(this.moveInterval); + this.activeKeys.clear(); + } }