From 2f626bcc39f890ce59696867101c35c2a2f2a4dd Mon Sep 17 00:00:00 2001 From: evanpelle Date: Mon, 16 Sep 2024 09:42:23 -0700 Subject: [PATCH] mobile friendly --- src/client/ClientGame.ts | 5 +- src/client/InputHandler.ts | 97 ++++++++++++++++++++--------- src/client/graphics/GameRenderer.ts | 1 + 3 files changed, 69 insertions(+), 34 deletions(-) diff --git a/src/client/ClientGame.ts b/src/client/ClientGame.ts index da2074576..104c9efc3 100644 --- a/src/client/ClientGame.ts +++ b/src/client/ClientGame.ts @@ -118,9 +118,6 @@ export class ClientGame { public start() { console.log('version 3') - - - this.isActive = true // TODO: make each class do this, or maybe have client intercept all requests? //this.eventBus.on(TickEvent, (e) => this.tick(e)) @@ -185,7 +182,7 @@ export class ClientGame { this.renderer.playerEvent(event) } - private inputEvent(event: MouseDownEvent) { + private inputEvent(event: MouseUpEvent) { if (!this.isActive) { return } diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index bad6f4f70..13faf254f 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -32,12 +32,17 @@ export class DragEvent implements GameEvent { export class InputHandler { - private lastMouseDownX: number = 0 - private lastMouseDownY: number + private lastPointerX: number = 0; + private lastPointerY: number = 0; - private isMouseDown: boolean = false; - private lastMouseX: number = 0; - private lastMouseY: number = 0; + private lastPointerDownX: number = 0; + private lastPointerDownY: number = 0; + + private pointers: Map = new Map(); + + private lastPinchDistance: number = 0; + + private pointerDown: boolean = false constructor(private eventBus: EventBus) { } @@ -45,20 +50,31 @@ export class InputHandler { document.addEventListener("pointerdown", (e) => this.onPointerDown(e)); document.addEventListener("pointerup", (e) => this.onPointerUp(e)); document.addEventListener("wheel", (e) => this.onScroll(e), {passive: false}); - document.addEventListener('mousedown', this.onMouseDown.bind(this)); - document.addEventListener('mousemove', this.onMouseMove.bind(this)); - document.addEventListener('mouseup', this.onMouseUp.bind(this)); - document.addEventListener('mouseleave', this.onMouseUp.bind(this)) + document.addEventListener('pointermove', this.onPointerMove.bind(this)); + this.pointers.clear() } - onPointerDown(event: PointerEvent) { - this.lastMouseDownX = event.x - this.lastMouseDownY = event.y - this.eventBus.emit(new MouseDownEvent(event.x, event.y)) + private onPointerDown(event: PointerEvent) { + this.pointerDown = true + this.pointers.set(event.pointerId, event); + + if (this.pointers.size === 1) { + this.lastPointerX = event.clientX; + this.lastPointerY = event.clientY; + + this.lastPointerDownX = event.clientX + this.lastPointerDownY = event.clientY + + this.eventBus.emit(new MouseDownEvent(event.clientX, event.clientY)); + } else if (this.pointers.size === 2) { + this.lastPinchDistance = this.getPinchDistance(); + } } onPointerUp(event: PointerEvent) { - const dist = Math.abs(event.x - this.lastMouseDownX) + Math.abs(event.y - this.lastMouseDownY); + this.pointerDown = false + this.pointers.delete(event.pointerId); + const dist = Math.abs(event.x - this.lastPointerDownX) + Math.abs(event.y - this.lastPointerDownY); if (dist < 10) { this.eventBus.emit(new MouseUpEvent(event.x, event.y)) } @@ -68,26 +84,47 @@ export class InputHandler { this.eventBus.emit(new ZoomEvent(event.x, event.y, event.deltaY)) } - private onMouseDown(event: MouseEvent) { - this.isMouseDown = true; - this.lastMouseX = event.clientX; - this.lastMouseY = event.clientY; + private onPointerMove(event: PointerEvent) { + + this.pointers.set(event.pointerId, event); + + if (!this.pointerDown) { + return + } + + if (this.pointers.size === 1) { + const deltaX = event.clientX - this.lastPointerX; + const deltaY = event.clientY - this.lastPointerY; + + this.eventBus.emit(new DragEvent(deltaX, deltaY)); + + this.lastPointerX = event.clientX; + this.lastPointerY = event.clientY; + } else if (this.pointers.size === 2) { + const currentPinchDistance = this.getPinchDistance(); + 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)); + this.lastPinchDistance = currentPinchDistance; + } + } } - private onMouseMove(event: MouseEvent) { - if (!this.isMouseDown) return; - - const deltaX = event.clientX - this.lastMouseX; - const deltaY = event.clientY - this.lastMouseY; - - this.eventBus.emit(new DragEvent(deltaX, deltaY)) - - this.lastMouseX = event.clientX; - this.lastMouseY = event.clientY; + private getPinchDistance(): number { + const pointerEvents = Array.from(this.pointers.values()); + const dx = pointerEvents[0].clientX - pointerEvents[1].clientX; + const dy = pointerEvents[0].clientY - pointerEvents[1].clientY; + return Math.sqrt(dx * dx + dy * dy); } - private onMouseUp(event: MouseEvent) { - this.isMouseDown = false; + private getPinchCenter(): {x: number, y: number} { + const pointerEvents = Array.from(this.pointers.values()); + return { + x: (pointerEvents[0].clientX + pointerEvents[1].clientX) / 2, + y: (pointerEvents[0].clientY + pointerEvents[1].clientY) / 2 + }; } } \ No newline at end of file diff --git a/src/client/graphics/GameRenderer.ts b/src/client/graphics/GameRenderer.ts index 2dea647de..c28700f37 100644 --- a/src/client/graphics/GameRenderer.ts +++ b/src/client/graphics/GameRenderer.ts @@ -45,6 +45,7 @@ export class GameRenderer { this.canvas.style.top = '0'; this.canvas.style.width = '100%'; this.canvas.style.height = '100%'; + this.canvas.style.touchAction = 'none'; this.nameRenderer.initialize() this.terrainRenderer.init()