import {Map} from './Map';
import {Game} from './Game';
/**
* The loader is an easy way to preload all the required assets for your game.
* You can use it from the load() method of your Game class.
* It can also be used while the game is running to load assets on the fly.
*/
export abstract class Loader {
/** The base path to the assets directory. */
public static basePath: string = '.';
private static _game: Game;
private static _loaded: boolean = false;
private static _images: Map = new Map();
private static _videos: Map = new Map();
private static _audios: Map = new Map();
private static _json: Map = new Map();
private static _files: Map = new Map();
/**
* Used internally to preload the game and its assets.
* @param game The game instance.
*/
public static _init(game: Game): void {
this._game = game;
this._game.load();
if (this._files.getAll().length === 0) {
this._fileLoaded();
}
}
/**
* Load an image file.
* If the file can't be loaded, the game won't start and a message will
* be logged to the console.
* @param fileName The name to save this file as in the loader.
* @param filePath The path to the file to load.
*/
public static loadImage(fileName: string, filePath: string): void {
const image = document.createElement('img');
filePath = `${this.basePath}/${filePath}`;
this._images.set(fileName, image);
this._files.set(fileName, false);
image.addEventListener('load', () => {
this._files.set(fileName, true);
if (!this._loaded) this._fileLoaded();
});
image.addEventListener('error', () => {
console.log(`Could not load file: ${filePath}.`);
});
image.src = filePath;
}
/**
* Load a video file.
* If the file can't be loaded, the game won't start and a message will
* be logged to the console.
* @param fileName The name to save this file as in the loader.
* @param filePath The path to the file to load.
*/
public static loadVideo(fileName: string, filePath: string): void {
const video = document.createElement('video');
filePath = `${this.basePath}/${filePath}`;
this._videos.set(fileName, video);
this._files.set(fileName, false);
video.addEventListener('loadeddata', () => {
this._files.set(fileName, true);
if (!this._loaded) this._fileLoaded();
});
video.addEventListener('error', () => {
console.log(`Could not load file: ${filePath}.`);
});
video.src = filePath;
}
/**
* Load an audio file.
* If the file can't be loaded, the game won't start and a message will
* be logged to the console.
* @param fileName The name to save this file as in the loader.
* @param filePath The path to the file to load.
*/
public static loadAudio(fileName: string, filePath: string): void {
const audio = document.createElement('audio');
filePath = `${this.basePath}/${filePath}`;
this._audios.set(fileName, audio);
this._files.set(fileName, false);
audio.addEventListener('loadeddata', () => {
this._files.set(fileName, true);
if (!this._loaded) this._fileLoaded();
});
audio.addEventListener('error', () => {
console.log(`Could not load file: ${filePath}.`);
});
audio.src = filePath;
}
/**
* Load a json file.
* If the file can't be loaded, the game won't start and a message will
* be logged to the console.
* @param fileName The name to save this file as in the loader.
* @param filePath The path to the file to load.
*/
public static loadJSON(fileName: string, filePath: string): void {
const xhr = new XMLHttpRequest();
filePath = `${this.basePath}/${filePath}`;
this._json.set(fileName, {});
this._files.set(fileName, false);
xhr.addEventListener('load', () => {
this._files.set(fileName, true);
this._json.set(fileName, JSON.parse(xhr.responseText));
if (!this._loaded) this._fileLoaded();
});
xhr.addEventListener('error', () => {
console.log(`Could not load file: ${filePath}`);
});
xhr.open('GET', filePath, true);
xhr.send();
}
/**
* Get a file from the loader.
* If the file was loaded on the fly, it may not be ready yet! You can
* check whether the file was loaded or not using the loaded() method.
* @param fileName The name of the file to get.
* @return The file, or null if the Loader does not contain the specified file.
*/
public static get(fileName: string): HTMLImageElement|HTMLAudioElement|HTMLVideoElement|object|null {
if (this._images.get(fileName) !== null) {
return this.image(fileName);
} else if (this._videos.get(fileName) !== null) {
return this.video(fileName);
} else if (this._audios.get(fileName) !== null) {
return this.audio(fileName);
} else if (this._json.get(fileName) !== null) {
return this.json(fileName);
} else {
return null;
}
}
/**
* Get an image that was loaded.
* If the image was loaded on the fly, it may not be ready yet! You can
* check whether the file was loaded or not using the loaded() method.
* @param fileName The name of the file to get.
* @return The image file, or null if the image was not loaded using loadImage().
*/
public static image(fileName: string): HTMLImageElement|null {
return this._images.get(fileName);
}
/**
* Get a video that was loaded.
* If the video was loaded on the fly, it may not be ready yet! You can
* check whether the file was loaded or not using the loaded() method.
* @param fileName The name of the file to get.
* @return The video file, or null if the video was not loaded using loadVideo().
*/
public static video(fileName: string): HTMLVideoElement|null {
return this._videos.get(fileName);
}
/**
* Get a audio that was loaded.
* If the audio was loaded on the fly, it may not be ready yet! You can
* check whether the file was loaded or not using the loaded() method.
* @param fileName The name of the file to get.
* @return The audio file, or null if the audio was not loaded using loadAudio().
*/
public static audio(fileName: string): HTMLAudioElement|null {
return this._audios.get(fileName);
}
/**
* Get a JSON file that was loaded.
* If the JSON file was loaded on the fly, it may not be ready yet! You can
* check whether the file was loaded or not using the loaded() method.
* @param fileName The name of the file to get.
* @return The parsed JSON file, or null if the JSON file was not loaded using loadJSON().
*/
public static json(fileName: string): object|null {
return this._json.get(fileName);
}
/**
* Check whether a file is ready to be used or not.
* @param fileName The file to check.
*/
public static loaded(fileName: string): boolean {
return this._files.get(fileName) || false;
}
private static _fileLoaded(): void {
if (this._files.getAll().indexOf(false) === -1) {
this._loaded = true;
this._game._start();
}
}
}