Files
BreakEscape/docs/BREATHING_ANIMATIONS.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

268 lines
7.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Breathing Idle Animations
## Overview
The PixelLab atlas sprites include "breathing-idle" animations that provide a subtle breathing effect when characters are standing still. These animations have been integrated into the game's idle state for both player and NPCs.
## Animation Details
### Frame Count
- **Breathing-idle**: 4 frames per direction
- **Directions**: All 8 directions (up, down, left, right, and 4 diagonals)
- **Total frames per character**: 32 frames (4 frames × 8 directions)
### Frame Rate Configuration
The breathing animation frame rate has been optimized for a natural, subtle breathing effect:
| Animation Type | Frame Rate | Cycle Duration | Notes |
|---------------|-----------|----------------|-------|
| **Idle (Breathing)** | 6 fps | ~0.67 seconds | Slower for natural breathing |
| **Walk** | 10 fps | ~0.6 seconds | Faster for smooth walking |
| **Attack** | 8 fps | Variable | Standard action speed |
### Why 6 fps for Breathing?
With 4 frames at 6 fps:
- One complete breathing cycle = 4 frames ÷ 6 fps = **0.67 seconds**
- ~90 breaths per minute (realistic resting rate)
- Subtle and natural-looking
- Not distracting during gameplay
## Implementation
### Atlas Mapping
The system automatically maps PixelLab animations to game animations:
```javascript
// Atlas format: "breathing-idle_east"
// Game format: "idle-right" (player) or "npc-{id}-idle-right" (NPCs)
const animTypeMap = {
'breathing-idle': 'idle', // ← Breathing animation mapped to idle
'walk': 'walk',
'cross-punch': 'attack',
'lead-jab': 'jab',
'falling-back-death': 'death'
};
```
### Player System
**File**: `js/core/player.js`
```javascript
function createAtlasPlayerAnimations(spriteSheet) {
const playerConfig = window.scenarioConfig?.player?.spriteConfig || {};
const idleFrameRate = playerConfig.idleFrameRate || 6; // Breathing rate
// Create idle animations from breathing-idle atlas data
for (const [atlasAnimKey, frames] of Object.entries(atlasData.animations)) {
if (atlasType === 'breathing-idle') {
const animKey = `idle-${direction}`;
gameRef.anims.create({
key: animKey,
frames: frames.map(frameName => ({ key: spriteSheet, frame: frameName })),
frameRate: idleFrameRate, // 6 fps
repeat: -1 // Loop forever
});
}
}
}
```
### NPC System
**File**: `js/systems/npc-sprites.js`
```javascript
function setupAtlasAnimations(scene, sprite, spriteSheet, config, npcId) {
// Default frame rate: 6 fps for idle (breathing)
let frameRate = config.idleFrameRate || 6;
// Create NPC idle animations from breathing-idle
const animKey = `npc-${npcId}-idle-${direction}`;
scene.anims.create({
key: animKey,
frames: frames.map(frameName => ({ key: spriteSheet, frame: frameName })),
frameRate: frameRate,
repeat: -1
});
}
```
## Configuration
### Scenario Configuration
Set frame rates in `scenario.json.erb`:
```json
{
"player": {
"spriteSheet": "female_hacker_hood",
"spriteConfig": {
"idleFrameRate": 6, // Breathing animation speed
"walkFrameRate": 10 // Walking animation speed
}
},
"npcs": [
{
"id": "sarah",
"spriteSheet": "female_office_worker",
"spriteConfig": {
"idleFrameRate": 6, // Breathing animation speed
"walkFrameRate": 10
}
}
]
}
```
### Adjusting Breathing Speed
To adjust the breathing effect:
**Slower breathing** (calmer, more relaxed):
```json
"idleFrameRate": 4 // 1 second per cycle, ~60 bpm
```
**Normal breathing** (default):
```json
"idleFrameRate": 6 // 0.67 seconds per cycle, ~90 bpm
```
**Faster breathing** (active, alert):
```json
"idleFrameRate": 8 // 0.5 seconds per cycle, ~120 bpm
```
## Animation States
### When Breathing Animation Plays
The breathing-idle animation plays in these states:
1. **Standing Still**: Character not moving
2. **Face Player**: NPC facing the player but not moving
3. **Dwell Time**: NPC waiting at a patrol waypoint
4. **Personal Space**: NPC adjusting distance from player
5. **Attack Range**: Hostile NPC in range but between attacks
### When Other Animations Play
- **Walk**: Moving in any direction
- **Attack**: Performing combat actions
- **Death**: Character defeated
- **Hit**: Taking damage
## Visual Effect
The breathing animation provides:
-**Subtle movement** when idle
-**Lifelike appearance** for characters
-**Visual feedback** that character is active
-**Polish** and professional game feel
### Before (Static Idle)
- Single frame
- Completely still
- Lifeless appearance
### After (Breathing Idle)
- 4-frame cycle
- Gentle animation
- Natural, living characters
## Performance
The breathing animation has minimal performance impact:
- **Memory**: Same as single-frame idle (uses same texture atlas)
- **CPU**: Negligible (just frame switching)
- **GPU**: No additional draw calls (same sprite)
## Compatibility
### Atlas Sprites (New)
- ✅ Full 4-frame breathing animation
- ✅ All 8 directions
- ✅ Configurable frame rate
### Legacy Sprites (Old)
- ⚠️ Single frame idle (no breathing)
- ⚠️ 5 directions with flipping
- Still fully supported
## Troubleshooting
### Breathing Too Fast
**Symptom**: Characters appear to be hyperventilating
**Solution**: Decrease `idleFrameRate` to 4-5 fps
### Breathing Too Slow
**Symptom**: Animation feels sluggish or barely noticeable
**Solution**: Increase `idleFrameRate` to 7-8 fps
### No Breathing Animation
**Symptom**: Characters completely still when idle
**Solution**:
1. Verify sprite is using atlas format (not legacy)
2. Check that `breathing-idle_*` animations exist in JSON
3. Confirm `idleFrameRate` is set in config
4. Check console for animation creation logs
### Animation Not Looping
**Symptom**: Breathing stops after one cycle
**Solution**: Verify `repeat: -1` is set in animation creation
## Future Enhancements
Potential improvements:
- [ ] Variable breathing rate based on character state (calm vs alert)
- [ ] Synchronized breathing for multiple characters
- [ ] Different breathing patterns for different character types
- [ ] Heavy breathing after running/combat
- [ ] Breathing affected by player proximity (nervousness)
## Technical Notes
### Animation Format
Atlas JSON structure:
```json
{
"animations": {
"breathing-idle_east": [
"breathing-idle_east_frame_000",
"breathing-idle_east_frame_001",
"breathing-idle_east_frame_002",
"breathing-idle_east_frame_003"
]
}
}
```
Game animation structure:
```javascript
{
key: 'idle-right',
frames: [
{ key: 'female_hacker_hood', frame: 'breathing-idle_east_frame_000' },
{ key: 'female_hacker_hood', frame: 'breathing-idle_east_frame_001' },
{ key: 'female_hacker_hood', frame: 'breathing-idle_east_frame_002' },
{ key: 'female_hacker_hood', frame: 'breathing-idle_east_frame_003' }
],
frameRate: 6,
repeat: -1
}
```
### Performance Metrics
- **Frame switches per second**: 6 (at 6 fps)
- **Memory per character**: ~4KB for breathing frames (shared in atlas)
- **CPU overhead**: <0.1% (Phaser handles animation efficiently)
- **Recommended max characters with breathing**: 50+ (no practical limit)