Files
BreakEscape/docs/PLAYER_SPRITE_CONFIG_FIX.md
Z. Cliffe Schreuders fb6e9b603c Enhance character sprite loading and animation handling
- Updated the game to support new character sprite atlases for both male and female characters, allowing for a wider variety of NPC designs.
- Improved player sprite initialization to dynamically select between atlas-based and legacy sprites, enhancing flexibility in character representation.
- Refined collision box settings based on sprite type, ensuring accurate physics interactions for both atlas (80x80) and legacy (64x64) sprites.
- Enhanced NPC behavior to utilize atlas animations, allowing for more fluid and diverse animations based on available frames.

Files modified:
- game.js: Added new character atlases and updated sprite loading logic.
- player.js: Improved player sprite handling and collision box adjustments.
- npc-behavior.js: Updated animation handling for NPCs to support atlas-based animations.
- npc-sprites.js: Enhanced NPC sprite creation to accommodate atlas detection and initial frame selection.
- scenario.json.erb: Updated player and NPC configurations to utilize new sprite sheets and animation settings.
- m01_npc_sarah.ink: Revised dialogue options to include new interactions related to NPCs.
2026-02-11 00:18:21 +00:00

5.6 KiB

Player Sprite Configuration Fix

Problem

The player sprite was not loading from the scenario configuration and was always defaulting to 'hacker', even when a different sprite was configured in scenario.json.erb.

Root Cause

The code was looking for window.scenarioConfig but the actual global variable is window.gameScenario.

Wrong Variable Name

Code was checking:

const playerSprite = window.scenarioConfig?.player?.spriteSheet || 'hacker';
//                          ^^^^^^^^^^^^^ WRONG

Should be:

const playerSprite = window.gameScenario?.player?.spriteSheet || 'hacker';
//                          ^^^^^^^^^^^^ CORRECT

Where gameScenario is Set

In game.js create function:

if (!window.gameScenario) {
    window.gameScenario = this.cache.json.get('gameScenarioJSON');
}

The scenario is loaded from the JSON file and stored in window.gameScenario, not window.scenarioConfig.

Files Fixed

1. Player System (js/core/player.js)

Fixed 3 locations:

A. Player Creation:

// Before
const playerSprite = window.scenarioConfig?.player?.spriteSheet || 'hacker';

// After
const playerSprite = window.gameScenario?.player?.spriteSheet || 'hacker';
console.log(`🎮 Loading player sprite: ${playerSprite} (from ${window.gameScenario?.player ? 'scenario' : 'default'})`);

B. Animation Creation:

// Before
const playerSprite = window.scenarioConfig?.player?.spriteSheet || 'hacker';

// After
const playerSprite = window.gameScenario?.player?.spriteSheet || 'hacker';

C. Frame Rate Config:

// Before
const playerConfig = window.scenarioConfig?.player?.spriteConfig || {};

// After
const playerConfig = window.gameScenario?.player?.spriteConfig || {};

2. Game System (js/core/game.js)

Character Registry Registration:

// Before
const playerData = {
    id: 'player',
    displayName: window.gameState?.playerName || 'Agent 0x00',
    spriteSheet: 'hacker',  // ← HARDCODED
    spriteTalk: 'assets/characters/hacker-talk.png',  // ← HARDCODED
    metadata: {}
};

// After
const playerData = {
    id: 'player',
    displayName: window.gameState?.playerName || window.gameScenario?.player?.displayName || 'Agent 0x00',
    spriteSheet: window.gameScenario?.player?.spriteSheet || 'hacker',
    spriteTalk: window.gameScenario?.player?.spriteTalk || 'assets/characters/hacker-talk.png',
    metadata: {}
};

Impact

Before Fix

  • Player always used 'hacker' sprite (64x64 legacy)
  • Scenario configuration ignored
  • Could not use new atlas sprites for player
  • spriteTalk always defaulted to hacker-talk.png
  • displayName always defaulted to 'Agent 0x00'

After Fix

  • Player uses configured sprite from scenario
  • Can use atlas sprites (80x80 with 8 directions)
  • spriteTalk loaded from scenario
  • displayName loaded from scenario
  • Frame rates configured per scenario
  • Falls back to 'hacker' if not configured

Scenario Configuration

Now this works correctly:

{
  "player": {
    "id": "player",
    "displayName": "Agent 0x00",
    "spriteSheet": "female_hacker_hood",
    "spriteTalk": "assets/characters/hacker-talk.png",
    "spriteConfig": {
      "idleFrameRate": 6,
      "walkFrameRate": 10
    }
  }
}

Console Logging

Added debug logging to verify correct loading:

🎮 Loading player sprite: female_hacker_hood (from scenario)
🔍 Player sprite female_hacker_hood: 256 frames, first: "breathing-idle_east_frame_000", isAtlas: true
🎮 Player using atlas sprite: female_hacker_hood

If scenario not loaded:

🎮 Loading player sprite: hacker (from default)

Testing

Tested with:

  • Player configured as female_hacker_hood - Loads correctly
  • Player configured as male_hacker - Loads correctly
  • No player config - Falls back to 'hacker'
  • spriteTalk from scenario - Used in chat portraits
  • displayName from scenario - Used in UI

Global Variables Reference

For future reference, the correct global variables are:

Variable Purpose Set In Type
window.gameScenario Full scenario data game.js create() Object
window.gameState Current game state state-sync.js Object
window.player Player sprite player.js Phaser.Sprite
window.characterRegistry Character data character-registry.js Object

NOT window.scenarioConfig (doesn't exist)

This was one of several configuration issues:

  1. scenarioConfig → gameScenario (variable name)
  2. Hardcoded sprite → configured sprite
  3. Hardcoded spriteTalk → configured spriteTalk
  4. Hardcoded displayName → configured displayName

Prevention

To avoid this in the future:

  • Use consistent naming conventions
  • Document global variables
  • Add type checking/validation for scenario structure
  • Consider using a centralized config accessor

Commit Message

Fix player sprite not loading from scenario config

Player was always using 'hacker' sprite because code was looking
for window.scenarioConfig instead of window.gameScenario.

Fixed references in:
- player.js: createPlayer(), createPlayerAnimations(), createAtlasPlayerAnimations()
- game.js: Character registry registration

Now properly loads:
- spriteSheet from scenario.player.spriteSheet
- spriteTalk from scenario.player.spriteTalk
- displayName from scenario.player.displayName
- spriteConfig (frame rates) from scenario.player.spriteConfig

Falls back to 'hacker' if not configured.