Files
BreakEscape/docs/FRAME_NUMBER_FIX.md

167 lines
5.0 KiB
Markdown
Raw Permalink Normal View History

# Frame Number Fix - Atlas vs Legacy Sprites
## Problem
Error when creating NPCs with atlas sprites:
```
Texture "male_spy" has no frame "20"
```
## Root Cause
The NPC sprite creation was using a hardcoded frame number (20) which works for legacy 64x64 sprites but doesn't exist in atlas sprites.
### Legacy Sprites (64x64)
- Use **numbered frames**: 0, 1, 2, 3, ..., 20, 21, etc.
- Frame 20 is the idle down-right frame
- Frames are generated from a regular grid layout
### Atlas Sprites (80x80)
- Use **named frames**: `"breathing-idle_south_frame_000"`, `"walk_east_frame_001"`, etc.
- Frame numbers don't exist - only frame names
- Frames are defined in the JSON atlas
## Solution
Detect sprite type and use appropriate initial frame:
### Implementation
```javascript
// Check if this is an atlas sprite
const isAtlas = scene.cache.json.exists(spriteSheet);
// Determine initial frame
let initialFrame;
if (isAtlas) {
// Atlas sprite - use first frame from breathing-idle_south animation
const atlasData = scene.cache.json.get(spriteSheet);
if (atlasData?.animations?.['breathing-idle_south']) {
initialFrame = atlasData.animations['breathing-idle_south'][0];
} else {
// Fallback to first frame in atlas
initialFrame = 0;
}
} else {
// Legacy sprite - use configured frame or default to 20
initialFrame = config.idleFrame || 20;
}
// Create sprite with correct frame
const sprite = scene.add.sprite(worldPos.x, worldPos.y, spriteSheet, initialFrame);
```
## Frame Selection Logic
### For Atlas Sprites
1. **First choice**: First frame of `breathing-idle_south` animation (facing down)
- Example: `"breathing-idle_south_frame_000"`
- This ensures the character starts in a natural idle pose facing downward
2. **Fallback**: Frame 0 (first frame in the atlas)
- Used if breathing-idle animation doesn't exist
### For Legacy Sprites
1. **First choice**: `config.idleFrame` (if specified in scenario)
2. **Fallback**: Frame 20 (down-right idle frame)
## Why Frame 20 for Legacy?
Legacy sprites use this frame layout:
```
Row 0 (frames 0-4): Right walk
Row 1 (frames 5-9): Down walk
Row 2 (frames 10-14): Up walk
Row 3 (frames 15-19): Up-right walk
Row 4 (frames 20-24): Down-right walk ← Frame 20 is first frame of this row
```
Frame 20 is the idle down-right pose, which is a good default starting position.
## Why breathing-idle_south for Atlas?
Atlas sprites have structured animation names:
```
breathing-idle_south → Idle breathing facing down
breathing-idle_east → Idle breathing facing right
walk_north → Walking upward
```
`breathing-idle_south` (down) is the most natural default direction for a character to face when first appearing.
## Files Modified
**File**: `public/break_escape/js/systems/npc-sprites.js`
**Function**: `createNPCSprite()`
**Lines**: 25-60
## Testing
Verified with:
- ✅ Atlas sprites (female_hacker_hood, male_spy, etc.) - No frame errors
- ✅ Legacy sprites (hacker, hacker-red) - Still works as before
- ✅ NPCs spawn with correct initial pose
- ✅ Animations play correctly after spawn
- ✅ Console logging shows correct frame selection
## Console Output
```
🎭 NPC briefing_cutscene created with atlas sprite (male_spy), initial frame: breathing-idle_south_frame_000
🎭 NPC sarah_martinez created with atlas sprite (female_office_worker), initial frame: breathing-idle_south_frame_000
🎭 NPC old_npc created with legacy sprite (hacker), initial frame: 20
```
## Error Prevention
### Before Fix
```javascript
const idleFrame = config.idleFrame || 20; // ❌ Always uses number
const sprite = scene.add.sprite(x, y, spriteSheet, idleFrame);
// ERROR: Texture "male_spy" has no frame "20"
```
### After Fix
```javascript
const isAtlas = scene.cache.json.exists(spriteSheet);
let initialFrame;
if (isAtlas) {
// Use named frame from atlas
initialFrame = atlasData.animations['breathing-idle_south'][0];
} else {
// Use numbered frame
initialFrame = config.idleFrame || 20;
}
const sprite = scene.add.sprite(x, y, spriteSheet, initialFrame);
// ✅ Works for both atlas and legacy sprites
```
## Related Issues
This is part of a series of fixes for atlas sprite support:
1. ✅ 8-directional animation support
2. ✅ Collision box adjustment for 80x80 sprites
3. ✅ NPC animation stuck on single frame
4. ✅ Initial frame selection (this fix)
## Future Improvements
- [ ] Allow specifying initial direction in scenario config
- [ ] Support custom initial frames per NPC
- [ ] Add visual indicator of sprite type in debug mode
- [ ] Validate frame exists before creating sprite
## Backward Compatibility
**Fully backward compatible**
- Legacy sprites continue to use frame 20 (or configured frame)
- Atlas sprites use appropriate named frames
- No changes needed to existing scenarios
- Automatic detection ensures correct behavior
## Performance
- **No performance impact**: Frame selection happens once at sprite creation
- **Minimal overhead**: Single JSON cache check to determine sprite type
- **Efficient**: Uses first frame from animation data without searching