diff --git a/src/main.js b/src/main.js index 65abed3..ceab269 100644 --- a/src/main.js +++ b/src/main.js @@ -43,7 +43,21 @@ const HOUSE_BOUNDS = { } const STAIRS_X = 675 -const PLAYER_CROP = { x: 17, y: 128, w: 63, h: 102 } +const PLAYER_IDLE_CROPS = [ + { x: 145, y: 12, w: 199, h: 310 }, + { x: 344, y: 12, w: 196, h: 310 }, + { x: 538, y: 11, w: 197, h: 311 }, + { x: 736, y: 11, w: 197, h: 311 } +] + +const PLAYER_WALK_CROPS = [ + { x: 8, y: 324, w: 176, h: 294 }, + { x: 183, y: 323, w: 181, h: 295 }, + { x: 364, y: 323, w: 177, h: 294 }, + { x: 543, y: 323, w: 179, h: 295 }, + { x: 723, y: 324, w: 178, h: 294 }, + { x: 899, y: 324, w: 176, h: 294 } +] const FURNITURE_CROPS = { bed: { x: 28, y: 68, w: 392, h: 425 }, @@ -138,16 +152,24 @@ class HouseScene extends Phaser.Scene { this.itemSprites = [] this.addIndex = 0 this.stairCooldown = 0 + this.playerAnimMode = 'idle' + this.playerAnimFrame = 0 + this.playerAnimClock = 0 } preload() { this.load.image('house', '/assets/open-dollhouse.png') this.load.image('furniture-sheet', '/assets/furniture-sheet.png') - this.load.image('production', '/assets/production-sheet.png') + this.load.image('character-sheet', '/assets/character-sheet.png') } async create() { - cropTexture(this, 'production', 'player', PLAYER_CROP) + PLAYER_IDLE_CROPS.forEach((rect, index) => { + cropTexture(this, 'character-sheet', 'player-idle-' + index, rect) + }) + PLAYER_WALK_CROPS.forEach((rect, index) => { + cropTexture(this, 'character-sheet', 'player-walk-' + index, rect) + }) Object.entries(FURNITURE_CROPS).forEach(([key, rect]) => { cropTexture(this, 'furniture-sheet', 'furniture-' + key, rect) }) @@ -297,12 +319,37 @@ class HouseScene extends Phaser.Scene { spawnPlayer() { this.player?.destroy() - this.player = this.add.image(this.state.player.x, this.state.player.y, 'player') + this.playerAnimMode = 'idle' + this.playerAnimFrame = 0 + this.playerAnimClock = 0 + this.player = this.add.image(this.state.player.x, this.state.player.y, 'player-idle-0') .setOrigin(0.5, 1) - .setScale(0.95) + .setScale(0.36) .setDepth(Math.floor(this.state.player.y) + 40) } + animatePlayer(mode, delta) { + if (!this.player) return + + const frameCount = mode === 'walk' ? PLAYER_WALK_CROPS.length : PLAYER_IDLE_CROPS.length + const frameMs = mode === 'walk' ? 105 : 420 + + if (this.playerAnimMode !== mode) { + this.playerAnimMode = mode + this.playerAnimFrame = 0 + this.playerAnimClock = 0 + this.player.setTexture('player-' + mode + '-0') + return + } + + this.playerAnimClock += delta + if (this.playerAnimClock < frameMs) return + + this.playerAnimClock %= frameMs + this.playerAnimFrame = (this.playerAnimFrame + 1) % frameCount + this.player.setTexture('player-' + mode + '-' + this.playerAnimFrame) + } + updateUi() { this.modeButton.text.setText(this.decorateMode ? '✓ Done decorating' : '✨ Decorate') const nextType = FURNITURE_ORDER[this.addIndex % FURNITURE_ORDER.length] @@ -418,7 +465,9 @@ class HouseScene extends Phaser.Scene { let dx = Number(right) - Number(left) let dy = Number(down) - Number(up) - if (dx === 0 && dy === 0) return + const isMoving = dx !== 0 || dy !== 0 + this.animatePlayer(isMoving ? 'walk' : 'idle', delta) + if (!isMoving) return const length = Math.hypot(dx, dy) || 1 dx /= length @@ -438,7 +487,7 @@ class HouseScene extends Phaser.Scene { if (Math.abs(dx) > 0.05) this.player.setFlipX(dx < 0) const depthT = Phaser.Math.Clamp((this.player.y - bounds.minY) / (bounds.maxY - bounds.minY), 0, 1) - this.player.setScale(Phaser.Math.Linear(0.84, 1.02, depthT)) + this.player.setScale(Phaser.Math.Linear(0.32, 0.39, depthT)) this.player.setDepth(Math.floor(this.player.y) + 40) this.capturePlayer()