Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
#
# Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore
#

# Node.js
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
package-lock.json

.utmp/
/[Ll]ibrary/
/[Tt]emp/
Expand Down
112 changes: 112 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,118 @@ All notable changes to the Skeleton Crew Framework will be documented in this fi

## Version History

- **3.1.0** - Added SaveSystem, AchievementSystem, Enhanced AudioSystem, Updated dependencies
- **3.0.0** - Added Lighting, Pathfinding, Dialogue, Quest, and Behavior Tree systems
- **2.0.0** - Added Particle System, Animation System, Spatial Grid
- **1.0.0** - Initial release with core framework and example games

---

## [3.1.0] - 2024-12-29

### Added

#### 💾 SaveSystem (`framework/utils/SaveSystem.js`)
- Complete save/load system for game state persistence
- localStorage-based storage with fallback detection
- Multiple save slots (configurable, default: 3)
- Auto-save functionality with configurable intervals
- Save state serialization and deserialization
- Export/import saves for backup and sharing
- Save metadata tracking (timestamp, custom metadata)
- Storage statistics and monitoring
- **54 comprehensive unit tests**
Comment thread
MiChaelinzo marked this conversation as resolved.

**Key Features:**
- Multiple independent save slots
- Auto-save with customizable interval
- Import/export for backup
- Storage usage statistics
- Validates save slot numbers
- Graceful handling of unavailable storage

#### 🏆 AchievementSystem (`framework/systems/AchievementSystem.js`)
- Comprehensive achievement tracking system
- Multiple achievement types: simple, progress, secret, challenge
- Progress tracking with percentage calculation
- Achievement persistence using localStorage
- Callback system for unlock and progress events
- Hidden/secret achievements
- Achievement rewards system
- Statistics tracking
- **32 comprehensive unit tests**

**Achievement Types:**
- **Simple** - One-time unlock achievements
- **Progress** - Incremental progress tracking with targets
- **Secret** - Hidden achievements until unlocked
- **Challenge** - Special difficulty achievements

**Key Features:**
- Unlock notifications (customizable)
- Progress incrementation
- Achievement statistics
- Callback events (onUnlock, onProgress)
- Persistent storage with gameId
- Hidden achievements support
- Reward metadata

#### 🔊 Enhanced AudioSystem
- Audio preloading functionality (`preloadSounds`)
- Fade in/out for ambient music
- Spatial audio support (distance-based volume)
- Ambient volume control methods
- Improved error handling

**New Methods:**
- `preloadSounds(sounds)` - Batch load multiple sounds
- `fadeInAmbient(id, targetVolume, duration)` - Fade in ambient music
- `fadeOutAmbient(duration, stopAfterFade)` - Fade out ambient music
- `fadeAmbientTo(targetVolume, duration)` - Fade to new volume
- `playSpatialSound(id, sourcePos, listenerPos, maxVolume, loop)` - Distance-based audio
- `updateSpatialSound(audioObj, sourcePos, listenerPos, maxVolume)` - Update spatial audio
- `setAmbientVolume(volume)` - Set ambient volume
- `getAmbientVolume()` - Get current ambient volume

### Changed

#### Dependencies Updated
- **Jest** updated from 29.7.0 to 30.2.0
- **@jest/globals** updated from 29.7.0 to 30.2.0
- **jest-environment-jsdom** updated from 29.7.0 to 30.2.0
- **fast-check** updated from 3.23.2 to 4.5.2

All tests passing with new versions (507 tests)

Copilot AI Dec 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent test counts: line 285 states 507 tests while line 307 claims 561 tests. The PR description mentions 508 total tests. These numbers should be reconciled to accurately reflect the test suite size.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback


#### Configuration
- Added `audio.enableSpatialAudio` config option
- Added `audio.maxDistance` config option for spatial audio range

### Documentation

#### Updated Files
- `README.md` - Added comprehensive v3.1 feature documentation
- SaveSystem usage examples and API
- AchievementSystem usage examples and API
- Enhanced AudioSystem features
- Configuration examples
- `CHANGELOG.md` - This file with v3.1 release notes
- `.gitignore` - Added node_modules and package-lock.json

### Testing

- Added 22 unit tests for SaveSystem
- Added 32 unit tests for AchievementSystem
- All 507 existing tests still passing
- Total: 561 tests passing
Comment thread
MiChaelinzo marked this conversation as resolved.
- Maintained backward compatibility
- No breaking changes to existing API

### Performance

- SaveSystem uses localStorage with efficient key-based storage
- AchievementSystem optimized with Map/Set data structures
- Spatial audio calculations optimized for performance
- Minimal overhead from new systems


215 changes: 215 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -777,3 +777,218 @@ Configure new systems in your game config:

See `examples/new-features-demo.html` for an interactive demonstration of all new features.

## 🆕 New Features (v3.1)

### SaveSystem

Comprehensive save/load system for game state persistence using localStorage.

