import { type SpriteSpec, SPRITE_SPECS } from "."; import { SOUND_SPECS, SoundSpec } from "./sounds"; export const FONT = new FontFace("scientifica", "url(/fonts/scientifica.ttf)"); FONT.load().then((font) => { document.fonts.add(font); }); export const IMAGES = new Map(); export const SOUNDS = new Map(); export const loadSpritesIntoImageElements = ( spriteSpecs: Partial[], ): Promise[] => { const spritePromises: Promise[] = []; for (const spriteSpec of spriteSpecs) { if (spriteSpec.sheet) { const img = new Image(); img.src = spriteSpec.sheet; IMAGES.set(spriteSpec.sheet, img); spritePromises.push( new Promise((resolve) => { img.onload = () => resolve(); }), ); } if (spriteSpec.states) { spritePromises.push( ...loadSpritesIntoImageElements(Array.from(spriteSpec.states.values())), ); } } return spritePromises; }; export const loadSoundsIntoAudioElements = ( soundSpecs: SoundSpec[], ): Promise[] => { const soundPromises: Promise[] = []; for (const soundSpec of soundSpecs) { if (soundSpec.url) { const promise = fetch(soundSpec.url) .then((response) => response.blob()) .then((blob) => { const audio = new Audio(); audio.src = URL.createObjectURL(blob); audio.volume = soundSpec.volume ?? 1; SOUNDS.set(soundSpec.name, audio); return new Promise((resolve, rej) => { audio.oncanplaythrough = () => { resolve(); }; audio.onerror = (e) => { console.error(soundSpec); rej(e); }; }); }); soundPromises.push(promise); } if (soundSpec.states) { soundPromises.push( ...loadSoundsIntoAudioElements(Array.from(soundSpec.states.values())), ); } } return soundPromises; }; export const loadAssets = () => Promise.all([ ...loadSpritesIntoImageElements( Array.from(SPRITE_SPECS.keys()).map( (key) => SPRITE_SPECS.get(key) as SpriteSpec, ), ), FONT.load(), ...loadSoundsIntoAudioElements(Array.from(SOUND_SPECS.values())), ]);