From 0c9ddfef5ccc4ee448bc6d1971a260cb3bc269a3 Mon Sep 17 00:00:00 2001 From: Admin Date: Mon, 21 Sep 2026 22:57:21 +0000 Subject: [PATCH] Make character touch-drag controlled --- src/main.js | 104 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 71 insertions(+), 33 deletions(-) diff --git a/src/main.js b/src/main.js index ceab269..d01b06c 100644 --- a/src/main.js +++ b/src/main.js @@ -155,6 +155,8 @@ class HouseScene extends Phaser.Scene { this.playerAnimMode = 'idle' this.playerAnimFrame = 0 this.playerAnimClock = 0 + this.playerDragging = false + this.lastPlayerDragX = null } preload() { @@ -184,7 +186,6 @@ class HouseScene extends Phaser.Scene { .setDepth(0) this.buildUi() - this.buildControls() this.bindInput() this.spawnAllFurniture() this.spawnPlayer() @@ -233,53 +234,82 @@ class HouseScene extends Phaser.Scene { .setScrollFactor(0) .setDepth(990) - this.stairsHint = this.add.text(480, 684, 'Use the stairs on the right to change floors ↑ ↓', { + this.stairsHint = this.add.text(480, 684, 'Drag her around • use the stairs on the right to change floors', { fontFamily: 'Arial Rounded MT Bold, ui-rounded, sans-serif', fontSize: '13px', color: '#7a526b' }).setOrigin(0.5).setScrollFactor(0).setDepth(1001) } - buildControls() { - const makePad = (x, label, direction) => { - const circle = this.add.circle(x, 687, 25, 0xffffff, 0.94) - .setStrokeStyle(2, 0xd889aa) - .setInteractive() - .setScrollFactor(0) - .setDepth(1010) - - this.add.text(x, 686, label, { - fontFamily: 'Arial, sans-serif', - fontSize: '23px', - color: '#b75c83', - fontStyle: 'bold' - }).setOrigin(0.5).setScrollFactor(0).setDepth(1011) - - const off = () => { this.moveIntent[direction] = false } - circle.on('pointerdown', () => { this.moveIntent[direction] = true }) - circle.on('pointerup', off) - circle.on('pointerout', off) - } - - makePad(44, '◀', 'left') - makePad(100, '▶', 'right') - makePad(156, '▲', 'up') - makePad(212, '▼', 'down') - } - bindInput() { this.cursors = this.input.keyboard.createCursorKeys() this.keys = this.input.keyboard.addKeys('W,A,S,D') + this.input.on('dragstart', (_pointer, object) => { + if (object.getData('kind') !== 'player' || this.decorateMode) return + this.playerDragging = true + this.lastPlayerDragX = object.x + this.animatePlayer('walk', 999) + }) + this.input.on('drag', (_pointer, object, dragX, dragY) => { - if (!this.decorateMode || object.getData('kind') !== 'furniture') return + const kind = object.getData('kind') + + if (kind === 'player') { + if (this.decorateMode) return + + let floor = this.state.player.floor ?? floorFromY(object.y) + const nearStairs = dragX >= STAIRS_X + + if (nearStairs && floor === 'lower' && dragY < 475) { + floor = 'upper' + this.state.player.floor = floor + dragY = HOUSE_BOUNDS.upper.homeY + } else if (nearStairs && floor === 'upper' && dragY > 430) { + floor = 'lower' + this.state.player.floor = floor + dragY = HOUSE_BOUNDS.lower.homeY + } + + const bounds = floorBounds(floor) + const previousX = this.lastPlayerDragX ?? object.x + + object.x = Phaser.Math.Clamp(dragX, HOUSE_BOUNDS.left, HOUSE_BOUNDS.right) + object.y = Phaser.Math.Clamp(dragY, bounds.minY, bounds.maxY) + + if (Math.abs(object.x - previousX) > 1) object.setFlipX(object.x < previousX) + this.lastPlayerDragX = object.x + + const depthT = Phaser.Math.Clamp((object.y - bounds.minY) / (bounds.maxY - bounds.minY), 0, 1) + object.setScale(Phaser.Math.Linear(0.32, 0.39, depthT)) + object.setDepth(Math.floor(object.y) + 40) + + this.capturePlayer() + return + } + + if (!this.decorateMode || kind !== 'furniture') return + object.x = Phaser.Math.Clamp(dragX, HOUSE_BOUNDS.left + 28, HOUSE_BOUNDS.right - 28) object.y = Phaser.Math.Clamp(dragY, 250, HOUSE_BOUNDS.lower.maxY) object.setDepth(Math.floor(object.y)) }) this.input.on('dragend', (_pointer, object) => { - if (object.getData('kind') !== 'furniture') return + const kind = object.getData('kind') + + if (kind === 'player') { + if (this.decorateMode) return + this.playerDragging = false + this.lastPlayerDragX = null + this.animatePlayer('idle', 999) + this.capturePlayer() + this.scheduleSave() + return + } + + if (kind !== 'furniture') return + const item = this.state.items.find((entry) => entry.id === object.getData('id')) if (!item) return @@ -326,6 +356,9 @@ class HouseScene extends Phaser.Scene { .setOrigin(0.5, 1) .setScale(0.36) .setDepth(Math.floor(this.state.player.y) + 40) + .setData('kind', 'player') + .setInteractive({ cursor: 'grab' }) + this.input.setDraggable(this.player) } animatePlayer(mode, delta) { @@ -354,7 +387,7 @@ class HouseScene extends Phaser.Scene { this.modeButton.text.setText(this.decorateMode ? '✓ Done decorating' : '✨ Decorate') const nextType = FURNITURE_ORDER[this.addIndex % FURNITURE_ORDER.length] this.addButton.text.setText('+ Add ' + FURNITURE_NAMES[nextType]) - this.helpText.setText(this.decorateMode ? 'drag furniture' : 'walk & play') + this.helpText.setText(this.decorateMode ? 'drag furniture' : 'drag her to move') this.itemSprites.forEach((sprite) => { sprite.setAlpha(this.decorateMode ? 1 : 0.98) @@ -442,6 +475,11 @@ class HouseScene extends Phaser.Scene { update(_time, delta) { if (!this.player || this.decorateMode || this.tweens.isTweening(this.player)) return + if (this.playerDragging) { + this.animatePlayer('walk', delta) + return + } + this.stairCooldown = Math.max(0, this.stairCooldown - delta) const left = this.cursors.left.isDown || this.keys.A.isDown || this.moveIntent.left @@ -513,7 +551,7 @@ const game = new Phaser.Game({ }) window.__DOLLHOUSE__ = { - version: '0.2.0', + version: '0.3.0', game, async resetAll() { await clearGameState()