```javascript
import { SaveSystem } from './framework/utils/SaveSystem.js';

// Initialize save system
const saveSystem = new SaveSystem({
gameId: 'my_horror_game',
maxSlots: 3,
autoSave: true,
autoSaveInterval: 60000 // 1 minute
});

// Save game state
const gameState = {
player: { x: 100, y: 200, health: 80 },
level: 5,
inventory: ['key', 'flashlight']
};

const metadata = {
playerName: 'Player1',
playtime: 3600,
levelName: 'Dark Corridor'
};

saveSystem.save(0, gameState, metadata);

// Load game state
const savedData = saveSystem.load(0);
if (savedData) {
console.log('Loaded game:', savedData.gameState);
console.log('Metadata:', savedData.metadata);
}

// Check if save exists
if (saveSystem.hasSave(0)) {
console.log('Save slot 0 has data');
}

// Get all save metadata
const allSaves = saveSystem.getAllSaveMetadata();
allSaves.forEach((save, slot) => {
if (save) {
console.log(`Slot ${slot}: ${save.metadata.playerName} - ${save.metadata.levelName}`);
}
});

// Export/Import for backup
const exportedData = saveSystem.exportSave(0);
saveSystem.importSave(1, exportedData); // Copy to slot 1

// Auto-save
saveSystem.startAutoSave(() => {
return getCurrentGameState(); // Your function to get current state
}, 0);

// Storage statistics
const stats = saveSystem.getStorageStats();
console.log(`Using ${stats.totalSize} bytes across ${stats.slotsUsed} slots`);
```

### AchievementSystem

Track player accomplishments with support for progress tracking, secret achievements, and rewards.

```javascript
import { AchievementSystem } from './framework/systems/AchievementSystem.js';

// Initialize achievement system
const achievements = new AchievementSystem({
gameId: 'my_horror_game',
enableNotifications: true,
notificationDuration: 3000
});

// Register achievements
achievements.registerAchievement({
id: 'first_kill',
name: 'First Blood',
description: 'Defeat your first enemy',
type: 'simple'
});

achievements.registerAchievement({
id: 'kill_100',
name: 'Centurion',
description: 'Defeat 100 enemies',
type: 'progress',
target: 100,
reward: { gold: 500, item: 'legendary_sword' }
});

achievements.registerAchievement({
id: 'secret_room',
name: '???',
description: 'Find the hidden chamber',
type: 'secret',
hidden: true
});

// Unlock simple achievement
achievements.unlock('first_kill');

// Update progress achievement
achievements.incrementProgress('kill_100', 1); // Increment by 1
achievements.updateProgress('kill_100', 50); // Set to 50

// Check achievement status
if (achievements.isUnlocked('first_kill')) {
console.log('Achievement unlocked!');
}

// Get progress
const progress = achievements.getProgress('kill_100');
console.log(`Progress: ${progress.current}/${progress.target} (${progress.percentage}%)`);

// Get all achievements
const allAchievements = achievements.getAllAchievements();
allAchievements.forEach(achievement => {
console.log(`${achievement.name}: ${achievement.unlocked ? 'Unlocked' : 'Locked'}`);
});

// Get statistics
const stats = achievements.getStats();
console.log(`Unlocked ${stats.unlocked}/${stats.total} achievements (${stats.percentage}%)`);

// Register callbacks
achievements.onUnlock((achievement) => {
console.log(`Achievement unlocked: ${achievement.name}`);
if (achievement.reward) {
giveRewardToPlayer(achievement.reward);
}
});

achievements.onProgress((achievement, current, target) => {
console.log(`${achievement.name}: ${current}/${target}`);
});
```

**Achievement Types:**
- `simple` - One-time unlock achievements
- `progress` - Track incremental progress towards a goal
- `secret` - Hidden until unlocked
- `challenge` - Difficult achievements with special requirements

### Enhanced Audio System

New audio features for better sound control and spatial audio.

```javascript
// Preload multiple sounds
await audio.preloadSounds([
{ id: 'bgm1', url: 'music/theme.mp3' },
{ id: 'footstep', url: 'sfx/footstep.wav' },
{ id: 'scream', url: 'sfx/scream.wav' }
]);

// Fade in ambient music
audio.fadeInAmbient('bgm1', 0.7, 2.0); // Fade to 0.7 volume over 2 seconds

// Fade out ambient music
audio.fadeOutAmbient(3.0); // Fade out over 3 seconds

// Fade to new volume
audio.fadeAmbientTo(0.3, 1.0); // Fade to 0.3 volume over 1 second

// Spatial audio (distance-based volume)
const audioObj = audio.playSpatialSound(
'footstep',
{ x: 500, y: 300 }, // Sound source position
{ x: 100, y: 100 }, // Listener position
1.0, // Max volume
false // Don't loop
);

// Update spatial audio as positions change
audio.updateSpatialSound(
audioObj,
{ x: 450, y: 300 }, // New source position
{ x: 150, y: 100 }, // New listener position
1.0
);

// Ambient volume control
audio.setAmbientVolume(0.5);
const currentVolume = audio.getAmbientVolume();
```

### Configuration Updates

Add new systems to your game configuration:

```json
{
"game": {
"particles": {
"maxParticles": 2000
},
"spatialGridCellSize": 100,
"worldWidth": 2000,
"worldHeight": 2000,
"audio": {
"enableSpatialAudio": true,
"maxDistance": 1000
}
}
}
```


Loading
Loading