63 KiB
API Reference
Complete API reference for all asset systems in the Game Arcade platform.
Table of Contents
- AssetManager
- MusicEngine
- BackgroundEngine
- AvatarSystem
- ContextRenderer
- ContextCatalog
- AssetCatalog
- AssetPresets
- AssetCompatibility
- Common Patterns
- 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()
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:
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()
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-arcadepuzzle-logicadventure-storyeducationalsimulationsports-racingstrategyrhythm-musichorror-survivalcasual-relaxingmultiplayer-party
Valid Moods:
EpicChillDarkUpbeatMysteriousRetroDramaticPeaceful
Returns: Array<Recommendation> - Top 3 recommendations
Recommendation Object:
{
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:
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()
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:
{
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:
const preset = AssetManager.findPreset('retro-platformer');
if (preset) {
await AssetManager.loadGameAssets(preset.config);
}
loadGameAssets()
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:
{
music: {
song: Song,
ready: boolean
},
background: {
theme: Theme,
variant: Variant,
renderFn: Function
},
context: {
context: Context,
sprites: Map<string, Sprite>
}
}
Example:
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()
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
{
valid: boolean,
errors: Array<string>,
warnings: Array<string>,
suggestions: Array<string>
}
Example:
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()
AssetManager.describeAssets(config) → AssetDescription
Get human-readable descriptions of an asset configuration.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
config |
Object | Yes | Asset configuration |
Returns: AssetDescription
{
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:
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()
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 assetscontrast- Opposite mood, complementary visualsrandom- Random compatible combinationseasonal- Seasonal variation if available
Returns: Object - New configuration object
Example:
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()
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
{
music: Array<Song>,
backgrounds: Array<{theme, variant}>,
contexts: Array<Context>,
presets: Array<Preset>,
totalCount: number
}
Example:
const results = AssetManager.searchAssets('forest', {
types: ['background', 'music'],
limit: 5
});
console.log(results.backgrounds);
// [{ theme: 'nature', variant: 'forest' },
// { theme: 'nature', variant: 'enchanted-forest' }]
getRandomCombination()
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:
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()
MusicEngine.initialize() → Promise<void>
Initialize the music engine. Called automatically by AssetManager.
Example:
await MusicEngine.initialize();
playRandomSong()
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:
const songId = MusicEngine.playRandomSong('Epic');
console.log(`Now playing: ${songId}`);
playSong()
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:
if (MusicEngine.playSong('epic-battle-04')) {
console.log('Song started');
} else {
console.log('Song not found');
}
stopMusic()
MusicEngine.stopMusic() → void
Stop the currently playing music immediately.
Example:
MusicEngine.stopMusic();
pauseMusic()
MusicEngine.pauseMusic() → void
Pause the currently playing music. Can be resumed with resumeMusic().
Example:
MusicEngine.pauseMusic();
resumeMusic()
MusicEngine.resumeMusic() → void
Resume paused music.
Example:
MusicEngine.resumeMusic();
setVolume()
MusicEngine.setVolume(level) → void
Set the music volume.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
level |
number | Yes | Volume level (0-1) |
Example:
MusicEngine.setVolume(0.7); // 70% volume
getVolume()
MusicEngine.getVolume() → number
Get the current volume level.
Returns: number - Current volume (0-1)
mute()
MusicEngine.mute() → void
Mute audio without changing volume setting.
unmute()
MusicEngine.unmute() → void
Unmute audio, restoring previous volume.
fadeOut()
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:
await MusicEngine.fadeOut(2000); // 2 second fade
MusicEngine.playRandomSong('Dark');
fadeIn()
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:
await MusicEngine.fadeIn('peaceful-meadow-02', 1500);
crossfade()
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:
await MusicEngine.crossfade('epic-battle-04', 1500);
getCatalog()
MusicEngine.getCatalog() → Array<Song>
Get all available songs.
Returns: Array<Song> - All songs in the catalog
Song Object:
{
id: string,
name: string,
mood: string,
tempo: number, // BPM
duration: number, // seconds
instruments: Array<string>,
tags: Array<string>,
intensity: number // 1-10
}
Example:
const songs = MusicEngine.getCatalog();
console.log(`Total songs: ${songs.length}`); // 160
findSongs()
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:
const songs = MusicEngine.findSongs({
mood: 'Epic',
minTempo: 120,
intensity: [7, 10]
});
getSongsByMood()
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:
const epicSongs = MusicEngine.getSongsByMood('Epic');
console.log(`Epic songs: ${epicSongs.length}`); // 20
getMoods()
MusicEngine.getMoods() → Array<string>
Get all available mood categories.
Returns: Array<string> - Available moods
Example:
const moods = MusicEngine.getMoods();
// ['Epic', 'Chill', 'Dark', 'Upbeat', 'Mysterious', 'Retro', 'Dramatic', 'Peaceful']
getSongInfo()
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()
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:
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 | Available theme names |
activeEffects |
Array | Currently active effects |
Methods
initialize()
BackgroundEngine.initialize() → Promise<void>
Initialize the background engine. Called automatically by AssetManager.
render()
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 particlesrain- Rain effectsnow- Snow effectfog- Fog overlaylightning- Lightning flashesstars-twinkle- Twinkling starsclouds-moving- Moving cloudsleaves-falling- Falling leavesfireflies- Glowing firefliesheat-distortion- Heat wave effect
Example:
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()
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:
// Render once for menu screens
BackgroundEngine.renderStatic(ctx, 'castle', 'entrance', 800, 600);
getThemes()
BackgroundEngine.getThemes() → Array<string>
Get all available theme names.
Returns: Array<string> - Theme names
Example:
const themes = BackgroundEngine.getThemes();
// ['nature', 'space', 'underwater', 'castle', 'city', 'desert',
// 'arctic', 'cave', 'sky', 'abstract', 'horror', 'fantasy']
getVariants()
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:
const variants = BackgroundEngine.getVariants('nature');
// ['forest', 'meadow', 'mountain', 'river', 'beach', 'jungle', 'autumn-forest']
getThemeInfo()
BackgroundEngine.getThemeInfo(theme) → ThemeInfo | null
Get detailed information about a theme.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
theme |
string | Yes | Theme name |
Returns: ThemeInfo | null
{
name: string,
description: string,
variants: Array<{
name: string,
description: string,
colors: Array<string>,
suggestedEffects: Array<string>
}>,
compatibleMoods: Array<string>,
tags: Array<string>
}
getEffects()
BackgroundEngine.getEffects() → Array<EffectInfo>
Get all available visual effects.
Returns: Array<EffectInfo>
{
id: string,
name: string,
description: string,
performance: 'low' | 'medium' | 'high',
compatibleThemes: Array<string> | 'all'
}
preloadTheme()
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()
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:
const renderForest = BackgroundEngine.createRenderFunction(
'nature',
'forest',
{ effects: ['fog'] }
);
function gameLoop(time) {
renderForest(ctx, canvas.width, canvas.height, time / 1000);
requestAnimationFrame(gameLoop);
}
setGlobalEffect()
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()
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:
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()
AvatarSystem.initialize() → Promise<void>
Initialize the avatar system. Called automatically by AssetManager.
create()
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:
{
id: string,
version: number,
customization: Object,
accessories: Map<string, string>,
createdAt: Date,
updatedAt: Date
}
Example:
const avatar = AvatarSystem.create({
base: 'humanoid',
skinTone: '#f5d0b0',
hairStyle: 'spiky',
hairColor: '#3d2314',
eyes: 'round',
eyeColor: '#4a90d9',
outfit: 'casual-tee'
});
createRandom()
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:
const randomAvatar = AvatarSystem.createRandom({
style: 'fantasy'
});
loadUserAvatar()
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:
const avatar = await AvatarSystem.loadUserAvatar(currentUser.id);
saveUserAvatar()
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()
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 detailsportrait- Head and shoulders onlyicon- Small icon versionsilhouette- Solid color silhouettegame- Optimized for gameplay
Example:
AvatarSystem.render(avatar, 'game', ctx, playerX, playerY, {
scale: 2,
flip: facingLeft,
animation: 'walk',
frame: Math.floor(time * 10) % 8
});
renderToImage()
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()
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, headbandsface- Glasses, masksneck- Necklaces, scarveshand-left- Left hand itemshand-right- Right hand itemsback- Capes, wings, backpackspet- Companion pets
Returns: boolean - True if equipped successfully
Example:
AvatarSystem.equipAccessory(avatar, 'head', 'wizard-hat');
AvatarSystem.equipAccessory(avatar, 'pet', 'dragon-hatchling');
unequipAccessory()
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()
AvatarSystem.getAccessories(category) → Array<Accessory>
Get available accessories by category.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
category |
string | No | Filter by category |
Returns: Array<Accessory>
{
id: string,
name: string,
slot: string,
category: string,
unlockLevel: number,
rarity: 'common' | 'uncommon' | 'rare' | 'epic' | 'legendary'
}
customize()
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:
AvatarSystem.customize(avatar, {
hairColor: '#ff0000',
outfit: 'knight-armor'
});
validate()
AvatarSystem.validate(avatar) → ValidationResult
Validate an avatar object.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
avatar |
Avatar | Yes | Avatar to validate |
Returns: ValidationResult
{
valid: boolean,
errors: Array<string>,
warnings: Array<string>
}
clone()
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()
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()
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()
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>
{
id: string,
name: string,
preview: string, // Preview image URL
unlockLevel: number,
colors: Array<string> // Available color options
}
getAnimations()
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:
idlewalkrunjumpfalllandattackhurtdiecelebrate
ContextRenderer
Applies and renders game contexts on avatars. Contexts define how avatars behave and appear in different game types.
Methods
apply()
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:
{
avatar: Avatar,
context: Context,
variant: string,
state: {
animation: string,
frame: number,
direction: 'left' | 'right',
effects: Array<string>
}
}
Example:
const player = ContextRenderer.apply(avatar, 'platformer-standard', {
variant: 'hero',
preserveAccessories: true
});
remove()
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()
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:
function gameLoop(time) {
ctx.clearRect(0, 0, width, height);
ContextRenderer.render(player, ctx, playerX, playerY, {
scale: 2,
time: time / 1000
});
requestAnimationFrame(gameLoop);
}
animate()
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:
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()
ContextRenderer.stopAnimation(avatarWithContext) → void
Stop the current animation, reverting to idle.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
avatarWithContext |
AvatarWithContext | Yes | Avatar with context |
addEffect()
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 glowtrail- Motion trailsparkle- Sparkle particlesfire- Fire auraice- Ice crystalselectric- Electric sparksheal- Healing particlesshield- Shield bubblespeed-lines- Speed effectdamage-flash- Red flash
Returns: boolean - True if effect added
Example:
// Temporary power-up glow
ContextRenderer.addEffect(player, 'glow', {
color: '#ffff00',
duration: 10000
});
// Damage feedback
ContextRenderer.addEffect(player, 'damage-flash', {
duration: 200
});
removeEffect()
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()
ContextRenderer.clearEffects(avatarWithContext) → void
Remove all effects from an avatar.
getHitbox()
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 boxfeet- Ground detectionhead- Ceiling detectionattack- Attack range (if attacking)
Returns: Hitbox
{
x: number, // Relative to avatar position
y: number,
width: number,
height: number
}
Example:
const hitbox = ContextRenderer.getHitbox(player, 'body');
const worldHitbox = {
x: playerX + hitbox.x,
y: playerY + hitbox.y,
width: hitbox.width,
height: hitbox.height
};
setDirection()
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()
ContextRenderer.getAvailableAnimations(avatarWithContext) → Array<AnimationInfo>
Get all animations available for this context.
Returns: Array<AnimationInfo>
{
id: string,
name: string,
frames: number,
duration: number, // ms per frame
loops: boolean
}
ContextCatalog
Catalog of all available game contexts.
Methods
getAll()
ContextCatalog.getAll() → Array<Context>
Get all available contexts.
Returns: Array<Context>
{
id: string,
name: string,
description: string,
category: string,
variants: Array<string>,
animations: Array<string>,
gameStyles: Array<string>,
tags: Array<string>
}
get()
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()
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:
const contexts = ContextCatalog.findByGameStyle('action-arcade');
// Returns shooter, platformer, fighting contexts
findByCategory()
ContextCatalog.findByCategory(category) → Array<Context>
Find contexts by category.
Categories:
action- Action game contextspuzzle- Puzzle game contextsadventure- Adventure contextsvehicle- Vehicle/racing contextssports- Sports game contextsspecial- Special/unique contexts
search()
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()
ContextCatalog.getVariants(contextId) → Array<VariantInfo>
Get all variants for a context.
Returns: Array<VariantInfo>
{
id: string,
name: string,
description: string,
preview: string
}
AssetCatalog
Unified catalog for browsing all assets.
Methods
browse()
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
{
items: Array<Asset>,
total: number,
page: number,
perPage: number,
totalPages: number
}
search()
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
{
results: Array<{
category: string,
asset: Asset,
score: number
}>,
totalCount: number
}
getStats()
AssetCatalog.getStats() → CatalogStats
Get statistics about the asset catalog.
Returns: CatalogStats
{
music: { total: 160, byMood: Object },
backgrounds: { themes: 12, variants: 84 },
contexts: { total: 44, byCategory: Object },
accessories: { total: 280, bySlot: Object },
presets: { total: 50 }
}
getRecent()
AssetCatalog.getRecent(category, limit) → Array<Asset>
Get recently added assets.
getPopular()
AssetCatalog.getPopular(category, limit) → Array<Asset>
Get most popular/used assets.
AssetPresets
Pre-configured asset combinations for quick setup.
Methods
getAll()
AssetPresets.getAll() → Array<Preset>
Get all available presets.
Returns: Array<Preset>
{
id: string,
name: string,
description: string,
config: {
music: Object,
background: Object,
context: Object
},
thumbnail: string,
tags: Array<string>,
gameStyles: Array<string>
}
get()
AssetPresets.get(presetId) → Preset | null
Get a specific preset.
findByGameStyle()
AssetPresets.findByGameStyle(gameStyle) → Array<Preset>
Find presets matching a game style.
findByTags()
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()
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:
const assets = await AssetPresets.apply('retro-platformer');
MusicEngine.playSong(assets.music.song.id);
create()
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()
AssetPresets.save(preset) → Promise<boolean>
Save a user preset to the server.
delete()
AssetPresets.delete(presetId) → Promise<boolean>
Delete a user preset.
getUserPresets()
AssetPresets.getUserPresets(userId) → Promise<Array<Preset>>
Get a user's saved presets.
AssetCompatibility
Validates and checks compatibility between assets.
Methods
validate()
AssetCompatibility.validate(config) → ValidationResult
Validate an asset configuration for compatibility.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
config |
Object | Yes | Asset configuration |
Returns: ValidationResult
{
valid: boolean,
errors: Array<{
code: string,
message: string,
field: string
}>,
warnings: Array<{
code: string,
message: string,
suggestion: string
}>
}
Example:
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()
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:
const compatible = AssetCompatibility.isCompatible(
{ type: 'background', id: 'space:nebula' },
{ type: 'context', id: 'shooter-standard' }
);
// true
getCompatibleAssets()
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:
const backgrounds = AssetCompatibility.getCompatibleAssets(
{ type: 'context', id: 'platformer-standard' },
'background'
);
// Returns backgrounds suitable for platformers
suggestFixes()
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>
{
type: 'music' | 'background' | 'context',
current: Object,
suggested: Object,
reason: string,
improvement: string
}
getMoodCompatibility()
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:
const score = AssetCompatibility.getMoodCompatibility('Epic', 'space');
// 95 - highly compatible
const score2 = AssetCompatibility.getMoodCompatibility('Peaceful', 'horror');
// 15 - poor compatibility
Common Patterns
Basic Game Setup
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
// 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
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
// 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
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
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
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:
- User interaction required: Most browsers require user interaction before playing audio.
document.addEventListener('click', () => {
MusicEngine.playRandomSong('Upbeat');
}, { once: true });
- Check volume:
console.log('Volume:', MusicEngine.getVolume());
console.log('Muted:', MusicEngine.muted);
MusicEngine.setVolume(0.7);
MusicEngine.unmute();
- Ensure initialization:
await AssetManager.initialize();
// or
await MusicEngine.initialize();
Background Not Animating
Symptom: Background appears static, not moving.
Solutions:
- Pass time parameter: The time must increase each frame.
// 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);
}
- Time should be in seconds:
// 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:
- Validate avatar object:
const validation = AvatarSystem.validate(avatar);
if (!validation.valid) {
console.error('Avatar errors:', validation.errors);
avatar = AvatarSystem.create(); // Use default
}
- Check mode is valid:
// Valid modes: 'full', 'portrait', 'icon', 'silhouette', 'game'
AvatarSystem.render(avatar, 'game', ctx, x, y);
- Ensure context is applied for game rendering:
// 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:
- Validate configuration:
const result = AssetCompatibility.validate({
context: { id: 'shooter-standard' },
background: { theme: 'nature', variant: 'forest' }
});
if (result.warnings.length > 0) {
console.warn('Compatibility warnings:', result.warnings);
}
- Check game style compatibility:
const contexts = ContextCatalog.findByGameStyle('action-arcade');
console.log('Compatible contexts:', contexts.map(c => c.id));
- Use recommendations:
const recs = AssetManager.getRecommendations('action-arcade', 'space shooter');
const bestContext = recs[0].config.context;
Performance Issues
Symptom: Game runs slowly or stutters.
Solutions:
- Reduce background effects:
// Disable expensive effects
BackgroundEngine.render(ctx, theme, variant, w, h, time, {
effects: [] // No effects
});
- Use static backgrounds for menus:
// Render once instead of every frame
BackgroundEngine.renderStatic(ctx, theme, variant, w, h);
- Preload assets:
await BackgroundEngine.preloadTheme('nature');
await AssetManager.initialize({ preloadBackgrounds: true });
- Use simpler render modes:
// 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:
- Check asset exists:
const song = MusicEngine.getSongInfo('my-song-id');
if (!song) {
console.error('Song not found. Available songs:');
console.log(MusicEngine.getCatalog().map(s => s.id));
}
- Search for similar assets:
const results = AssetManager.searchAssets('forest', {
types: ['background']
});
console.log('Found backgrounds:', results.backgrounds);
- Use fallbacks:
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 |