import { type SpriteSpec, SPRITE_SPECS } from "."; import { SOUND_SPECS, SoundSpec } from "./sounds"; let BASE_URL = import.meta.env.BASE_URL || document.location; BASE_URL = BASE_URL.endsWith("/") ? BASE_URL.slice(0, -1) : BASE_URL; export const FONT = new FontFace( "scientifica", `url(${BASE_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 = BASE_URL + 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(BASE_URL + 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())), ]);