Add zoom and drag to move camera

This commit is contained in:
Peter Stockings
2026-01-05 22:44:04 +11:00
parent d9da9f69a5
commit 7888f375e1
2 changed files with 67 additions and 1 deletions

View File

@@ -33,6 +33,7 @@ export class GameScene extends Phaser.Scene {
private playerPath: Vec2[] = [];
private awaitingPlayer = false;
private followPlayer = true;
// Sub-systems
private dungeonRenderer!: DungeonRenderer;
@@ -144,8 +145,66 @@ export class GameScene extends Phaser.Scene {
});
// Zoom Control
this.input.on(
"wheel",
(
_pointer: Phaser.Input.Pointer,
_gameObjects: any,
_deltaX: number,
deltaY: number,
_deltaZ: number
) => {
if (this.isMenuOpen || this.isInventoryOpen || this.dungeonRenderer.isMinimapVisible()) return;
const zoomDir = deltaY > 0 ? -1 : 1;
const newZoom = Phaser.Math.Clamp(
this.cameras.main.zoom + zoomDir * GAME_CONFIG.rendering.zoomStep,
GAME_CONFIG.rendering.minZoom,
GAME_CONFIG.rendering.maxZoom
);
this.cameras.main.setZoom(newZoom);
}
);
// Disable context menu for right-click panning
this.input.mouse?.disableContextMenu();
// Camera Panning
this.input.on("pointermove", (p: Phaser.Input.Pointer) => {
if (!p.isDown) return;
if (this.isMenuOpen || this.isInventoryOpen || this.dungeonRenderer.isMinimapVisible()) return;
// Pan with Middle Click or Right Click
// Note: p.button is not always reliable in move events for holding,
// so we use specific button down checks or the shift key modifier.
const isRightDrag = p.rightButtonDown();
const isMiddleDrag = p.middleButtonDown();
const isShiftDrag = p.isDown && p.event.shiftKey;
if (isRightDrag || isMiddleDrag || isShiftDrag) {
const { x, y } = p.position;
const { x: prevX, y: prevY } = p.prevPosition;
const dx = (x - prevX) / this.cameras.main.zoom;
const dy = (y - prevY) / this.cameras.main.zoom;
this.cameras.main.scrollX -= dx;
this.cameras.main.scrollY -= dy;
this.followPlayer = false;
}
});
// Mouse click -> compute path (only during player turn, and not while menu/minimap is open)
this.input.on("pointerdown", (p: Phaser.Input.Pointer) => {
// Only allow Left Click (0) for movement
if (p.button !== 0) return;
this.followPlayer = true;
if (!this.awaitingPlayer) return;
if (this.isMenuOpen || this.isInventoryOpen || this.dungeonRenderer.isMinimapVisible()) return;
@@ -258,6 +317,7 @@ export class GameScene extends Phaser.Scene {
private commitPlayerAction(action: Action) {
this.awaitingPlayer = false;
this.followPlayer = true;
const playerEvents = applyAction(this.world, this.playerId, action, this.entityManager);
const enemyStep = stepUntilPlayerTurn(this.world, this.playerId, this.entityManager);
@@ -328,13 +388,16 @@ export class GameScene extends Phaser.Scene {
}
this.dungeonRenderer.computeFov(this.playerId);
this.centerCameraOnPlayer();
if (this.followPlayer) {
this.centerCameraOnPlayer();
}
this.dungeonRenderer.render(this.playerPath);
this.emitUIUpdate();
}
private loadFloor(floor: number) {
this.floorIndex = floor;
this.followPlayer = true;
const { world, playerId } = generateWorld(floor, this.runState);
this.world = world;