2755 lines
63 KiB
Markdown
2755 lines
63 KiB
Markdown
# API Reference
|
|
|
|
Complete API reference for all asset systems in the Game Arcade platform.
|
|
|
|
## Table of Contents
|
|
1. [AssetManager](#assetmanager)
|
|
2. [MusicEngine](#musicengine)
|
|
3. [BackgroundEngine](#backgroundengine)
|
|
4. [AvatarSystem](#avatarsystem)
|
|
5. [ContextRenderer](#contextrenderer)
|
|
6. [ContextCatalog](#contextcatalog)
|
|
7. [AssetCatalog](#assetcatalog)
|
|
8. [AssetPresets](#assetpresets)
|
|
9. [AssetCompatibility](#assetcompatibility)
|
|
10. [Common Patterns](#common-patterns)
|
|
11. [Troubleshooting](#troubleshooting)
|
|
|
|
---
|
|
|
|
## AssetManager
|
|
|
|
Main coordinator for all asset systems. Provides unified access to music, backgrounds, avatars, and contexts.
|
|
|
|
### Properties
|
|
|
|
| Property | Type | Description |
|
|
|----------|------|-------------|
|
|
| `initialized` | boolean | Whether the manager has been initialized |
|
|
| `stats` | Object | Statistics about loaded assets |
|
|
|
|
### Methods
|
|
|
|
#### initialize()
|
|
```javascript
|
|
AssetManager.initialize(options) → Promise<{stats}>
|
|
```
|
|
Initialize all asset systems. Call once at startup before using any other asset methods.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `options` | Object | No | Configuration options |
|
|
| `options.preloadMusic` | boolean | No | Preload all music (default: false) |
|
|
| `options.preloadBackgrounds` | boolean | No | Preload background assets (default: true) |
|
|
| `options.cacheAvatars` | boolean | No | Enable avatar caching (default: true) |
|
|
| `options.maxCacheSize` | number | No | Maximum cache entries (default: 100) |
|
|
|
|
**Returns:** `Promise<Object>` - Stats object with loaded asset counts
|
|
|
|
**Example:**
|
|
```javascript
|
|
const stats = await AssetManager.initialize({
|
|
preloadMusic: false,
|
|
preloadBackgrounds: true
|
|
});
|
|
console.log(stats.music.songs); // 160
|
|
console.log(stats.backgrounds.themes); // 12
|
|
console.log(stats.avatars.parts); // 340
|
|
console.log(stats.contexts.total); // 44
|
|
```
|
|
|
|
---
|
|
|
|
#### getRecommendations()
|
|
```javascript
|
|
AssetManager.getRecommendations(gameStyle, keywords, mood) → Array<Recommendation>
|
|
```
|
|
Get asset recommendations based on game description. Returns the top 3 matching asset combinations.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `gameStyle` | string | Yes | One of the 11 game styles |
|
|
| `keywords` | string\|Array | Yes | Description text or keyword array |
|
|
| `mood` | string | No | Override auto-detected mood |
|
|
|
|
**Valid Game Styles:**
|
|
- `action-arcade`
|
|
- `puzzle-logic`
|
|
- `adventure-story`
|
|
- `educational`
|
|
- `simulation`
|
|
- `sports-racing`
|
|
- `strategy`
|
|
- `rhythm-music`
|
|
- `horror-survival`
|
|
- `casual-relaxing`
|
|
- `multiplayer-party`
|
|
|
|
**Valid Moods:**
|
|
- `Epic`
|
|
- `Chill`
|
|
- `Dark`
|
|
- `Upbeat`
|
|
- `Mysterious`
|
|
- `Retro`
|
|
- `Dramatic`
|
|
- `Peaceful`
|
|
|
|
**Returns:** `Array<Recommendation>` - Top 3 recommendations
|
|
|
|
**Recommendation Object:**
|
|
```javascript
|
|
{
|
|
config: {
|
|
music: { mood: string, songId: string },
|
|
background: { theme: string, variant: string },
|
|
context: { id: string, variant: string }
|
|
},
|
|
score: number, // 0-100 match score
|
|
explanation: string // Human-readable explanation
|
|
}
|
|
```
|
|
|
|
**Example:**
|
|
```javascript
|
|
const recs = AssetManager.getRecommendations(
|
|
'action-arcade',
|
|
'space shooter aliens lasers explosions',
|
|
'Epic'
|
|
);
|
|
|
|
console.log(recs[0]);
|
|
// {
|
|
// config: {
|
|
// music: { mood: 'Epic', songId: 'epic-battle-04' },
|
|
// background: { theme: 'space', variant: 'nebula' },
|
|
// context: { id: 'shooter-standard', variant: 'default' }
|
|
// },
|
|
// score: 94,
|
|
// explanation: 'Space theme with epic music matches action shooter keywords'
|
|
// }
|
|
```
|
|
|
|
---
|
|
|
|
#### findPreset()
|
|
```javascript
|
|
AssetManager.findPreset(name) → Preset | null
|
|
```
|
|
Find a named preset by exact name or partial match.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `name` | string | Yes | Preset name (case-insensitive) |
|
|
|
|
**Returns:** `Preset | null` - Matching preset or null if not found
|
|
|
|
**Preset Object:**
|
|
```javascript
|
|
{
|
|
id: string,
|
|
name: string,
|
|
description: string,
|
|
config: {
|
|
music: { mood: string, songId?: string },
|
|
background: { theme: string, variant: string, effects?: Array },
|
|
context: { id: string, variant?: string }
|
|
},
|
|
tags: Array<string>,
|
|
gameStyles: Array<string>
|
|
}
|
|
```
|
|
|
|
**Example:**
|
|
```javascript
|
|
const preset = AssetManager.findPreset('retro-platformer');
|
|
if (preset) {
|
|
await AssetManager.loadGameAssets(preset.config);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### loadGameAssets()
|
|
```javascript
|
|
AssetManager.loadGameAssets(config) → Promise<LoadedAssets>
|
|
```
|
|
Load and prepare all assets for a game based on configuration.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `config` | Object | Yes | Asset configuration object |
|
|
| `config.music` | Object | No | Music configuration |
|
|
| `config.music.mood` | string | No | Music mood category |
|
|
| `config.music.songId` | string | No | Specific song ID |
|
|
| `config.background` | Object | No | Background configuration |
|
|
| `config.background.theme` | string | Yes | Background theme |
|
|
| `config.background.variant` | string | Yes | Theme variant |
|
|
| `config.background.effects` | Array | No | Visual effects to apply |
|
|
| `config.context` | Object | No | Context configuration |
|
|
| `config.context.id` | string | Yes | Context ID |
|
|
| `config.context.variant` | string | No | Context variant |
|
|
|
|
**Returns:** `Promise<LoadedAssets>` - Object containing loaded asset references
|
|
|
|
**LoadedAssets Object:**
|
|
```javascript
|
|
{
|
|
music: {
|
|
song: Song,
|
|
ready: boolean
|
|
},
|
|
background: {
|
|
theme: Theme,
|
|
variant: Variant,
|
|
renderFn: Function
|
|
},
|
|
context: {
|
|
context: Context,
|
|
sprites: Map<string, Sprite>
|
|
}
|
|
}
|
|
```
|
|
|
|
**Example:**
|
|
```javascript
|
|
const assets = await AssetManager.loadGameAssets({
|
|
music: { mood: 'Upbeat' },
|
|
background: { theme: 'nature', variant: 'forest' },
|
|
context: { id: 'platformer-standard' }
|
|
});
|
|
|
|
// Start music
|
|
MusicEngine.playSong(assets.music.song.id);
|
|
|
|
// Use in game loop
|
|
function render(time) {
|
|
assets.background.renderFn(ctx, width, height, time);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### validateCombination()
|
|
```javascript
|
|
AssetManager.validateCombination(config) → ValidationResult
|
|
```
|
|
Validate that an asset combination is compatible and complete.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `config` | Object | Yes | Configuration to validate |
|
|
|
|
**Returns:** `ValidationResult`
|
|
```javascript
|
|
{
|
|
valid: boolean,
|
|
errors: Array<string>,
|
|
warnings: Array<string>,
|
|
suggestions: Array<string>
|
|
}
|
|
```
|
|
|
|
**Example:**
|
|
```javascript
|
|
const result = AssetManager.validateCombination({
|
|
music: { mood: 'Epic' },
|
|
background: { theme: 'nature', variant: 'peaceful-meadow' },
|
|
context: { id: 'shooter-standard' }
|
|
});
|
|
|
|
console.log(result);
|
|
// {
|
|
// valid: true,
|
|
// errors: [],
|
|
// warnings: ['Epic music may not match peaceful background'],
|
|
// suggestions: ['Consider using "forest" variant for better mood match']
|
|
// }
|
|
```
|
|
|
|
---
|
|
|
|
#### describeAssets()
|
|
```javascript
|
|
AssetManager.describeAssets(config) → AssetDescription
|
|
```
|
|
Get human-readable descriptions of an asset configuration.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `config` | Object | Yes | Asset configuration |
|
|
|
|
**Returns:** `AssetDescription`
|
|
```javascript
|
|
{
|
|
summary: string,
|
|
music: {
|
|
name: string,
|
|
description: string,
|
|
mood: string,
|
|
tempo: string
|
|
},
|
|
background: {
|
|
name: string,
|
|
description: string,
|
|
colors: Array<string>
|
|
},
|
|
context: {
|
|
name: string,
|
|
description: string,
|
|
animations: Array<string>
|
|
}
|
|
}
|
|
```
|
|
|
|
**Example:**
|
|
```javascript
|
|
const desc = AssetManager.describeAssets({
|
|
music: { songId: 'epic-battle-04' },
|
|
background: { theme: 'space', variant: 'nebula' },
|
|
context: { id: 'shooter-standard' }
|
|
});
|
|
|
|
console.log(desc.summary);
|
|
// "Epic orchestral music with a colorful space nebula background,
|
|
// featuring a shooter-style player with laser animations"
|
|
```
|
|
|
|
---
|
|
|
|
#### getVariation()
|
|
```javascript
|
|
AssetManager.getVariation(config, variationType) → Object
|
|
```
|
|
Get a variation of the current configuration.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `config` | Object | Yes | Current configuration |
|
|
| `variationType` | string | No | Type of variation (default: 'similar') |
|
|
|
|
**Variation Types:**
|
|
- `similar` - Same mood/theme, different specific assets
|
|
- `contrast` - Opposite mood, complementary visuals
|
|
- `random` - Random compatible combination
|
|
- `seasonal` - Seasonal variation if available
|
|
|
|
**Returns:** `Object` - New configuration object
|
|
|
|
**Example:**
|
|
```javascript
|
|
const original = {
|
|
music: { mood: 'Epic' },
|
|
background: { theme: 'castle', variant: 'throne-room' }
|
|
};
|
|
|
|
const variation = AssetManager.getVariation(original, 'similar');
|
|
// Returns different Epic song, different castle variant
|
|
```
|
|
|
|
---
|
|
|
|
#### searchAssets()
|
|
```javascript
|
|
AssetManager.searchAssets(query, options) → SearchResults
|
|
```
|
|
Search across all asset types.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `query` | string | Yes | Search query |
|
|
| `options` | Object | No | Search options |
|
|
| `options.types` | Array | No | Asset types to search (default: all) |
|
|
| `options.limit` | number | No | Maximum results per type (default: 10) |
|
|
| `options.includeMetadata` | boolean | No | Include full metadata (default: false) |
|
|
|
|
**Valid Types:** `['music', 'background', 'context', 'preset']`
|
|
|
|
**Returns:** `SearchResults`
|
|
```javascript
|
|
{
|
|
music: Array<Song>,
|
|
backgrounds: Array<{theme, variant}>,
|
|
contexts: Array<Context>,
|
|
presets: Array<Preset>,
|
|
totalCount: number
|
|
}
|
|
```
|
|
|
|
**Example:**
|
|
```javascript
|
|
const results = AssetManager.searchAssets('forest', {
|
|
types: ['background', 'music'],
|
|
limit: 5
|
|
});
|
|
|
|
console.log(results.backgrounds);
|
|
// [{ theme: 'nature', variant: 'forest' },
|
|
// { theme: 'nature', variant: 'enchanted-forest' }]
|
|
```
|
|
|
|
---
|
|
|
|
#### getRandomCombination()
|
|
```javascript
|
|
AssetManager.getRandomCombination(constraints) → Object
|
|
```
|
|
Generate a random compatible asset combination.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `constraints` | Object | No | Constraints for random selection |
|
|
| `constraints.mood` | string | No | Required mood |
|
|
| `constraints.gameStyle` | string | No | Required game style compatibility |
|
|
| `constraints.excludeThemes` | Array | No | Themes to exclude |
|
|
| `constraints.excludeContexts` | Array | No | Contexts to exclude |
|
|
|
|
**Returns:** `Object` - Random configuration
|
|
|
|
**Example:**
|
|
```javascript
|
|
const random = AssetManager.getRandomCombination({
|
|
mood: 'Upbeat',
|
|
gameStyle: 'casual-relaxing',
|
|
excludeThemes: ['horror', 'space']
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
## MusicEngine
|
|
|
|
Procedural music synthesis using Tone.js. Generates and plays dynamic music in various moods and styles.
|
|
|
|
### Properties
|
|
|
|
| Property | Type | Description |
|
|
|----------|------|-------------|
|
|
| `isPlaying` | boolean | Whether music is currently playing |
|
|
| `currentSong` | Song\|null | Currently playing song |
|
|
| `volume` | number | Current volume (0-1) |
|
|
| `muted` | boolean | Whether audio is muted |
|
|
|
|
### Methods
|
|
|
|
#### initialize()
|
|
```javascript
|
|
MusicEngine.initialize() → Promise<void>
|
|
```
|
|
Initialize the music engine. Called automatically by AssetManager.
|
|
|
|
**Example:**
|
|
```javascript
|
|
await MusicEngine.initialize();
|
|
```
|
|
|
|
---
|
|
|
|
#### playRandomSong()
|
|
```javascript
|
|
MusicEngine.playRandomSong(mood) → string
|
|
```
|
|
Play a random song from the specified mood category.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `mood` | string | Yes | Mood category |
|
|
|
|
**Valid Moods:** `Epic`, `Chill`, `Dark`, `Upbeat`, `Mysterious`, `Retro`, `Dramatic`, `Peaceful`
|
|
|
|
**Returns:** `string` - ID of the song that started playing
|
|
|
|
**Example:**
|
|
```javascript
|
|
const songId = MusicEngine.playRandomSong('Epic');
|
|
console.log(`Now playing: ${songId}`);
|
|
```
|
|
|
|
---
|
|
|
|
#### playSong()
|
|
```javascript
|
|
MusicEngine.playSong(songId) → boolean
|
|
```
|
|
Play a specific song by its ID.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `songId` | string | Yes | Unique song identifier |
|
|
|
|
**Returns:** `boolean` - True if song started playing, false if not found
|
|
|
|
**Example:**
|
|
```javascript
|
|
if (MusicEngine.playSong('epic-battle-04')) {
|
|
console.log('Song started');
|
|
} else {
|
|
console.log('Song not found');
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### stopMusic()
|
|
```javascript
|
|
MusicEngine.stopMusic() → void
|
|
```
|
|
Stop the currently playing music immediately.
|
|
|
|
**Example:**
|
|
```javascript
|
|
MusicEngine.stopMusic();
|
|
```
|
|
|
|
---
|
|
|
|
#### pauseMusic()
|
|
```javascript
|
|
MusicEngine.pauseMusic() → void
|
|
```
|
|
Pause the currently playing music. Can be resumed with `resumeMusic()`.
|
|
|
|
**Example:**
|
|
```javascript
|
|
MusicEngine.pauseMusic();
|
|
```
|
|
|
|
---
|
|
|
|
#### resumeMusic()
|
|
```javascript
|
|
MusicEngine.resumeMusic() → void
|
|
```
|
|
Resume paused music.
|
|
|
|
**Example:**
|
|
```javascript
|
|
MusicEngine.resumeMusic();
|
|
```
|
|
|
|
---
|
|
|
|
#### setVolume()
|
|
```javascript
|
|
MusicEngine.setVolume(level) → void
|
|
```
|
|
Set the music volume.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `level` | number | Yes | Volume level (0-1) |
|
|
|
|
**Example:**
|
|
```javascript
|
|
MusicEngine.setVolume(0.7); // 70% volume
|
|
```
|
|
|
|
---
|
|
|
|
#### getVolume()
|
|
```javascript
|
|
MusicEngine.getVolume() → number
|
|
```
|
|
Get the current volume level.
|
|
|
|
**Returns:** `number` - Current volume (0-1)
|
|
|
|
---
|
|
|
|
#### mute()
|
|
```javascript
|
|
MusicEngine.mute() → void
|
|
```
|
|
Mute audio without changing volume setting.
|
|
|
|
---
|
|
|
|
#### unmute()
|
|
```javascript
|
|
MusicEngine.unmute() → void
|
|
```
|
|
Unmute audio, restoring previous volume.
|
|
|
|
---
|
|
|
|
#### fadeOut()
|
|
```javascript
|
|
MusicEngine.fadeOut(duration) → Promise<void>
|
|
```
|
|
Gradually fade out the music.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `duration` | number | No | Fade duration in milliseconds (default: 1000) |
|
|
|
|
**Returns:** `Promise<void>` - Resolves when fade completes
|
|
|
|
**Example:**
|
|
```javascript
|
|
await MusicEngine.fadeOut(2000); // 2 second fade
|
|
MusicEngine.playRandomSong('Dark');
|
|
```
|
|
|
|
---
|
|
|
|
#### fadeIn()
|
|
```javascript
|
|
MusicEngine.fadeIn(songId, duration) → Promise<void>
|
|
```
|
|
Start a song with a fade in effect.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `songId` | string | Yes | Song to play |
|
|
| `duration` | number | No | Fade duration in ms (default: 1000) |
|
|
|
|
**Returns:** `Promise<void>` - Resolves when fade completes
|
|
|
|
**Example:**
|
|
```javascript
|
|
await MusicEngine.fadeIn('peaceful-meadow-02', 1500);
|
|
```
|
|
|
|
---
|
|
|
|
#### crossfade()
|
|
```javascript
|
|
MusicEngine.crossfade(songId, duration) → Promise<void>
|
|
```
|
|
Crossfade from current song to a new song.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `songId` | string | Yes | Song to crossfade to |
|
|
| `duration` | number | No | Crossfade duration in ms (default: 2000) |
|
|
|
|
**Returns:** `Promise<void>` - Resolves when crossfade completes
|
|
|
|
**Example:**
|
|
```javascript
|
|
await MusicEngine.crossfade('epic-battle-04', 1500);
|
|
```
|
|
|
|
---
|
|
|
|
#### getCatalog()
|
|
```javascript
|
|
MusicEngine.getCatalog() → Array<Song>
|
|
```
|
|
Get all available songs.
|
|
|
|
**Returns:** `Array<Song>` - All songs in the catalog
|
|
|
|
**Song Object:**
|
|
```javascript
|
|
{
|
|
id: string,
|
|
name: string,
|
|
mood: string,
|
|
tempo: number, // BPM
|
|
duration: number, // seconds
|
|
instruments: Array<string>,
|
|
tags: Array<string>,
|
|
intensity: number // 1-10
|
|
}
|
|
```
|
|
|
|
**Example:**
|
|
```javascript
|
|
const songs = MusicEngine.getCatalog();
|
|
console.log(`Total songs: ${songs.length}`); // 160
|
|
```
|
|
|
|
---
|
|
|
|
#### findSongs()
|
|
```javascript
|
|
MusicEngine.findSongs(filters) → Array<Song>
|
|
```
|
|
Find songs matching specified filters.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `filters` | Object | Yes | Filter criteria |
|
|
| `filters.mood` | string | No | Filter by mood |
|
|
| `filters.minTempo` | number | No | Minimum tempo (BPM) |
|
|
| `filters.maxTempo` | number | No | Maximum tempo (BPM) |
|
|
| `filters.instruments` | Array | No | Required instruments |
|
|
| `filters.tags` | Array | No | Required tags (any match) |
|
|
| `filters.intensity` | number\|Array | No | Exact or [min, max] range |
|
|
|
|
**Returns:** `Array<Song>` - Matching songs
|
|
|
|
**Example:**
|
|
```javascript
|
|
const songs = MusicEngine.findSongs({
|
|
mood: 'Epic',
|
|
minTempo: 120,
|
|
intensity: [7, 10]
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
#### getSongsByMood()
|
|
```javascript
|
|
MusicEngine.getSongsByMood(mood) → Array<Song>
|
|
```
|
|
Get all songs in a specific mood category.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `mood` | string | Yes | Mood category |
|
|
|
|
**Returns:** `Array<Song>` - Songs in that mood
|
|
|
|
**Example:**
|
|
```javascript
|
|
const epicSongs = MusicEngine.getSongsByMood('Epic');
|
|
console.log(`Epic songs: ${epicSongs.length}`); // 20
|
|
```
|
|
|
|
---
|
|
|
|
#### getMoods()
|
|
```javascript
|
|
MusicEngine.getMoods() → Array<string>
|
|
```
|
|
Get all available mood categories.
|
|
|
|
**Returns:** `Array<string>` - Available moods
|
|
|
|
**Example:**
|
|
```javascript
|
|
const moods = MusicEngine.getMoods();
|
|
// ['Epic', 'Chill', 'Dark', 'Upbeat', 'Mysterious', 'Retro', 'Dramatic', 'Peaceful']
|
|
```
|
|
|
|
---
|
|
|
|
#### getSongInfo()
|
|
```javascript
|
|
MusicEngine.getSongInfo(songId) → Song | null
|
|
```
|
|
Get detailed information about a specific song.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `songId` | string | Yes | Song identifier |
|
|
|
|
**Returns:** `Song | null` - Song object or null if not found
|
|
|
|
---
|
|
|
|
#### onSongEnd()
|
|
```javascript
|
|
MusicEngine.onSongEnd(callback) → Function
|
|
```
|
|
Register a callback for when a song ends.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `callback` | Function | Yes | Called when song ends |
|
|
|
|
**Returns:** `Function` - Unsubscribe function
|
|
|
|
**Example:**
|
|
```javascript
|
|
const unsubscribe = MusicEngine.onSongEnd(() => {
|
|
MusicEngine.playRandomSong('Epic'); // Loop
|
|
});
|
|
|
|
// Later: unsubscribe();
|
|
```
|
|
|
|
---
|
|
|
|
## BackgroundEngine
|
|
|
|
Procedural background rendering system. Generates animated backgrounds using canvas drawing.
|
|
|
|
### Properties
|
|
|
|
| Property | Type | Description |
|
|
|----------|------|-------------|
|
|
| `themes` | Array<string> | Available theme names |
|
|
| `activeEffects` | Array<string> | Currently active effects |
|
|
|
|
### Methods
|
|
|
|
#### initialize()
|
|
```javascript
|
|
BackgroundEngine.initialize() → Promise<void>
|
|
```
|
|
Initialize the background engine. Called automatically by AssetManager.
|
|
|
|
---
|
|
|
|
#### render()
|
|
```javascript
|
|
BackgroundEngine.render(ctx, theme, variant, width, height, time, options) → void
|
|
```
|
|
Render a background to a canvas context.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `ctx` | CanvasRenderingContext2D | Yes | Canvas 2D context |
|
|
| `theme` | string | Yes | Theme name |
|
|
| `variant` | string | Yes | Variant name |
|
|
| `width` | number | Yes | Canvas width in pixels |
|
|
| `height` | number | Yes | Canvas height in pixels |
|
|
| `time` | number | Yes | Time in seconds (for animation) |
|
|
| `options` | Object | No | Rendering options |
|
|
| `options.effects` | Array | No | Visual effects to apply |
|
|
| `options.parallax` | Object | No | Parallax configuration |
|
|
| `options.colorShift` | number | No | Hue shift in degrees |
|
|
|
|
**Available Effects:**
|
|
- `particles` - Floating particles
|
|
- `rain` - Rain effect
|
|
- `snow` - Snow effect
|
|
- `fog` - Fog overlay
|
|
- `lightning` - Lightning flashes
|
|
- `stars-twinkle` - Twinkling stars
|
|
- `clouds-moving` - Moving clouds
|
|
- `leaves-falling` - Falling leaves
|
|
- `fireflies` - Glowing fireflies
|
|
- `heat-distortion` - Heat wave effect
|
|
|
|
**Example:**
|
|
```javascript
|
|
function gameLoop(timestamp) {
|
|
const time = timestamp / 1000; // Convert to seconds
|
|
|
|
BackgroundEngine.render(
|
|
ctx,
|
|
'nature',
|
|
'forest',
|
|
canvas.width,
|
|
canvas.height,
|
|
time,
|
|
{ effects: ['leaves-falling', 'fog'] }
|
|
);
|
|
|
|
requestAnimationFrame(gameLoop);
|
|
}
|
|
requestAnimationFrame(gameLoop);
|
|
```
|
|
|
|
---
|
|
|
|
#### renderStatic()
|
|
```javascript
|
|
BackgroundEngine.renderStatic(ctx, theme, variant, width, height, options) → void
|
|
```
|
|
Render a static (non-animated) background.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `ctx` | CanvasRenderingContext2D | Yes | Canvas 2D context |
|
|
| `theme` | string | Yes | Theme name |
|
|
| `variant` | string | Yes | Variant name |
|
|
| `width` | number | Yes | Canvas width |
|
|
| `height` | number | Yes | Canvas height |
|
|
| `options` | Object | No | Rendering options |
|
|
|
|
**Example:**
|
|
```javascript
|
|
// Render once for menu screens
|
|
BackgroundEngine.renderStatic(ctx, 'castle', 'entrance', 800, 600);
|
|
```
|
|
|
|
---
|
|
|
|
#### getThemes()
|
|
```javascript
|
|
BackgroundEngine.getThemes() → Array<string>
|
|
```
|
|
Get all available theme names.
|
|
|
|
**Returns:** `Array<string>` - Theme names
|
|
|
|
**Example:**
|
|
```javascript
|
|
const themes = BackgroundEngine.getThemes();
|
|
// ['nature', 'space', 'underwater', 'castle', 'city', 'desert',
|
|
// 'arctic', 'cave', 'sky', 'abstract', 'horror', 'fantasy']
|
|
```
|
|
|
|
---
|
|
|
|
#### getVariants()
|
|
```javascript
|
|
BackgroundEngine.getVariants(theme) → Array<string>
|
|
```
|
|
Get all variant names for a theme.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `theme` | string | Yes | Theme name |
|
|
|
|
**Returns:** `Array<string>` - Variant names for the theme
|
|
|
|
**Example:**
|
|
```javascript
|
|
const variants = BackgroundEngine.getVariants('nature');
|
|
// ['forest', 'meadow', 'mountain', 'river', 'beach', 'jungle', 'autumn-forest']
|
|
```
|
|
|
|
---
|
|
|
|
#### getThemeInfo()
|
|
```javascript
|
|
BackgroundEngine.getThemeInfo(theme) → ThemeInfo | null
|
|
```
|
|
Get detailed information about a theme.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `theme` | string | Yes | Theme name |
|
|
|
|
**Returns:** `ThemeInfo | null`
|
|
```javascript
|
|
{
|
|
name: string,
|
|
description: string,
|
|
variants: Array<{
|
|
name: string,
|
|
description: string,
|
|
colors: Array<string>,
|
|
suggestedEffects: Array<string>
|
|
}>,
|
|
compatibleMoods: Array<string>,
|
|
tags: Array<string>
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### getEffects()
|
|
```javascript
|
|
BackgroundEngine.getEffects() → Array<EffectInfo>
|
|
```
|
|
Get all available visual effects.
|
|
|
|
**Returns:** `Array<EffectInfo>`
|
|
```javascript
|
|
{
|
|
id: string,
|
|
name: string,
|
|
description: string,
|
|
performance: 'low' | 'medium' | 'high',
|
|
compatibleThemes: Array<string> | 'all'
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### preloadTheme()
|
|
```javascript
|
|
BackgroundEngine.preloadTheme(theme) → Promise<void>
|
|
```
|
|
Preload a theme's assets for smoother rendering.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `theme` | string | Yes | Theme to preload |
|
|
|
|
**Returns:** `Promise<void>` - Resolves when preloaded
|
|
|
|
---
|
|
|
|
#### createRenderFunction()
|
|
```javascript
|
|
BackgroundEngine.createRenderFunction(theme, variant, options) → Function
|
|
```
|
|
Create a reusable render function for a specific background.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `theme` | string | Yes | Theme name |
|
|
| `variant` | string | Yes | Variant name |
|
|
| `options` | Object | No | Permanent options |
|
|
|
|
**Returns:** `Function` - `(ctx, width, height, time) => void`
|
|
|
|
**Example:**
|
|
```javascript
|
|
const renderForest = BackgroundEngine.createRenderFunction(
|
|
'nature',
|
|
'forest',
|
|
{ effects: ['fog'] }
|
|
);
|
|
|
|
function gameLoop(time) {
|
|
renderForest(ctx, canvas.width, canvas.height, time / 1000);
|
|
requestAnimationFrame(gameLoop);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### setGlobalEffect()
|
|
```javascript
|
|
BackgroundEngine.setGlobalEffect(effectId, enabled) → void
|
|
```
|
|
Enable or disable a global effect.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `effectId` | string | Yes | Effect identifier |
|
|
| `enabled` | boolean | Yes | Whether to enable |
|
|
|
|
---
|
|
|
|
#### getColorPalette()
|
|
```javascript
|
|
BackgroundEngine.getColorPalette(theme, variant) → Array<string>
|
|
```
|
|
Get the color palette for a background.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `theme` | string | Yes | Theme name |
|
|
| `variant` | string | Yes | Variant name |
|
|
|
|
**Returns:** `Array<string>` - Hex color codes
|
|
|
|
**Example:**
|
|
```javascript
|
|
const colors = BackgroundEngine.getColorPalette('nature', 'forest');
|
|
// ['#1a472a', '#2d5a27', '#228b22', '#90ee90', '#87ceeb']
|
|
```
|
|
|
|
---
|
|
|
|
## AvatarSystem
|
|
|
|
Avatar creation, customization, rendering, and management system.
|
|
|
|
### Properties
|
|
|
|
| Property | Type | Description |
|
|
|----------|------|-------------|
|
|
| `currentAvatar` | Avatar\|null | Currently loaded avatar |
|
|
| `parts` | Object | Available parts by category |
|
|
|
|
### Methods
|
|
|
|
#### initialize()
|
|
```javascript
|
|
AvatarSystem.initialize() → Promise<void>
|
|
```
|
|
Initialize the avatar system. Called automatically by AssetManager.
|
|
|
|
---
|
|
|
|
#### create()
|
|
```javascript
|
|
AvatarSystem.create(customization) → Avatar
|
|
```
|
|
Create a new avatar with specified customization.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `customization` | Object | No | Customization options |
|
|
| `customization.base` | string | No | Base body type |
|
|
| `customization.skinTone` | string | No | Skin tone color |
|
|
| `customization.hairStyle` | string | No | Hair style ID |
|
|
| `customization.hairColor` | string | No | Hair color |
|
|
| `customization.eyes` | string | No | Eye style ID |
|
|
| `customization.eyeColor` | string | No | Eye color |
|
|
| `customization.outfit` | string | No | Outfit ID |
|
|
| `customization.accessories` | Array | No | Equipped accessories |
|
|
|
|
**Returns:** `Avatar` - New avatar object
|
|
|
|
**Avatar Object:**
|
|
```javascript
|
|
{
|
|
id: string,
|
|
version: number,
|
|
customization: Object,
|
|
accessories: Map<string, string>,
|
|
createdAt: Date,
|
|
updatedAt: Date
|
|
}
|
|
```
|
|
|
|
**Example:**
|
|
```javascript
|
|
const avatar = AvatarSystem.create({
|
|
base: 'humanoid',
|
|
skinTone: '#f5d0b0',
|
|
hairStyle: 'spiky',
|
|
hairColor: '#3d2314',
|
|
eyes: 'round',
|
|
eyeColor: '#4a90d9',
|
|
outfit: 'casual-tee'
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
#### createRandom()
|
|
```javascript
|
|
AvatarSystem.createRandom(constraints) → Avatar
|
|
```
|
|
Create a random avatar.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `constraints` | Object | No | Constraints for randomization |
|
|
| `constraints.base` | string | No | Fixed base type |
|
|
| `constraints.style` | string | No | Style category |
|
|
|
|
**Returns:** `Avatar` - Random avatar
|
|
|
|
**Example:**
|
|
```javascript
|
|
const randomAvatar = AvatarSystem.createRandom({
|
|
style: 'fantasy'
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
#### loadUserAvatar()
|
|
```javascript
|
|
AvatarSystem.loadUserAvatar(userId) → Promise<Avatar>
|
|
```
|
|
Load a user's saved avatar from the server.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `userId` | string | Yes | User identifier |
|
|
|
|
**Returns:** `Promise<Avatar>` - User's avatar
|
|
|
|
**Example:**
|
|
```javascript
|
|
const avatar = await AvatarSystem.loadUserAvatar(currentUser.id);
|
|
```
|
|
|
|
---
|
|
|
|
#### saveUserAvatar()
|
|
```javascript
|
|
AvatarSystem.saveUserAvatar(userId, avatar) → Promise<boolean>
|
|
```
|
|
Save a user's avatar to the server.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `userId` | string | Yes | User identifier |
|
|
| `avatar` | Avatar | Yes | Avatar to save |
|
|
|
|
**Returns:** `Promise<boolean>` - Success status
|
|
|
|
---
|
|
|
|
#### render()
|
|
```javascript
|
|
AvatarSystem.render(avatar, mode, ctx, x, y, options) → void
|
|
```
|
|
Render an avatar to a canvas context.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `avatar` | Avatar | Yes | Avatar to render |
|
|
| `mode` | string | Yes | Render mode |
|
|
| `ctx` | CanvasRenderingContext2D | Yes | Canvas context |
|
|
| `x` | number | Yes | X position |
|
|
| `y` | number | Yes | Y position |
|
|
| `options` | Object | No | Rendering options |
|
|
| `options.scale` | number | No | Scale factor (default: 1) |
|
|
| `options.flip` | boolean | No | Flip horizontally |
|
|
| `options.animation` | string | No | Current animation |
|
|
| `options.frame` | number | No | Animation frame |
|
|
|
|
**Render Modes:**
|
|
- `full` - Full avatar with all details
|
|
- `portrait` - Head and shoulders only
|
|
- `icon` - Small icon version
|
|
- `silhouette` - Solid color silhouette
|
|
- `game` - Optimized for gameplay
|
|
|
|
**Example:**
|
|
```javascript
|
|
AvatarSystem.render(avatar, 'game', ctx, playerX, playerY, {
|
|
scale: 2,
|
|
flip: facingLeft,
|
|
animation: 'walk',
|
|
frame: Math.floor(time * 10) % 8
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
#### renderToImage()
|
|
```javascript
|
|
AvatarSystem.renderToImage(avatar, mode, options) → Promise<HTMLImageElement>
|
|
```
|
|
Render avatar to an image element.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `avatar` | Avatar | Yes | Avatar to render |
|
|
| `mode` | string | Yes | Render mode |
|
|
| `options` | Object | No | Rendering options |
|
|
| `options.width` | number | No | Output width |
|
|
| `options.height` | number | No | Output height |
|
|
|
|
**Returns:** `Promise<HTMLImageElement>` - Rendered image
|
|
|
|
---
|
|
|
|
#### equipAccessory()
|
|
```javascript
|
|
AvatarSystem.equipAccessory(avatar, slot, itemId) → boolean
|
|
```
|
|
Equip an accessory to an avatar.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `avatar` | Avatar | Yes | Avatar to modify |
|
|
| `slot` | string | Yes | Accessory slot |
|
|
| `itemId` | string | Yes | Accessory ID |
|
|
|
|
**Accessory Slots:**
|
|
- `head` - Hats, helmets, headbands
|
|
- `face` - Glasses, masks
|
|
- `neck` - Necklaces, scarves
|
|
- `hand-left` - Left hand items
|
|
- `hand-right` - Right hand items
|
|
- `back` - Capes, wings, backpacks
|
|
- `pet` - Companion pets
|
|
|
|
**Returns:** `boolean` - True if equipped successfully
|
|
|
|
**Example:**
|
|
```javascript
|
|
AvatarSystem.equipAccessory(avatar, 'head', 'wizard-hat');
|
|
AvatarSystem.equipAccessory(avatar, 'pet', 'dragon-hatchling');
|
|
```
|
|
|
|
---
|
|
|
|
#### unequipAccessory()
|
|
```javascript
|
|
AvatarSystem.unequipAccessory(avatar, slot) → string | null
|
|
```
|
|
Remove an accessory from a slot.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `avatar` | Avatar | Yes | Avatar to modify |
|
|
| `slot` | string | Yes | Slot to clear |
|
|
|
|
**Returns:** `string | null` - Removed item ID or null if empty
|
|
|
|
---
|
|
|
|
#### getAccessories()
|
|
```javascript
|
|
AvatarSystem.getAccessories(category) → Array<Accessory>
|
|
```
|
|
Get available accessories by category.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `category` | string | No | Filter by category |
|
|
|
|
**Returns:** `Array<Accessory>`
|
|
```javascript
|
|
{
|
|
id: string,
|
|
name: string,
|
|
slot: string,
|
|
category: string,
|
|
unlockLevel: number,
|
|
rarity: 'common' | 'uncommon' | 'rare' | 'epic' | 'legendary'
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### customize()
|
|
```javascript
|
|
AvatarSystem.customize(avatar, changes) → Avatar
|
|
```
|
|
Apply customization changes to an avatar.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `avatar` | Avatar | Yes | Avatar to modify |
|
|
| `changes` | Object | Yes | Customization changes |
|
|
|
|
**Returns:** `Avatar` - Modified avatar (same reference)
|
|
|
|
**Example:**
|
|
```javascript
|
|
AvatarSystem.customize(avatar, {
|
|
hairColor: '#ff0000',
|
|
outfit: 'knight-armor'
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
#### validate()
|
|
```javascript
|
|
AvatarSystem.validate(avatar) → ValidationResult
|
|
```
|
|
Validate an avatar object.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `avatar` | Avatar | Yes | Avatar to validate |
|
|
|
|
**Returns:** `ValidationResult`
|
|
```javascript
|
|
{
|
|
valid: boolean,
|
|
errors: Array<string>,
|
|
warnings: Array<string>
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### clone()
|
|
```javascript
|
|
AvatarSystem.clone(avatar) → Avatar
|
|
```
|
|
Create a deep copy of an avatar.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `avatar` | Avatar | Yes | Avatar to clone |
|
|
|
|
**Returns:** `Avatar` - New avatar copy
|
|
|
|
---
|
|
|
|
#### export()
|
|
```javascript
|
|
AvatarSystem.export(avatar) → string
|
|
```
|
|
Export avatar to a JSON string.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `avatar` | Avatar | Yes | Avatar to export |
|
|
|
|
**Returns:** `string` - JSON representation
|
|
|
|
---
|
|
|
|
#### import()
|
|
```javascript
|
|
AvatarSystem.import(json) → Avatar
|
|
```
|
|
Import avatar from JSON string.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `json` | string | Yes | JSON avatar data |
|
|
|
|
**Returns:** `Avatar` - Imported avatar
|
|
|
|
---
|
|
|
|
#### getPartOptions()
|
|
```javascript
|
|
AvatarSystem.getPartOptions(category) → Array<PartOption>
|
|
```
|
|
Get all options for an avatar part category.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `category` | string | Yes | Part category |
|
|
|
|
**Categories:** `base`, `hair`, `eyes`, `mouth`, `outfit`, `shoes`
|
|
|
|
**Returns:** `Array<PartOption>`
|
|
```javascript
|
|
{
|
|
id: string,
|
|
name: string,
|
|
preview: string, // Preview image URL
|
|
unlockLevel: number,
|
|
colors: Array<string> // Available color options
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### getAnimations()
|
|
```javascript
|
|
AvatarSystem.getAnimations(avatar) → Array<string>
|
|
```
|
|
Get available animations for an avatar.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `avatar` | Avatar | Yes | Avatar to check |
|
|
|
|
**Returns:** `Array<string>` - Animation names
|
|
|
|
**Standard Animations:**
|
|
- `idle`
|
|
- `walk`
|
|
- `run`
|
|
- `jump`
|
|
- `fall`
|
|
- `land`
|
|
- `attack`
|
|
- `hurt`
|
|
- `die`
|
|
- `celebrate`
|
|
|
|
---
|
|
|
|
## ContextRenderer
|
|
|
|
Applies and renders game contexts on avatars. Contexts define how avatars behave and appear in different game types.
|
|
|
|
### Methods
|
|
|
|
#### apply()
|
|
```javascript
|
|
ContextRenderer.apply(avatar, contextId, options) → AvatarWithContext
|
|
```
|
|
Apply a game context to an avatar.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `avatar` | Avatar | Yes | Base avatar |
|
|
| `contextId` | string | Yes | Context to apply |
|
|
| `options` | Object | No | Context options |
|
|
| `options.variant` | string | No | Context variant |
|
|
| `options.color` | string | No | Primary color override |
|
|
| `options.preserveAccessories` | boolean | No | Keep equipped accessories |
|
|
|
|
**Returns:** `AvatarWithContext` - Avatar with applied context
|
|
|
|
**AvatarWithContext Object:**
|
|
```javascript
|
|
{
|
|
avatar: Avatar,
|
|
context: Context,
|
|
variant: string,
|
|
state: {
|
|
animation: string,
|
|
frame: number,
|
|
direction: 'left' | 'right',
|
|
effects: Array<string>
|
|
}
|
|
}
|
|
```
|
|
|
|
**Example:**
|
|
```javascript
|
|
const player = ContextRenderer.apply(avatar, 'platformer-standard', {
|
|
variant: 'hero',
|
|
preserveAccessories: true
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
#### remove()
|
|
```javascript
|
|
ContextRenderer.remove(avatarWithContext) → Avatar
|
|
```
|
|
Remove context from an avatar.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `avatarWithContext` | AvatarWithContext | Yes | Avatar with context |
|
|
|
|
**Returns:** `Avatar` - Original avatar
|
|
|
|
---
|
|
|
|
#### render()
|
|
```javascript
|
|
ContextRenderer.render(avatarWithContext, ctx, x, y, options) → void
|
|
```
|
|
Render an avatar with its context.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `avatarWithContext` | AvatarWithContext | Yes | Avatar with context |
|
|
| `ctx` | CanvasRenderingContext2D | Yes | Canvas context |
|
|
| `x` | number | Yes | X position |
|
|
| `y` | number | Yes | Y position |
|
|
| `options` | Object | No | Rendering options |
|
|
| `options.scale` | number | No | Scale factor |
|
|
| `options.time` | number | No | Time for animation |
|
|
| `options.debug` | boolean | No | Show hitboxes |
|
|
|
|
**Example:**
|
|
```javascript
|
|
function gameLoop(time) {
|
|
ctx.clearRect(0, 0, width, height);
|
|
ContextRenderer.render(player, ctx, playerX, playerY, {
|
|
scale: 2,
|
|
time: time / 1000
|
|
});
|
|
requestAnimationFrame(gameLoop);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### animate()
|
|
```javascript
|
|
ContextRenderer.animate(avatarWithContext, animationId, options) → boolean
|
|
```
|
|
Start or change an animation on an avatar.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `avatarWithContext` | AvatarWithContext | Yes | Avatar with context |
|
|
| `animationId` | string | Yes | Animation to play |
|
|
| `options` | Object | No | Animation options |
|
|
| `options.loop` | boolean | No | Loop animation (default: varies) |
|
|
| `options.speed` | number | No | Speed multiplier (default: 1) |
|
|
| `options.onComplete` | Function | No | Callback when animation ends |
|
|
|
|
**Returns:** `boolean` - True if animation started
|
|
|
|
**Example:**
|
|
```javascript
|
|
if (keys.ArrowRight) {
|
|
player.state.direction = 'right';
|
|
ContextRenderer.animate(player, 'run');
|
|
} else if (keys.ArrowLeft) {
|
|
player.state.direction = 'left';
|
|
ContextRenderer.animate(player, 'run');
|
|
} else {
|
|
ContextRenderer.animate(player, 'idle');
|
|
}
|
|
|
|
// One-shot animation with callback
|
|
ContextRenderer.animate(player, 'attack', {
|
|
loop: false,
|
|
onComplete: () => canAttack = true
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
#### stopAnimation()
|
|
```javascript
|
|
ContextRenderer.stopAnimation(avatarWithContext) → void
|
|
```
|
|
Stop the current animation, reverting to idle.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `avatarWithContext` | AvatarWithContext | Yes | Avatar with context |
|
|
|
|
---
|
|
|
|
#### addEffect()
|
|
```javascript
|
|
ContextRenderer.addEffect(avatarWithContext, effectId, options) → boolean
|
|
```
|
|
Add a visual effect to an avatar.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `avatarWithContext` | AvatarWithContext | Yes | Avatar with context |
|
|
| `effectId` | string | Yes | Effect to add |
|
|
| `options` | Object | No | Effect options |
|
|
| `options.duration` | number | No | Auto-remove after ms |
|
|
| `options.color` | string | No | Effect color |
|
|
| `options.intensity` | number | No | Effect intensity (0-1) |
|
|
|
|
**Available Effects:**
|
|
- `glow` - Outer glow
|
|
- `trail` - Motion trail
|
|
- `sparkle` - Sparkle particles
|
|
- `fire` - Fire aura
|
|
- `ice` - Ice crystals
|
|
- `electric` - Electric sparks
|
|
- `heal` - Healing particles
|
|
- `shield` - Shield bubble
|
|
- `speed-lines` - Speed effect
|
|
- `damage-flash` - Red flash
|
|
|
|
**Returns:** `boolean` - True if effect added
|
|
|
|
**Example:**
|
|
```javascript
|
|
// Temporary power-up glow
|
|
ContextRenderer.addEffect(player, 'glow', {
|
|
color: '#ffff00',
|
|
duration: 10000
|
|
});
|
|
|
|
// Damage feedback
|
|
ContextRenderer.addEffect(player, 'damage-flash', {
|
|
duration: 200
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
#### removeEffect()
|
|
```javascript
|
|
ContextRenderer.removeEffect(avatarWithContext, effectId) → boolean
|
|
```
|
|
Remove an effect from an avatar.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `avatarWithContext` | AvatarWithContext | Yes | Avatar with context |
|
|
| `effectId` | string | Yes | Effect to remove |
|
|
|
|
**Returns:** `boolean` - True if effect was removed
|
|
|
|
---
|
|
|
|
#### clearEffects()
|
|
```javascript
|
|
ContextRenderer.clearEffects(avatarWithContext) → void
|
|
```
|
|
Remove all effects from an avatar.
|
|
|
|
---
|
|
|
|
#### getHitbox()
|
|
```javascript
|
|
ContextRenderer.getHitbox(avatarWithContext, type) → Hitbox
|
|
```
|
|
Get collision hitbox for the avatar in current state.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `avatarWithContext` | AvatarWithContext | Yes | Avatar with context |
|
|
| `type` | string | No | Hitbox type (default: 'body') |
|
|
|
|
**Hitbox Types:**
|
|
- `body` - Main collision box
|
|
- `feet` - Ground detection
|
|
- `head` - Ceiling detection
|
|
- `attack` - Attack range (if attacking)
|
|
|
|
**Returns:** `Hitbox`
|
|
```javascript
|
|
{
|
|
x: number, // Relative to avatar position
|
|
y: number,
|
|
width: number,
|
|
height: number
|
|
}
|
|
```
|
|
|
|
**Example:**
|
|
```javascript
|
|
const hitbox = ContextRenderer.getHitbox(player, 'body');
|
|
const worldHitbox = {
|
|
x: playerX + hitbox.x,
|
|
y: playerY + hitbox.y,
|
|
width: hitbox.width,
|
|
height: hitbox.height
|
|
};
|
|
```
|
|
|
|
---
|
|
|
|
#### setDirection()
|
|
```javascript
|
|
ContextRenderer.setDirection(avatarWithContext, direction) → void
|
|
```
|
|
Set facing direction.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `avatarWithContext` | AvatarWithContext | Yes | Avatar with context |
|
|
| `direction` | string | Yes | 'left' or 'right' |
|
|
|
|
---
|
|
|
|
#### getAvailableAnimations()
|
|
```javascript
|
|
ContextRenderer.getAvailableAnimations(avatarWithContext) → Array<AnimationInfo>
|
|
```
|
|
Get all animations available for this context.
|
|
|
|
**Returns:** `Array<AnimationInfo>`
|
|
```javascript
|
|
{
|
|
id: string,
|
|
name: string,
|
|
frames: number,
|
|
duration: number, // ms per frame
|
|
loops: boolean
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## ContextCatalog
|
|
|
|
Catalog of all available game contexts.
|
|
|
|
### Methods
|
|
|
|
#### getAll()
|
|
```javascript
|
|
ContextCatalog.getAll() → Array<Context>
|
|
```
|
|
Get all available contexts.
|
|
|
|
**Returns:** `Array<Context>`
|
|
```javascript
|
|
{
|
|
id: string,
|
|
name: string,
|
|
description: string,
|
|
category: string,
|
|
variants: Array<string>,
|
|
animations: Array<string>,
|
|
gameStyles: Array<string>,
|
|
tags: Array<string>
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### get()
|
|
```javascript
|
|
ContextCatalog.get(contextId) → Context | null
|
|
```
|
|
Get a specific context by ID.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `contextId` | string | Yes | Context identifier |
|
|
|
|
**Returns:** `Context | null`
|
|
|
|
---
|
|
|
|
#### findByGameStyle()
|
|
```javascript
|
|
ContextCatalog.findByGameStyle(gameStyle) → Array<Context>
|
|
```
|
|
Find contexts compatible with a game style.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `gameStyle` | string | Yes | Game style |
|
|
|
|
**Returns:** `Array<Context>` - Compatible contexts
|
|
|
|
**Example:**
|
|
```javascript
|
|
const contexts = ContextCatalog.findByGameStyle('action-arcade');
|
|
// Returns shooter, platformer, fighting contexts
|
|
```
|
|
|
|
---
|
|
|
|
#### findByCategory()
|
|
```javascript
|
|
ContextCatalog.findByCategory(category) → Array<Context>
|
|
```
|
|
Find contexts by category.
|
|
|
|
**Categories:**
|
|
- `action` - Action game contexts
|
|
- `puzzle` - Puzzle game contexts
|
|
- `adventure` - Adventure contexts
|
|
- `vehicle` - Vehicle/racing contexts
|
|
- `sports` - Sports game contexts
|
|
- `special` - Special/unique contexts
|
|
|
|
---
|
|
|
|
#### search()
|
|
```javascript
|
|
ContextCatalog.search(query) → Array<Context>
|
|
```
|
|
Search contexts by name, description, or tags.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `query` | string | Yes | Search query |
|
|
|
|
**Returns:** `Array<Context>` - Matching contexts
|
|
|
|
---
|
|
|
|
#### getVariants()
|
|
```javascript
|
|
ContextCatalog.getVariants(contextId) → Array<VariantInfo>
|
|
```
|
|
Get all variants for a context.
|
|
|
|
**Returns:** `Array<VariantInfo>`
|
|
```javascript
|
|
{
|
|
id: string,
|
|
name: string,
|
|
description: string,
|
|
preview: string
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## AssetCatalog
|
|
|
|
Unified catalog for browsing all assets.
|
|
|
|
### Methods
|
|
|
|
#### browse()
|
|
```javascript
|
|
AssetCatalog.browse(category, options) → BrowseResult
|
|
```
|
|
Browse assets by category.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `category` | string | Yes | Asset category |
|
|
| `options` | Object | No | Browse options |
|
|
| `options.page` | number | No | Page number (default: 1) |
|
|
| `options.perPage` | number | No | Items per page (default: 20) |
|
|
| `options.sort` | string | No | Sort field |
|
|
| `options.filter` | Object | No | Filter criteria |
|
|
|
|
**Categories:** `music`, `backgrounds`, `contexts`, `accessories`, `presets`
|
|
|
|
**Returns:** `BrowseResult`
|
|
```javascript
|
|
{
|
|
items: Array<Asset>,
|
|
total: number,
|
|
page: number,
|
|
perPage: number,
|
|
totalPages: number
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### search()
|
|
```javascript
|
|
AssetCatalog.search(query, options) → SearchResult
|
|
```
|
|
Search across all asset categories.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `query` | string | Yes | Search query |
|
|
| `options` | Object | No | Search options |
|
|
| `options.categories` | Array | No | Limit to categories |
|
|
| `options.limit` | number | No | Max results (default: 50) |
|
|
|
|
**Returns:** `SearchResult`
|
|
```javascript
|
|
{
|
|
results: Array<{
|
|
category: string,
|
|
asset: Asset,
|
|
score: number
|
|
}>,
|
|
totalCount: number
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### getStats()
|
|
```javascript
|
|
AssetCatalog.getStats() → CatalogStats
|
|
```
|
|
Get statistics about the asset catalog.
|
|
|
|
**Returns:** `CatalogStats`
|
|
```javascript
|
|
{
|
|
music: { total: 160, byMood: Object },
|
|
backgrounds: { themes: 12, variants: 84 },
|
|
contexts: { total: 44, byCategory: Object },
|
|
accessories: { total: 280, bySlot: Object },
|
|
presets: { total: 50 }
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### getRecent()
|
|
```javascript
|
|
AssetCatalog.getRecent(category, limit) → Array<Asset>
|
|
```
|
|
Get recently added assets.
|
|
|
|
---
|
|
|
|
#### getPopular()
|
|
```javascript
|
|
AssetCatalog.getPopular(category, limit) → Array<Asset>
|
|
```
|
|
Get most popular/used assets.
|
|
|
|
---
|
|
|
|
## AssetPresets
|
|
|
|
Pre-configured asset combinations for quick setup.
|
|
|
|
### Methods
|
|
|
|
#### getAll()
|
|
```javascript
|
|
AssetPresets.getAll() → Array<Preset>
|
|
```
|
|
Get all available presets.
|
|
|
|
**Returns:** `Array<Preset>`
|
|
```javascript
|
|
{
|
|
id: string,
|
|
name: string,
|
|
description: string,
|
|
config: {
|
|
music: Object,
|
|
background: Object,
|
|
context: Object
|
|
},
|
|
thumbnail: string,
|
|
tags: Array<string>,
|
|
gameStyles: Array<string>
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### get()
|
|
```javascript
|
|
AssetPresets.get(presetId) → Preset | null
|
|
```
|
|
Get a specific preset.
|
|
|
|
---
|
|
|
|
#### findByGameStyle()
|
|
```javascript
|
|
AssetPresets.findByGameStyle(gameStyle) → Array<Preset>
|
|
```
|
|
Find presets matching a game style.
|
|
|
|
---
|
|
|
|
#### findByTags()
|
|
```javascript
|
|
AssetPresets.findByTags(tags, matchAll) → Array<Preset>
|
|
```
|
|
Find presets by tags.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `tags` | Array | Yes | Tags to match |
|
|
| `matchAll` | boolean | No | Require all tags (default: false) |
|
|
|
|
---
|
|
|
|
#### apply()
|
|
```javascript
|
|
AssetPresets.apply(presetId) → Promise<LoadedAssets>
|
|
```
|
|
Apply a preset, loading all its assets.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `presetId` | string | Yes | Preset identifier |
|
|
|
|
**Returns:** `Promise<LoadedAssets>` - Loaded asset references
|
|
|
|
**Example:**
|
|
```javascript
|
|
const assets = await AssetPresets.apply('retro-platformer');
|
|
MusicEngine.playSong(assets.music.song.id);
|
|
```
|
|
|
|
---
|
|
|
|
#### create()
|
|
```javascript
|
|
AssetPresets.create(name, config, metadata) → Preset
|
|
```
|
|
Create a custom preset (user presets).
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `name` | string | Yes | Preset name |
|
|
| `config` | Object | Yes | Asset configuration |
|
|
| `metadata` | Object | No | Additional metadata |
|
|
|
|
**Returns:** `Preset` - Created preset
|
|
|
|
---
|
|
|
|
#### save()
|
|
```javascript
|
|
AssetPresets.save(preset) → Promise<boolean>
|
|
```
|
|
Save a user preset to the server.
|
|
|
|
---
|
|
|
|
#### delete()
|
|
```javascript
|
|
AssetPresets.delete(presetId) → Promise<boolean>
|
|
```
|
|
Delete a user preset.
|
|
|
|
---
|
|
|
|
#### getUserPresets()
|
|
```javascript
|
|
AssetPresets.getUserPresets(userId) → Promise<Array<Preset>>
|
|
```
|
|
Get a user's saved presets.
|
|
|
|
---
|
|
|
|
## AssetCompatibility
|
|
|
|
Validates and checks compatibility between assets.
|
|
|
|
### Methods
|
|
|
|
#### validate()
|
|
```javascript
|
|
AssetCompatibility.validate(config) → ValidationResult
|
|
```
|
|
Validate an asset configuration for compatibility.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `config` | Object | Yes | Asset configuration |
|
|
|
|
**Returns:** `ValidationResult`
|
|
```javascript
|
|
{
|
|
valid: boolean,
|
|
errors: Array<{
|
|
code: string,
|
|
message: string,
|
|
field: string
|
|
}>,
|
|
warnings: Array<{
|
|
code: string,
|
|
message: string,
|
|
suggestion: string
|
|
}>
|
|
}
|
|
```
|
|
|
|
**Example:**
|
|
```javascript
|
|
const result = AssetCompatibility.validate({
|
|
music: { mood: 'Peaceful' },
|
|
background: { theme: 'horror', variant: 'haunted-house' },
|
|
context: { id: 'shooter-standard' }
|
|
});
|
|
|
|
console.log(result);
|
|
// {
|
|
// valid: true,
|
|
// errors: [],
|
|
// warnings: [
|
|
// {
|
|
// code: 'MOOD_MISMATCH',
|
|
// message: 'Peaceful music may not match horror theme',
|
|
// suggestion: 'Consider using Dark or Mysterious mood'
|
|
// }
|
|
// ]
|
|
// }
|
|
```
|
|
|
|
---
|
|
|
|
#### isCompatible()
|
|
```javascript
|
|
AssetCompatibility.isCompatible(asset1, asset2) → boolean
|
|
```
|
|
Check if two assets are compatible.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `asset1` | Object | Yes | First asset {type, id} |
|
|
| `asset2` | Object | Yes | Second asset {type, id} |
|
|
|
|
**Returns:** `boolean` - True if compatible
|
|
|
|
**Example:**
|
|
```javascript
|
|
const compatible = AssetCompatibility.isCompatible(
|
|
{ type: 'background', id: 'space:nebula' },
|
|
{ type: 'context', id: 'shooter-standard' }
|
|
);
|
|
// true
|
|
```
|
|
|
|
---
|
|
|
|
#### getCompatibleAssets()
|
|
```javascript
|
|
AssetCompatibility.getCompatibleAssets(asset, targetType) → Array<Asset>
|
|
```
|
|
Get assets compatible with a given asset.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `asset` | Object | Yes | Source asset {type, id} |
|
|
| `targetType` | string | Yes | Type of assets to find |
|
|
|
|
**Returns:** `Array<Asset>` - Compatible assets
|
|
|
|
**Example:**
|
|
```javascript
|
|
const backgrounds = AssetCompatibility.getCompatibleAssets(
|
|
{ type: 'context', id: 'platformer-standard' },
|
|
'background'
|
|
);
|
|
// Returns backgrounds suitable for platformers
|
|
```
|
|
|
|
---
|
|
|
|
#### suggestFixes()
|
|
```javascript
|
|
AssetCompatibility.suggestFixes(config) → Array<Suggestion>
|
|
```
|
|
Get suggestions to improve an asset configuration.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `config` | Object | Yes | Current configuration |
|
|
|
|
**Returns:** `Array<Suggestion>`
|
|
```javascript
|
|
{
|
|
type: 'music' | 'background' | 'context',
|
|
current: Object,
|
|
suggested: Object,
|
|
reason: string,
|
|
improvement: string
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### getMoodCompatibility()
|
|
```javascript
|
|
AssetCompatibility.getMoodCompatibility(mood, theme) → number
|
|
```
|
|
Get compatibility score between a music mood and background theme.
|
|
|
|
**Parameters:**
|
|
| Name | Type | Required | Description |
|
|
|------|------|----------|-------------|
|
|
| `mood` | string | Yes | Music mood |
|
|
| `theme` | string | Yes | Background theme |
|
|
|
|
**Returns:** `number` - Compatibility score (0-100)
|
|
|
|
**Example:**
|
|
```javascript
|
|
const score = AssetCompatibility.getMoodCompatibility('Epic', 'space');
|
|
// 95 - highly compatible
|
|
|
|
const score2 = AssetCompatibility.getMoodCompatibility('Peaceful', 'horror');
|
|
// 15 - poor compatibility
|
|
```
|
|
|
|
---
|
|
|
|
## Common Patterns
|
|
|
|
### Basic Game Setup
|
|
```javascript
|
|
async function initGame() {
|
|
// Initialize all systems
|
|
await AssetManager.initialize();
|
|
|
|
// Load game-specific assets
|
|
const assets = await AssetManager.loadGameAssets({
|
|
music: { mood: 'Upbeat' },
|
|
background: { theme: 'nature', variant: 'forest' },
|
|
context: { id: 'platformer-standard' }
|
|
});
|
|
|
|
// Start music
|
|
MusicEngine.playRandomSong('Upbeat');
|
|
|
|
// Load player avatar
|
|
const avatar = await AvatarSystem.loadUserAvatar(userId);
|
|
const player = ContextRenderer.apply(avatar, 'platformer-standard');
|
|
|
|
// Game loop
|
|
function gameLoop(timestamp) {
|
|
const time = timestamp / 1000;
|
|
|
|
// Clear canvas
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
|
// Render background
|
|
BackgroundEngine.render(
|
|
ctx,
|
|
'nature',
|
|
'forest',
|
|
canvas.width,
|
|
canvas.height,
|
|
time
|
|
);
|
|
|
|
// Update and render player
|
|
updatePlayer(player);
|
|
ContextRenderer.render(player, ctx, playerX, playerY, { time });
|
|
|
|
requestAnimationFrame(gameLoop);
|
|
}
|
|
|
|
requestAnimationFrame(gameLoop);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Switching Music Mood
|
|
```javascript
|
|
// Smooth transition when entering boss fight
|
|
async function onBossFight() {
|
|
await MusicEngine.fadeOut(1000);
|
|
MusicEngine.playRandomSong('Epic');
|
|
}
|
|
|
|
// Crossfade for seamless transition
|
|
function onAreaChange(newArea) {
|
|
const moodMap = {
|
|
forest: 'Peaceful',
|
|
dungeon: 'Dark',
|
|
boss: 'Epic',
|
|
victory: 'Upbeat'
|
|
};
|
|
|
|
const newMood = moodMap[newArea];
|
|
const songs = MusicEngine.findSongs({ mood: newMood });
|
|
const randomSong = songs[Math.floor(Math.random() * songs.length)];
|
|
|
|
MusicEngine.crossfade(randomSong.id, 2000);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Animation Control
|
|
```javascript
|
|
function updatePlayer(player) {
|
|
// Movement animations
|
|
if (keys.ArrowRight) {
|
|
ContextRenderer.setDirection(player, 'right');
|
|
if (isGrounded) {
|
|
ContextRenderer.animate(player, keys.Shift ? 'run' : 'walk');
|
|
}
|
|
playerX += keys.Shift ? 8 : 4;
|
|
} else if (keys.ArrowLeft) {
|
|
ContextRenderer.setDirection(player, 'left');
|
|
if (isGrounded) {
|
|
ContextRenderer.animate(player, keys.Shift ? 'run' : 'walk');
|
|
}
|
|
playerX -= keys.Shift ? 8 : 4;
|
|
} else if (isGrounded) {
|
|
ContextRenderer.animate(player, 'idle');
|
|
}
|
|
|
|
// Jump animation
|
|
if (keys.Space && isGrounded) {
|
|
ContextRenderer.animate(player, 'jump');
|
|
velocityY = -15;
|
|
isGrounded = false;
|
|
}
|
|
|
|
// Falling animation
|
|
if (!isGrounded && velocityY > 0) {
|
|
ContextRenderer.animate(player, 'fall');
|
|
}
|
|
|
|
// Attack animation (one-shot)
|
|
if (keys.z && canAttack) {
|
|
canAttack = false;
|
|
ContextRenderer.animate(player, 'attack', {
|
|
loop: false,
|
|
onComplete: () => {
|
|
canAttack = true;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Dynamic Background Effects
|
|
```javascript
|
|
// Weather system
|
|
class WeatherSystem {
|
|
constructor() {
|
|
this.currentWeather = 'clear';
|
|
}
|
|
|
|
setWeather(weather) {
|
|
// Remove old effects
|
|
BackgroundEngine.setGlobalEffect('rain', false);
|
|
BackgroundEngine.setGlobalEffect('snow', false);
|
|
BackgroundEngine.setGlobalEffect('fog', false);
|
|
BackgroundEngine.setGlobalEffect('lightning', false);
|
|
|
|
// Apply new weather
|
|
switch (weather) {
|
|
case 'rain':
|
|
BackgroundEngine.setGlobalEffect('rain', true);
|
|
MusicEngine.crossfade('rain-ambience', 2000);
|
|
break;
|
|
case 'storm':
|
|
BackgroundEngine.setGlobalEffect('rain', true);
|
|
BackgroundEngine.setGlobalEffect('lightning', true);
|
|
MusicEngine.crossfade('storm-dramatic', 2000);
|
|
break;
|
|
case 'snow':
|
|
BackgroundEngine.setGlobalEffect('snow', true);
|
|
MusicEngine.crossfade('winter-peaceful', 2000);
|
|
break;
|
|
case 'fog':
|
|
BackgroundEngine.setGlobalEffect('fog', true);
|
|
MusicEngine.crossfade('mysterious-ambient', 2000);
|
|
break;
|
|
}
|
|
|
|
this.currentWeather = weather;
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Power-up Effects
|
|
```javascript
|
|
function applyPowerUp(player, powerUpType) {
|
|
switch (powerUpType) {
|
|
case 'speed':
|
|
ContextRenderer.addEffect(player, 'speed-lines', {
|
|
duration: 10000,
|
|
color: '#00ffff'
|
|
});
|
|
playerSpeed *= 2;
|
|
setTimeout(() => playerSpeed /= 2, 10000);
|
|
break;
|
|
|
|
case 'shield':
|
|
ContextRenderer.addEffect(player, 'shield', {
|
|
duration: 15000,
|
|
color: '#4444ff'
|
|
});
|
|
isInvulnerable = true;
|
|
setTimeout(() => isInvulnerable = false, 15000);
|
|
break;
|
|
|
|
case 'fire':
|
|
ContextRenderer.addEffect(player, 'fire', {
|
|
color: '#ff4400'
|
|
});
|
|
attackDamage *= 2;
|
|
break;
|
|
|
|
case 'heal':
|
|
ContextRenderer.addEffect(player, 'heal', {
|
|
duration: 2000
|
|
});
|
|
health = Math.min(health + 30, maxHealth);
|
|
break;
|
|
}
|
|
}
|
|
|
|
function onPlayerHit(player, damage) {
|
|
if (isInvulnerable) return;
|
|
|
|
health -= damage;
|
|
|
|
// Visual feedback
|
|
ContextRenderer.addEffect(player, 'damage-flash', {
|
|
duration: 200
|
|
});
|
|
|
|
// Screen shake
|
|
screenShake(10, 200);
|
|
|
|
if (health <= 0) {
|
|
ContextRenderer.animate(player, 'die', {
|
|
loop: false,
|
|
onComplete: showGameOver
|
|
});
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Preset-Based Game Loading
|
|
```javascript
|
|
async function loadGameWithPreset(presetName) {
|
|
const preset = AssetManager.findPreset(presetName);
|
|
|
|
if (!preset) {
|
|
console.error(`Preset "${presetName}" not found`);
|
|
return null;
|
|
}
|
|
|
|
// Validate the preset
|
|
const validation = AssetCompatibility.validate(preset.config);
|
|
if (!validation.valid) {
|
|
console.error('Invalid preset:', validation.errors);
|
|
return null;
|
|
}
|
|
|
|
// Show any warnings
|
|
if (validation.warnings.length > 0) {
|
|
console.warn('Preset warnings:', validation.warnings);
|
|
}
|
|
|
|
// Load all assets
|
|
const assets = await AssetManager.loadGameAssets(preset.config);
|
|
|
|
return {
|
|
preset,
|
|
assets,
|
|
description: AssetManager.describeAssets(preset.config)
|
|
};
|
|
}
|
|
|
|
// Usage
|
|
const game = await loadGameWithPreset('retro-platformer');
|
|
console.log(game.description.summary);
|
|
// "8-bit chiptune music with pixelated forest background,
|
|
// featuring a classic platformer hero with retro animations"
|
|
```
|
|
|
|
---
|
|
|
|
### Responsive Asset Recommendations
|
|
```javascript
|
|
async function setupGameFromDescription(description, gameStyle) {
|
|
// Get AI-powered recommendations
|
|
const recommendations = AssetManager.getRecommendations(
|
|
gameStyle,
|
|
description
|
|
);
|
|
|
|
// Use the top recommendation
|
|
const topRec = recommendations[0];
|
|
console.log(`Selected: ${topRec.explanation} (score: ${topRec.score})`);
|
|
|
|
// Load the recommended assets
|
|
const assets = await AssetManager.loadGameAssets(topRec.config);
|
|
|
|
return {
|
|
assets,
|
|
config: topRec.config,
|
|
alternatives: recommendations.slice(1)
|
|
};
|
|
}
|
|
|
|
// Usage
|
|
const game = await setupGameFromDescription(
|
|
'A spooky adventure in a haunted mansion with ghosts and puzzles',
|
|
'adventure-story'
|
|
);
|
|
// Automatically selects dark/mysterious music, horror mansion background,
|
|
// and adventure context
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Music Not Playing
|
|
|
|
**Symptom:** `MusicEngine.playSong()` returns true but no sound.
|
|
|
|
**Solutions:**
|
|
1. **User interaction required:** Most browsers require user interaction before playing audio.
|
|
```javascript
|
|
document.addEventListener('click', () => {
|
|
MusicEngine.playRandomSong('Upbeat');
|
|
}, { once: true });
|
|
```
|
|
|
|
2. **Check volume:**
|
|
```javascript
|
|
console.log('Volume:', MusicEngine.getVolume());
|
|
console.log('Muted:', MusicEngine.muted);
|
|
MusicEngine.setVolume(0.7);
|
|
MusicEngine.unmute();
|
|
```
|
|
|
|
3. **Ensure initialization:**
|
|
```javascript
|
|
await AssetManager.initialize();
|
|
// or
|
|
await MusicEngine.initialize();
|
|
```
|
|
|
|
---
|
|
|
|
### Background Not Animating
|
|
|
|
**Symptom:** Background appears static, not moving.
|
|
|
|
**Solutions:**
|
|
1. **Pass time parameter:** The time must increase each frame.
|
|
```javascript
|
|
// Wrong - time is always 0
|
|
BackgroundEngine.render(ctx, theme, variant, w, h, 0);
|
|
|
|
// Correct - time increases
|
|
function gameLoop(timestamp) {
|
|
const time = timestamp / 1000; // Convert to seconds
|
|
BackgroundEngine.render(ctx, theme, variant, w, h, time);
|
|
requestAnimationFrame(gameLoop);
|
|
}
|
|
```
|
|
|
|
2. **Time should be in seconds:**
|
|
```javascript
|
|
// Wrong - milliseconds
|
|
BackgroundEngine.render(ctx, theme, variant, w, h, Date.now());
|
|
|
|
// Correct - seconds
|
|
BackgroundEngine.render(ctx, theme, variant, w, h, Date.now() / 1000);
|
|
```
|
|
|
|
---
|
|
|
|
### Avatar Not Rendering
|
|
|
|
**Symptom:** Avatar appears blank or throws errors.
|
|
|
|
**Solutions:**
|
|
1. **Validate avatar object:**
|
|
```javascript
|
|
const validation = AvatarSystem.validate(avatar);
|
|
if (!validation.valid) {
|
|
console.error('Avatar errors:', validation.errors);
|
|
avatar = AvatarSystem.create(); // Use default
|
|
}
|
|
```
|
|
|
|
2. **Check mode is valid:**
|
|
```javascript
|
|
// Valid modes: 'full', 'portrait', 'icon', 'silhouette', 'game'
|
|
AvatarSystem.render(avatar, 'game', ctx, x, y);
|
|
```
|
|
|
|
3. **Ensure context is applied for game rendering:**
|
|
```javascript
|
|
// If using ContextRenderer, must apply context first
|
|
const player = ContextRenderer.apply(avatar, 'platformer-standard');
|
|
ContextRenderer.render(player, ctx, x, y);
|
|
```
|
|
|
|
---
|
|
|
|
### Context Mismatch
|
|
|
|
**Symptom:** Avatar looks wrong or animations don't work.
|
|
|
|
**Solutions:**
|
|
1. **Validate configuration:**
|
|
```javascript
|
|
const result = AssetCompatibility.validate({
|
|
context: { id: 'shooter-standard' },
|
|
background: { theme: 'nature', variant: 'forest' }
|
|
});
|
|
|
|
if (result.warnings.length > 0) {
|
|
console.warn('Compatibility warnings:', result.warnings);
|
|
}
|
|
```
|
|
|
|
2. **Check game style compatibility:**
|
|
```javascript
|
|
const contexts = ContextCatalog.findByGameStyle('action-arcade');
|
|
console.log('Compatible contexts:', contexts.map(c => c.id));
|
|
```
|
|
|
|
3. **Use recommendations:**
|
|
```javascript
|
|
const recs = AssetManager.getRecommendations('action-arcade', 'space shooter');
|
|
const bestContext = recs[0].config.context;
|
|
```
|
|
|
|
---
|
|
|
|
### Performance Issues
|
|
|
|
**Symptom:** Game runs slowly or stutters.
|
|
|
|
**Solutions:**
|
|
1. **Reduce background effects:**
|
|
```javascript
|
|
// Disable expensive effects
|
|
BackgroundEngine.render(ctx, theme, variant, w, h, time, {
|
|
effects: [] // No effects
|
|
});
|
|
```
|
|
|
|
2. **Use static backgrounds for menus:**
|
|
```javascript
|
|
// Render once instead of every frame
|
|
BackgroundEngine.renderStatic(ctx, theme, variant, w, h);
|
|
```
|
|
|
|
3. **Preload assets:**
|
|
```javascript
|
|
await BackgroundEngine.preloadTheme('nature');
|
|
await AssetManager.initialize({ preloadBackgrounds: true });
|
|
```
|
|
|
|
4. **Use simpler render modes:**
|
|
```javascript
|
|
// Use 'game' mode instead of 'full' for gameplay
|
|
AvatarSystem.render(avatar, 'game', ctx, x, y);
|
|
```
|
|
|
|
---
|
|
|
|
### Asset Not Found
|
|
|
|
**Symptom:** Methods return null or false.
|
|
|
|
**Solutions:**
|
|
1. **Check asset exists:**
|
|
```javascript
|
|
const song = MusicEngine.getSongInfo('my-song-id');
|
|
if (!song) {
|
|
console.error('Song not found. Available songs:');
|
|
console.log(MusicEngine.getCatalog().map(s => s.id));
|
|
}
|
|
```
|
|
|
|
2. **Search for similar assets:**
|
|
```javascript
|
|
const results = AssetManager.searchAssets('forest', {
|
|
types: ['background']
|
|
});
|
|
console.log('Found backgrounds:', results.backgrounds);
|
|
```
|
|
|
|
3. **Use fallbacks:**
|
|
```javascript
|
|
const preset = AssetManager.findPreset('my-preset')
|
|
|| AssetManager.findPreset('default-platformer');
|
|
```
|
|
|
|
---
|
|
|
|
## Error Codes
|
|
|
|
| Code | Description | Solution |
|
|
|------|-------------|----------|
|
|
| `ASSET_NOT_FOUND` | Requested asset doesn't exist | Check asset ID, use search |
|
|
| `INVALID_MOOD` | Music mood not recognized | Use `MusicEngine.getMoods()` |
|
|
| `INVALID_THEME` | Background theme not recognized | Use `BackgroundEngine.getThemes()` |
|
|
| `INVALID_CONTEXT` | Context ID not recognized | Use `ContextCatalog.getAll()` |
|
|
| `INCOMPATIBLE_ASSETS` | Assets don't work together | Use `AssetCompatibility.suggestFixes()` |
|
|
| `NOT_INITIALIZED` | System not initialized | Call `AssetManager.initialize()` |
|
|
| `AUDIO_BLOCKED` | Browser blocked audio | Require user interaction first |
|
|
| `AVATAR_INVALID` | Malformed avatar object | Use `AvatarSystem.validate()` |
|
|
| `CONTEXT_REQUIRED` | Operation requires context | Use `ContextRenderer.apply()` |
|
|
| `ANIMATION_NOT_FOUND` | Animation doesn't exist for context | Use `ContextRenderer.getAvailableAnimations()` |
|
|
|
|
---
|
|
|
|
## Version History
|
|
|
|
| Version | Date | Changes |
|
|
|---------|------|---------|
|
|
| 2.0.0 | 2026-02-05 | Added ContextRenderer, expanded MusicEngine |
|
|
| 1.5.0 | 2026-01-15 | Added AssetCompatibility, presets system |
|
|
| 1.0.0 | 2025-12-01 | Initial release |
|