From e0034bafe02338af1129adccb185d9cfceefdf5b Mon Sep 17 00:00:00 2001 From: "Z. Cliffe Schreuders" Date: Sun, 9 Nov 2025 20:56:10 +0000 Subject: [PATCH] feat(npc): Add logging for patrol movement and animation setup --- js/systems/npc-behavior.js | 10 ++++++--- js/systems/npc-sprites.js | 42 ++++++++++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/js/systems/npc-behavior.js b/js/systems/npc-behavior.js index 38bd7df..183452b 100644 --- a/js/systems/npc-behavior.js +++ b/js/systems/npc-behavior.js @@ -398,6 +398,7 @@ class NPCBehavior { // Update direction and animation this.direction = this.calculateDirection(dx, dy); + console.log(`🚶 [${this.npcId}] Patrol moving - direction: ${this.direction}, velocity: (${velocityX.toFixed(0)}, ${velocityY.toFixed(0)})`); this.playAnimation('walk', this.direction); this.isMoving = true; } @@ -502,17 +503,20 @@ class NPCBehavior { // Only change animation if different if (this.lastAnimationKey !== animKey) { - if (this.sprite.anims && this.sprite.anims.exists(animKey)) { + // Use scene.anims to check if animation exists in the global animation manager + if (this.scene?.anims?.exists(animKey)) { this.sprite.play(animKey, true); this.lastAnimationKey = animKey; } else { // Fallback: use idle animation if walk doesn't exist if (state === 'walk') { const idleKey = `npc-${this.npcId}-idle-${animDirection}`; - if (this.sprite.anims && this.sprite.anims.exists(idleKey)) { - console.warn(`āš ļø Walk animation missing for ${this.npcId}-${animDirection}, using idle`); + if (this.scene?.anims?.exists(idleKey)) { this.sprite.play(idleKey, true); this.lastAnimationKey = idleKey; + console.warn(`āš ļø [${this.npcId}] Walk animation missing, using idle: ${idleKey}`); + } else { + console.error(`āŒ [${this.npcId}] BOTH animations missing! Walk: ${animKey}, Idle: ${idleKey}`); } } } diff --git a/js/systems/npc-sprites.js b/js/systems/npc-sprites.js index cb54145..4c6b157 100644 --- a/js/systems/npc-sprites.js +++ b/js/systems/npc-sprites.js @@ -56,10 +56,13 @@ export function createNPCSprite(scene, npc, roomData) { // Set up animations setupNPCAnimations(scene, sprite, spriteSheet, config, npc.id); - // Start idle animation + // Start idle animation (default facing down) const idleAnimKey = `npc-${npc.id}-idle`; if (sprite.anims.exists(idleAnimKey)) { sprite.play(idleAnimKey, true); + console.log(`ā–¶ļø [${npc.id}] Playing initial idle animation: ${idleAnimKey}`); + } else { + console.warn(`āš ļø [${npc.id}] Idle animation not found: ${idleAnimKey}`); } // Set depth (same system as player: bottomY + 0.5) @@ -130,6 +133,7 @@ export function calculateNPCWorldPosition(npc, roomData) { * @param {string} npcId - NPC identifier for animation key naming */ export function setupNPCAnimations(scene, sprite, spriteSheet, config, npcId) { + console.log(`\nšŸŽØ Setting up animations for NPC: ${npcId} (spriteSheet: ${spriteSheet})`); const animPrefix = config.animPrefix || 'idle'; // ===== IDLE ANIMATIONS (8 directions) ===== @@ -195,25 +199,37 @@ export function setupNPCAnimations(scene, sprite, spriteSheet, config, npcId) { // ===== WALK ANIMATIONS (8 directions) ===== // Walk animations for 5 base directions (left uses right with flipX) + // Frame layout (standard hacker spritesheet 64x64): + // Row 0 (right): frames 0-4 + // Row 1 (down): frames 5-9 + // Row 2 (up): frames 10-14 + // Row 3 (up-right): frames 15-19 + // Row 4 (down-right): frames 20-24 const walkAnimations = [ - { dir: 'right', frames: [1, 2, 3, 4] }, - { dir: 'down', frames: [6, 7, 8, 9] }, - { dir: 'up', frames: [11, 12, 13, 14] }, - { dir: 'up-right', frames: [16, 17, 18, 19] }, - { dir: 'down-right', frames: [21, 22, 23, 24] } + { dir: 'right', start: 1, end: 4 }, + { dir: 'down', start: 6, end: 9 }, + { dir: 'up', start: 11, end: 14 }, + { dir: 'up-right', start: 16, end: 19 }, + { dir: 'down-right', start: 21, end: 24 } ]; walkAnimations.forEach(anim => { const animKey = `npc-${npcId}-walk-${anim.dir}`; if (!scene.anims.exists(animKey)) { + const frames = scene.anims.generateFrameNumbers(spriteSheet, { + start: anim.start, + end: anim.end + }); + console.log(` šŸ“‹ Walk ${anim.dir}: frames ${anim.start}-${anim.end}, generated ${frames.length} frames`); scene.anims.create({ key: animKey, - frames: scene.anims.generateFrameNumbers(spriteSheet, { - frames: anim.frames - }), + frames: frames, frameRate: 8, repeat: -1 }); + console.log(`āœ… Created walk animation: ${animKey}`); + } else { + console.log(`āš ļø Walk animation already exists: ${animKey}`); } }); @@ -239,6 +255,12 @@ export function setupNPCAnimations(scene, sprite, spriteSheet, config, npcId) { } }); + console.log(`šŸ“Š Walk animations summary for ${npcId}:`); + ['right', 'down', 'up', 'up-right', 'down-right', 'left', 'up-left', 'down-left'].forEach(dir => { + const key = `npc-${npcId}-walk-${dir}`; + console.log(` ${dir}: ${scene.anims.exists(key) ? 'āœ…' : 'āŒ'} ${key}`); + }); + // ===== OPTIONAL ANIMATIONS ===== // Optional: Greeting animation (wave or nod) if (config.greetFrameStart !== undefined && config.greetFrameEnd !== undefined) { @@ -269,6 +291,8 @@ export function setupNPCAnimations(scene, sprite, spriteSheet, config, npcId) { }); } } + + console.log(`āœ… Animation setup complete for ${npcId}\n`); } /**