From 5495e15dcff06c48d65727298494782f9d20e0b7 Mon Sep 17 00:00:00 2001 From: Admin Date: Mon, 21 Sep 2026 23:37:49 +0000 Subject: [PATCH] Use press-and-hold room selection for elevator travel --- src/main.js | 125 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 118 insertions(+), 7 deletions(-) diff --git a/src/main.js b/src/main.js index 98be623..fb01a12 100644 --- a/src/main.js +++ b/src/main.js @@ -48,6 +48,8 @@ const FLOOR_COUNT = 5 const PLAYER_DRAG_FOLLOW = 0.18 const PLAYER_DRAG_OFFSET_Y = 42 +const ROOM_HOLD_MS = 520 +const ROOM_HOLD_MOVE_TOLERANCE = 18 const PLAYER_STATE = { IDLE: 'idle', @@ -186,6 +188,11 @@ class HouseScene extends Phaser.Scene { this.playerAnimClock = 0 this.journeyActive = false this.saveTimer = null + this.roomZones = [] + this.roomHoldTimer = null + this.roomHoldRoom = null + this.roomHoldStart = null + this.roomHoldPointerId = null } preload() { @@ -216,6 +223,7 @@ class HouseScene extends Phaser.Scene { this.buildElevator() this.buildUi() this.spawnPlayer() + this.buildRoomHoldTargets() this.bindInput() this.events.once(Phaser.Scenes.Events.SHUTDOWN, () => this.persist()) @@ -265,7 +273,7 @@ class HouseScene extends Phaser.Scene { } } - this.add.text(WIDTH / 2, 48, 'Drag within a room to walk • drag into another room to ride the lift', { + this.add.text(WIDTH / 2, 48, 'Drag her to walk • press & hold a room to ride the lift', { fontFamily: 'Arial Rounded MT Bold, ui-rounded, sans-serif', fontSize: '15px', color: '#6d4c61' @@ -357,6 +365,112 @@ class HouseScene extends Phaser.Scene { this.updateStatus(room) } + buildRoomHoldTargets() { + this.roomHoldGraphics = this.add.graphics().setDepth(120) + + this.roomZones = ROOMS.map((room) => { + const zone = this.add.zone( + room.x + room.width / 2, + room.y + room.height / 2, + room.width, + room.height + ) + .setDepth(3) + .setData('roomId', room.id) + .setInteractive() + + zone.on('pointerdown', (pointer) => { + this.startRoomHold(room, pointer) + }) + + zone.on('pointermove', (pointer) => { + if ( + this.roomHoldPointerId !== pointer.id || + !this.roomHoldStart + ) return + + const moved = Phaser.Math.Distance.Between( + this.roomHoldStart.x, + this.roomHoldStart.y, + pointer.x, + pointer.y + ) + + if (moved > ROOM_HOLD_MOVE_TOLERANCE) { + this.cancelRoomHold() + } + }) + + zone.on('pointerup', () => this.cancelRoomHold()) + zone.on('pointerout', () => this.cancelRoomHold()) + + return zone + }) + + this.input.on('pointerup', (pointer) => { + if (pointer.id === this.roomHoldPointerId) { + this.cancelRoomHold() + } + }) + } + + startRoomHold(room, pointer) { + if ( + this.journeyActive || + room.id === this.state.player.roomId + ) return + + this.cancelRoomHold(false) + + this.roomHoldRoom = room + this.roomHoldPointerId = pointer.id + this.roomHoldStart = { x: pointer.x, y: pointer.y } + + this.roomHoldGraphics.clear() + this.roomHoldGraphics.lineStyle(6, 0xf28fb3, 1) + this.roomHoldGraphics.strokeRoundedRect( + room.x + 3, + room.y + 3, + room.width - 6, + room.height - 6, + 12 + ) + + this.updateStatus(this.currentRoom(), 'Hold for ' + room.name + '…') + + this.roomHoldTimer = this.time.delayedCall(ROOM_HOLD_MS, () => { + if ( + this.roomHoldRoom?.id !== room.id || + this.journeyActive + ) return + + this.roomHoldTimer = null + this.roomHoldRoom = null + this.roomHoldStart = null + this.roomHoldPointerId = null + this.roomHoldGraphics.clear() + + this.beginElevatorJourney(room) + }) + } + + cancelRoomHold(resetStatus = true) { + if (this.roomHoldTimer) { + this.roomHoldTimer.remove(false) + this.roomHoldTimer = null + } + + this.roomHoldRoom = null + this.roomHoldStart = null + this.roomHoldPointerId = null + + this.roomHoldGraphics?.clear() + + if (resetStatus && !this.journeyActive && this.statusText) { + this.updateStatus(this.currentRoom()) + } + } + bindInput() { this.cursors = this.input.keyboard.createCursorKeys() this.keys = this.input.keyboard.addKeys('W,A,S,D') @@ -381,11 +495,8 @@ class HouseScene extends Phaser.Scene { const targetRoom = this.getRoomAt(pointer.x, pointer.y) const currentRoom = this.currentRoom() - if (targetRoom && targetRoom.id !== currentRoom.id) { - this.beginElevatorJourney(targetRoom) - return - } - + // Dragging the character is movement-only. Crossing into another + // room never triggers travel; room changes require a deliberate hold. if (!targetRoom || targetRoom.id !== currentRoom.id) return const targetX = Phaser.Math.Clamp( @@ -796,7 +907,7 @@ const game = new Phaser.Game({ }) window.__DOLLHOUSE__ = { - version: '0.4.0', + version: '0.4.1', game, async resetAll() { await clearGameState()