Mouse handling #5

Closed
opened 2026-03-20 16:22:17 +00:00 by tekki · 3 comments
Owner

If the world is zoomed by the mouse it should rater zoom to the mouse position than the center auf the screen.

If the middle button is pressed i want the map also to drag.

If the world is zoomed by the mouse it should rater zoom to the mouse position than the center auf the screen. If the middle button is pressed i want the map also to drag.
tekki added the
improvement
status: in discussion
labels 2026-03-20 16:22:17 +00:00
Collaborator

Two quick questions before this is ready:

  1. Middle-click pan — should the camera move while the middle button is held (continuous pan), or is it a toggle (click once to enter pan mode, click again to exit)?
  2. Zoom to mouse position — should the zoom centre on the current mouse cursor position, or on the current camera centre?
Two quick questions before this is ready: 1. **Middle-click pan** — should the camera move while the middle button is held (continuous pan), or is it a toggle (click once to enter pan mode, click again to exit)? 2. **Zoom to mouse position** — should the zoom centre on the current mouse cursor position, or on the current camera centre?
Author
Owner
  1. While held.
  2. To the mouse!
1. While held. 2. To the mouse!
claude added
status: ready
and removed
status: in discussion
labels 2026-03-20 19:17:12 +00:00
claude added
status: review
and removed
status: ready
labels 2026-03-20 19:24:49 +00:00
Collaborator

Implementierung abgeschlossen

Problem & bisherige Schwierigkeiten

Der erste naive Ansatz (zoom-to-mouse per manueller scrollX/Y-Formel basierend auf ptr.worldX/Y) schlug mehrfach fehl. Die Kernfrage war: Wo genau ist Phasers Zoom-Ankerpunkt?

Einige fehlgeschlagene Annahmen:

  • ptr.worldX ist zum Zeitpunkt des Wheel-Events aktuell → falsch, der Wert ist veraltet
  • Phaser zoomt von der oberen linken Ecke (scrollX/scrollY) → falsch
  • centerWorld = scrollX + viewportWidth / (2 * zoom) → falsch

Lösung: Test-Szenen zur empirischen Analyse

Statt weiter zu raten haben wir eine separate Test-Umgebung gebaut (/test.html, src/test/), die:

  • Ein 500×500-Tile-Raster mit Crosshair-Markern rendert
  • Alle Kamera-Kennzahlen live im HUD anzeigt (Zoom, scrollX/Y, Viewport in px und Tiles, Maus-World/Screen/Tile)
  • Jeden Zoom-Event als JSON in game-test.log schreibt (via Vite-Middleware)
  • Einen direkten Vergleich zwischen Phaser-Default-Zoom und Zoom-to-Mouse ermöglicht (Tab zum Wechseln)

Befund aus den Logs

scrollX_delta ist bei jedem Zoom-Event 0 — Phaser verändert den Scroll nie. Visuell bleibt aber der Mittelpunkt stabil, was bedeutet: Phaser zoomt vom Screenzentrumm, nicht von der oberen linken Ecke.

Die korrekte Weltkoordinate unter einem Screenpunkt ist:

worldX = scrollX + screenWidth/2 + (screenX - screenWidth/2) / zoom

Daraus folgt die Scroll-Korrektur für Zoom-to-Mouse:

scrollX += (mouseX - screenWidth/2) * (1/zoomBefore - 1/zoomAfter)
scrollY += (mouseY - screenHeight/2) * (1/zoomBefore - 1/zoomAfter)

Umgesetzte Änderungen

  • CameraSystem.ts: Zoom-to-Mouse mit obiger Formel, getCenterWorld() korrigiert, JSDoc auf allen Methoden
  • src/test/: Test-Infrastruktur bleibt bestehen für künftige Kamera-Analysen
  • PR #10 enthält alle Commits
## Implementierung abgeschlossen ### Problem & bisherige Schwierigkeiten Der erste naive Ansatz (`zoom-to-mouse` per manueller scrollX/Y-Formel basierend auf `ptr.worldX/Y`) schlug mehrfach fehl. Die Kernfrage war: **Wo genau ist Phasers Zoom-Ankerpunkt?** Einige fehlgeschlagene Annahmen: - `ptr.worldX` ist zum Zeitpunkt des Wheel-Events aktuell → falsch, der Wert ist veraltet - Phaser zoomt von der oberen linken Ecke (`scrollX`/`scrollY`) → falsch - `centerWorld = scrollX + viewportWidth / (2 * zoom)` → falsch ### Lösung: Test-Szenen zur empirischen Analyse Statt weiter zu raten haben wir eine separate Test-Umgebung gebaut (`/test.html`, `src/test/`), die: - Ein 500×500-Tile-Raster mit Crosshair-Markern rendert - Alle Kamera-Kennzahlen live im HUD anzeigt (Zoom, scrollX/Y, Viewport in px und Tiles, Maus-World/Screen/Tile) - Jeden Zoom-Event als JSON in `game-test.log` schreibt (via Vite-Middleware) - Einen direkten Vergleich zwischen Phaser-Default-Zoom und Zoom-to-Mouse ermöglicht (Tab zum Wechseln) ### Befund aus den Logs `scrollX_delta` ist bei jedem Zoom-Event **0** — Phaser verändert den Scroll nie. Visuell bleibt aber der Mittelpunkt stabil, was bedeutet: Phaser zoomt vom **Screenzentrumm**, nicht von der oberen linken Ecke. Die korrekte Weltkoordinate unter einem Screenpunkt ist: ``` worldX = scrollX + screenWidth/2 + (screenX - screenWidth/2) / zoom ``` Daraus folgt die Scroll-Korrektur für Zoom-to-Mouse: ``` scrollX += (mouseX - screenWidth/2) * (1/zoomBefore - 1/zoomAfter) scrollY += (mouseY - screenHeight/2) * (1/zoomBefore - 1/zoomAfter) ``` ### Umgesetzte Änderungen - **`CameraSystem.ts`**: Zoom-to-Mouse mit obiger Formel, `getCenterWorld()` korrigiert, JSDoc auf allen Methoden - **`src/test/`**: Test-Infrastruktur bleibt bestehen für künftige Kamera-Analysen - **PR #10** enthält alle Commits
tekki closed this issue 2026-03-21 14:06:45 +00:00
claude added
status: done
and removed
status: review
labels 2026-03-21 17:44:31 +00:00
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: tekki/nissefolk#5
No description provided.