179 lines
6.1 KiB
TypeScript
179 lines
6.1 KiB
TypeScript
import Map from "../DataTypes/Map";
|
|
import Tilemap from "../Nodes/Tilemap";
|
|
import Queue from "../DataTypes/Queue";
|
|
import { TiledTilemapData } from "../DataTypes/Tilesets/TiledData";
|
|
import StringUtils from "../Utils/StringUtils";
|
|
|
|
export default class ResourceManager {
|
|
private static instance: ResourceManager;
|
|
|
|
private loading: boolean;
|
|
|
|
private imagesLoaded: number;
|
|
private imagesToLoad: number;
|
|
private imageLoadingQueue: Queue<{key: string, path: string}>;
|
|
private images: Map<HTMLImageElement>;
|
|
|
|
private tilemapsLoaded: number;
|
|
private tilemapsToLoad: number;
|
|
private tilemapLoadingQueue: Queue<{key: string, path: string}>;
|
|
private tilemaps: Map<TiledTilemapData>;
|
|
|
|
private constructor(){
|
|
this.loading = false;
|
|
|
|
this.imagesLoaded = 0;
|
|
this.imagesToLoad = 0;
|
|
this.imageLoadingQueue = new Queue();
|
|
this.images = new Map();
|
|
|
|
this.tilemapsLoaded = 0;
|
|
this.tilemapsToLoad = 0;
|
|
this.tilemapLoadingQueue = new Queue();
|
|
this.tilemaps = new Map();
|
|
};
|
|
|
|
static getInstance(): ResourceManager {
|
|
if(!this.instance){
|
|
this.instance = new ResourceManager();
|
|
}
|
|
|
|
return this.instance;
|
|
}
|
|
|
|
public image(key: string, path: string): void {
|
|
this.imageLoadingQueue.enqueue({key: key, path: path});
|
|
}
|
|
|
|
public spritesheet(key: string, path: string, frames: {hFrames: number, vFrames: number}): void {
|
|
|
|
}
|
|
|
|
public audio(key: string, path: string): void {
|
|
|
|
}
|
|
|
|
// This one is trickier than the others because we first have to load the json file, then we have to load the images
|
|
public tilemap(key: string, path: string): void {
|
|
// Add a function that loads the tilemap to the queue
|
|
this.tilemapLoadingQueue.enqueue({key: key, path: path});
|
|
|
|
// this.tilemapLoadingQueue.enqueue((callback: Function) => {
|
|
// this.loadTilemap(path, (tilemapData: TiledTilemapData) => {
|
|
// // When the tilemap file loads, first construct the tilemap
|
|
// // TODO: Ignore multiple layers for now, but this will have to be elegantly dealt with sometime in the future
|
|
|
|
// // Count the total number of images that need to be loaded
|
|
|
|
// let tilemap = new constr(tilemapData);
|
|
// // For each of the tilesets in the tilemap, load the image
|
|
// tilemap.getTilesets().forEach(tileset => {
|
|
// let imagePath = StringUtils.getPathFromFilePath(path) + tileset.getImageUrl();
|
|
// this.loadImage(imagePath, (image: HTMLImageElement) => {
|
|
// tileset.setImage(image);
|
|
// })
|
|
// });
|
|
|
|
// this.tilemaps.add(key, tilemap);
|
|
// });
|
|
// });
|
|
}
|
|
|
|
loadResourcesFromQueue(callback: Function): void {
|
|
this.loading = true;
|
|
|
|
// Load everything in the queues. Tilemaps have to come before images because they will add new images to the queue
|
|
this.loadTilemapsFromQueue(() => {
|
|
this.loadImagesFromQueue(() => {
|
|
// Done loading
|
|
this.loading = false;
|
|
callback();
|
|
});
|
|
});
|
|
|
|
}
|
|
|
|
private loadTilemapsFromQueue(onFinishLoading: Function){
|
|
this.tilemapsToLoad = this.tilemapLoadingQueue.getSize();
|
|
this.tilemapsLoaded = 0;
|
|
|
|
while(this.tilemapLoadingQueue.hasItems()){
|
|
let tilemap = this.tilemapLoadingQueue.dequeue();
|
|
this.loadTilemap(tilemap.key, tilemap.path, onFinishLoading);
|
|
}
|
|
}
|
|
|
|
private loadTilemap(key: string, pathToTilemapJSON: string, callbackIfLast: Function): void {
|
|
this.loadTextFile(pathToTilemapJSON, (fileText: string) => {
|
|
let tilemapObject = <TiledTilemapData>JSON.parse(fileText);
|
|
|
|
// We can parse the object later - it's much faster than loading
|
|
this.tilemaps.add(key, tilemapObject);
|
|
|
|
// Grab the tileset images we need to load and add them to the imageloading queue
|
|
for(let tileset of tilemapObject.tilesets){
|
|
let key = tileset.image;
|
|
let path = StringUtils.getPathFromFilePath(pathToTilemapJSON) + key;
|
|
this.imageLoadingQueue.enqueue({key: key, path: path});
|
|
}
|
|
|
|
// Finish loading
|
|
this.finishLoadingTilemap(callbackIfLast);
|
|
});
|
|
}
|
|
|
|
private finishLoadingTilemap(callback: Function){
|
|
this.tilemapsLoaded += 1;
|
|
|
|
if(this.tilemapsLoaded === this.tilemapsToLoad){
|
|
// We're done loading tilemaps
|
|
callback();
|
|
}
|
|
}
|
|
|
|
private loadImagesFromQueue(onFinishLoading: Function): void {
|
|
this.imagesToLoad = this.imageLoadingQueue.getSize();
|
|
this.tilemapsLoaded = 0;
|
|
|
|
while(this.imageLoadingQueue.hasItems()){
|
|
let image = this.imageLoadingQueue.dequeue();
|
|
this.loadImage(image.key, image.path, onFinishLoading);
|
|
}
|
|
}
|
|
|
|
// TODO: When you switch to WebGL, make sure to make this private and make a "loadTexture" function
|
|
public loadImage(key: string, path: string, callbackIfLast: Function): void {
|
|
var image = new Image();
|
|
|
|
image.onload = () => {
|
|
// Add to loaded images
|
|
this.images.add(key, image);
|
|
|
|
// Finish image load
|
|
this.finishLoadingImage(callbackIfLast);
|
|
}
|
|
|
|
image.src = path;
|
|
}
|
|
|
|
private finishLoadingImage(callback: Function): void {
|
|
this.imagesLoaded += 1;
|
|
|
|
if(this.imagesLoaded === this.imagesToLoad ){
|
|
// We're done loading tilemaps
|
|
callback();
|
|
}
|
|
}
|
|
|
|
private loadTextFile(textFilePath: string, callback: Function): void {
|
|
let xobj: XMLHttpRequest = new XMLHttpRequest();
|
|
xobj.overrideMimeType("application/json");
|
|
xobj.open('GET', textFilePath, true);
|
|
xobj.onreadystatechange = function () {
|
|
if ((xobj.readyState == 4) && (xobj.status == 200)) {
|
|
callback(xobj.responseText);
|
|
}
|
|
};
|
|
xobj.send(null);
|
|
}
|
|
} |