Issue #5: Mouse handling — zoom-to-mouse + middle-click pan #10
@@ -26,6 +26,10 @@ export class CameraSystem {
|
|||||||
private middlePanActive = false
|
private middlePanActive = false
|
||||||
private lastPanX = 0
|
private lastPanX = 0
|
||||||
private lastPanY = 0
|
private lastPanY = 0
|
||||||
|
private mouseScreenX = 0
|
||||||
|
private mouseScreenY = 0
|
||||||
|
private mouseWorldX = 0
|
||||||
|
private mouseWorldY = 0
|
||||||
private debugCross?: Phaser.GameObjects.Graphics
|
private debugCross?: Phaser.GameObjects.Graphics
|
||||||
|
|
||||||
constructor(scene: Phaser.Scene, adapter: LocalAdapter) {
|
constructor(scene: Phaser.Scene, adapter: LocalAdapter) {
|
||||||
@@ -62,18 +66,24 @@ export class CameraSystem {
|
|||||||
this.debugCross.lineBetween(cx - 12, cy, cx + 12, cy)
|
this.debugCross.lineBetween(cx - 12, cy, cx + 12, cy)
|
||||||
this.debugCross.lineBetween(cx, cy - 12, cx, cy + 12)
|
this.debugCross.lineBetween(cx, cy - 12, cx, cy + 12)
|
||||||
|
|
||||||
|
// Track mouse world position on every move so we have a stable value for zoom
|
||||||
|
this.scene.input.on('pointermove', (ptr: Phaser.Input.Pointer) => {
|
||||||
|
this.mouseScreenX = ptr.x
|
||||||
|
this.mouseScreenY = ptr.y
|
||||||
|
this.mouseWorldX = cam.scrollX + ptr.x / cam.zoom
|
||||||
|
this.mouseWorldY = cam.scrollY + ptr.y / cam.zoom
|
||||||
|
})
|
||||||
|
|
||||||
// Scroll wheel zoom — zoom toward mouse pointer
|
// Scroll wheel zoom — zoom toward mouse pointer
|
||||||
this.scene.input.on('wheel', (ptr: Phaser.Input.Pointer, _objs: unknown, _dx: number, dy: number) => {
|
this.scene.input.on('wheel', (_ptr: Phaser.Input.Pointer, _objs: unknown, _dx: number, dy: number) => {
|
||||||
const newZoom = Phaser.Math.Clamp(cam.zoom - Math.sign(dy) * ZOOM_STEP, MIN_ZOOM, MAX_ZOOM)
|
const newZoom = Phaser.Math.Clamp(cam.zoom - Math.sign(dy) * ZOOM_STEP, MIN_ZOOM, MAX_ZOOM)
|
||||||
if (newZoom === cam.zoom) return
|
if (newZoom === cam.zoom) return
|
||||||
const worldX = ptr.worldX // capture BEFORE zoom changes the value
|
|
||||||
const worldY = ptr.worldY
|
|
||||||
cam.setZoom(newZoom)
|
cam.setZoom(newZoom)
|
||||||
cam.scrollX = worldX - ptr.x / newZoom
|
cam.scrollX = this.mouseWorldX - this.mouseScreenX / newZoom
|
||||||
cam.scrollY = worldY - ptr.y / newZoom
|
cam.scrollY = this.mouseWorldY - this.mouseScreenY / newZoom
|
||||||
const centerX = cam.scrollX + cam.width / (2 * cam.zoom)
|
const centerX = cam.scrollX + cam.width / (2 * cam.zoom)
|
||||||
const centerY = cam.scrollY + cam.height / (2 * cam.zoom)
|
const centerY = cam.scrollY + cam.height / (2 * cam.zoom)
|
||||||
console.log(`[zoom] ptr=(${ptr.x.toFixed(0)},${ptr.y.toFixed(0)}) world=(${ptr.worldX.toFixed(0)},${ptr.worldY.toFixed(0)}) center=(${centerX.toFixed(0)},${centerY.toFixed(0)}) zoom=${cam.zoom.toFixed(2)}`)
|
console.log(`[zoom] screen=(${this.mouseScreenX.toFixed(0)},${this.mouseScreenY.toFixed(0)}) world=(${this.mouseWorldX.toFixed(0)},${this.mouseWorldY.toFixed(0)}) center=(${centerX.toFixed(0)},${centerY.toFixed(0)}) zoom=${cam.zoom.toFixed(2)}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Middle-click pan: start on button down
|
// Middle-click pan: start on button down
|
||||||
|
|||||||
Reference in New Issue
Block a user