mirror of
https://github.com/cliffe/BreakEscape.git
synced 2026-02-21 11:18:08 +00:00
- 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.
167 lines
5.0 KiB
Markdown
167 lines
5.0 KiB
Markdown
# 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
|