added animated sprites
This commit is contained in:
parent
b6a0aa569a
commit
32d63ea2bf
11
src/DataTypes/Spritesheet.ts
Normal file
11
src/DataTypes/Spritesheet.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { AnimationData } from "../Rendering/Animations/AnimationTypes";
|
||||||
|
|
||||||
|
export default class Spritesheet {
|
||||||
|
name: string;
|
||||||
|
spriteSheetImage: string;
|
||||||
|
spriteWidth: number;
|
||||||
|
spriteHeight: number;
|
||||||
|
columns: number;
|
||||||
|
rows: number;
|
||||||
|
animations: Array<AnimationData>;
|
||||||
|
}
|
35
src/Nodes/Sprites/AnimatedSprite.ts
Normal file
35
src/Nodes/Sprites/AnimatedSprite.ts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import Sprite from "./Sprite";
|
||||||
|
import AnimationManager from "../../Rendering/Animations/AnimationManager";
|
||||||
|
import Spritesheet from "../../DataTypes/Spritesheet";
|
||||||
|
import Vec2 from "../../DataTypes/Vec2";
|
||||||
|
|
||||||
|
export default class AnimatedSprite extends Sprite {
|
||||||
|
/** The number of columns in this sprite sheet */
|
||||||
|
protected numCols: number;
|
||||||
|
|
||||||
|
/** The number of rows in this sprite sheet */
|
||||||
|
protected numRows: number;
|
||||||
|
|
||||||
|
/** The animationManager for this sprite */
|
||||||
|
animation: AnimationManager;
|
||||||
|
|
||||||
|
constructor(spritesheet: Spritesheet){
|
||||||
|
super(spritesheet.name);
|
||||||
|
this.numCols = spritesheet.columns;
|
||||||
|
this.numRows = spritesheet.rows;
|
||||||
|
|
||||||
|
// Set the size of the sprite to the sprite size specified by the spritesheet
|
||||||
|
this.size.set(spritesheet.spriteWidth, spritesheet.spriteHeight);
|
||||||
|
|
||||||
|
this.animation = new AnimationManager();
|
||||||
|
|
||||||
|
// Add the animations to the animated sprite
|
||||||
|
for(let animation of spritesheet.animations){
|
||||||
|
this.animation.add(animation.name, animation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getAnimationOffset(index: number): Vec2 {
|
||||||
|
return new Vec2((index % this.numCols) * this.size.x, Math.floor(index / this.numCols) * this.size.y);
|
||||||
|
}
|
||||||
|
}
|
173
src/Rendering/Animations/AnimationManager.ts
Normal file
173
src/Rendering/Animations/AnimationManager.ts
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
import Map from "../../DataTypes/Map";
|
||||||
|
import Emitter from "../../Events/Emitter";
|
||||||
|
import CanvasNode from "../../Nodes/CanvasNode";
|
||||||
|
import { AnimationData, AnimationState } from "./AnimationTypes";
|
||||||
|
|
||||||
|
export default class AnimationManager {
|
||||||
|
/** The owner of this animation manager */
|
||||||
|
protected owner: CanvasNode;
|
||||||
|
|
||||||
|
/** The current animation state of this sprite */
|
||||||
|
protected animationState: AnimationState;
|
||||||
|
|
||||||
|
/** The name of the current animation of this sprite */
|
||||||
|
protected currentAnimation: string;
|
||||||
|
|
||||||
|
/** The current frame of this animation */
|
||||||
|
protected currentFrame: number;
|
||||||
|
|
||||||
|
/** The progress of the current animation through the current frame */
|
||||||
|
protected frameProgress: number;
|
||||||
|
|
||||||
|
/** Whether the current animation is looping or not */
|
||||||
|
protected loop: boolean;
|
||||||
|
|
||||||
|
/** The map of animations */
|
||||||
|
protected animations: Map<AnimationData>;
|
||||||
|
|
||||||
|
/** The name of the event (if any) to send when the current animation stops playing. */
|
||||||
|
protected onEndEvent: string;
|
||||||
|
|
||||||
|
/** The event emitter for this animation manager */
|
||||||
|
protected emitter: Emitter;
|
||||||
|
|
||||||
|
/** A queued animation */
|
||||||
|
protected pendingAnimation: string;
|
||||||
|
|
||||||
|
/** The loop status of a pending animation */
|
||||||
|
protected pendingLoop: boolean;
|
||||||
|
|
||||||
|
/** The onEnd event of a pending animation */
|
||||||
|
protected pendingOnEnd: string;
|
||||||
|
|
||||||
|
constructor(){
|
||||||
|
this.animationState = AnimationState.STOPPED;
|
||||||
|
this.currentAnimation = "";
|
||||||
|
this.currentFrame = 0;
|
||||||
|
this.frameProgress = 0;
|
||||||
|
this.loop = false;
|
||||||
|
this.animations = new Map();
|
||||||
|
this.onEndEvent = null;
|
||||||
|
this.emitter = new Emitter();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an animation to this sprite
|
||||||
|
* @param key The unique key of the animation
|
||||||
|
* @param animation The animation data
|
||||||
|
*/
|
||||||
|
add(key: string, animation: AnimationData): void {
|
||||||
|
this.animations.add(key, animation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the index specified by the current animation and current frame */
|
||||||
|
getIndex(): number {
|
||||||
|
if(this.animations.has(this.currentAnimation)){
|
||||||
|
return this.animations.get(this.currentAnimation).frames[this.currentFrame].index;
|
||||||
|
} else {
|
||||||
|
// No current animation, warn the user
|
||||||
|
console.warn("Animation index was requested, but the current animation was invalid");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getIndexAndAdvanceAnimation(): number {
|
||||||
|
// If we aren't playing, we won't be advancing the animation
|
||||||
|
if(!(this.animationState === AnimationState.PLAYING)){
|
||||||
|
return this.getIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.animations.has(this.currentAnimation)){
|
||||||
|
let currentAnimation = this.animations.get(this.currentAnimation);
|
||||||
|
let index = currentAnimation.frames[this.currentFrame].index;
|
||||||
|
|
||||||
|
// Advance the animation
|
||||||
|
this.frameProgress += 1;
|
||||||
|
if(this.frameProgress >= currentAnimation.frames[this.currentFrame].duration){
|
||||||
|
// We have been on this frame for its whole duration, go to the next one
|
||||||
|
this.frameProgress = 0;
|
||||||
|
this.currentFrame += 1;
|
||||||
|
|
||||||
|
if(this.currentFrame >= currentAnimation.frames.length){
|
||||||
|
// We have reached the end of this animation
|
||||||
|
if(this.loop){
|
||||||
|
this.currentFrame = 0;
|
||||||
|
this.frameProgress = 0;
|
||||||
|
} else {
|
||||||
|
this.endCurrentAnimation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the current index
|
||||||
|
return index;
|
||||||
|
} else {
|
||||||
|
// No current animation, can't advance. Warn the user
|
||||||
|
console.warn("Animation index and advance was requested, but the current animation was invalid");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected endCurrentAnimation(): void {
|
||||||
|
this.currentFrame = 0;
|
||||||
|
this.animationState = AnimationState.STOPPED;
|
||||||
|
|
||||||
|
if(this.onEndEvent !== null){
|
||||||
|
this.emitter.fireEvent(this.onEndEvent, {owner: this.owner, animation: this.currentAnimation});
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is a pending animation, play it
|
||||||
|
if(this.pendingAnimation !== null){
|
||||||
|
this.play(this.pendingAnimation, this.pendingLoop, this.pendingOnEnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plays the specified animation
|
||||||
|
* @param animation The name of the animation to play
|
||||||
|
* @param loop Whether or not to loop the animation. False by default
|
||||||
|
* @param onEnd The name of an event to send when this animation naturally stops playing. This only matters if loop is false.
|
||||||
|
*/
|
||||||
|
play(animation: string, loop: boolean = false, onEnd?: string): void {
|
||||||
|
this.currentAnimation = animation;
|
||||||
|
this.currentFrame = 0;
|
||||||
|
this.frameProgress = 0;
|
||||||
|
this.loop = loop;
|
||||||
|
this.animationState = AnimationState.PLAYING;
|
||||||
|
if(onEnd !== undefined){
|
||||||
|
this.onEndEvent = onEnd;
|
||||||
|
} else {
|
||||||
|
this.onEndEvent = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pendingAnimation = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Queues a single animation to be played after the current one. Does NOT stack */
|
||||||
|
queue(animation: string, loop: boolean = false, onEnd?: string): void {
|
||||||
|
this.pendingAnimation = animation;
|
||||||
|
this.pendingLoop = loop;
|
||||||
|
if(onEnd !== undefined){
|
||||||
|
this.pendingOnEnd = onEnd;
|
||||||
|
} else {
|
||||||
|
this.pendingOnEnd = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Pauses the current animation */
|
||||||
|
pause(): void {
|
||||||
|
this.animationState = AnimationState.PAUSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Resumes the current animation if possible */
|
||||||
|
resume(): void {
|
||||||
|
if(this.animationState === AnimationState.PAUSED){
|
||||||
|
this.animationState = AnimationState.PLAYING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Stops the current animation. The animation cannot be resumed after this. */
|
||||||
|
stop(): void {
|
||||||
|
this.animationState = AnimationState.STOPPED;
|
||||||
|
}
|
||||||
|
}
|
14
src/Rendering/Animations/AnimationTypes.ts
Normal file
14
src/Rendering/Animations/AnimationTypes.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
export enum AnimationState {
|
||||||
|
STOPPED = 0,
|
||||||
|
PAUSED = 1,
|
||||||
|
PLAYING = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AnimationData {
|
||||||
|
name: string;
|
||||||
|
frames: Array<{index: number, duration: number}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TweenData {
|
||||||
|
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ import Label from "../Nodes/UIElements/Label";
|
||||||
import Button from "../Nodes/UIElements/Button";
|
import Button from "../Nodes/UIElements/Button";
|
||||||
import Slider from "../Nodes/UIElements/Slider";
|
import Slider from "../Nodes/UIElements/Slider";
|
||||||
import TextInput from "../Nodes/UIElements/TextInput";
|
import TextInput from "../Nodes/UIElements/TextInput";
|
||||||
|
import AnimatedSprite from "../Nodes/Sprites/AnimatedSprite";
|
||||||
|
|
||||||
export default class CanvasRenderer extends RenderingManager {
|
export default class CanvasRenderer extends RenderingManager {
|
||||||
protected ctx: CanvasRenderingContext2D;
|
protected ctx: CanvasRenderingContext2D;
|
||||||
|
@ -78,7 +79,9 @@ export default class CanvasRenderer extends RenderingManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected renderNode(node: CanvasNode): void {
|
protected renderNode(node: CanvasNode): void {
|
||||||
if(node instanceof Sprite){
|
if(node instanceof AnimatedSprite){
|
||||||
|
this.renderAnimatedSprite(<AnimatedSprite>node);
|
||||||
|
} else if(node instanceof Sprite){
|
||||||
this.renderSprite(<Sprite>node);
|
this.renderSprite(<Sprite>node);
|
||||||
} else if(node instanceof Graphic){
|
} else if(node instanceof Graphic){
|
||||||
this.renderGraphic(<Graphic>node);
|
this.renderGraphic(<Graphic>node);
|
||||||
|
@ -120,8 +123,41 @@ export default class CanvasRenderer extends RenderingManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected renderAnimatedSprite(): void {
|
protected renderAnimatedSprite(sprite: AnimatedSprite): void {
|
||||||
throw new Error("Method not implemented.");
|
// Get the image from the resource manager
|
||||||
|
let image = this.resourceManager.getImage(sprite.imageId);
|
||||||
|
|
||||||
|
// Calculate the origin of the viewport according to this sprite
|
||||||
|
let origin = this.scene.getViewTranslation(sprite);
|
||||||
|
|
||||||
|
// Get the zoom level of the scene
|
||||||
|
let zoom = this.scene.getViewScale();
|
||||||
|
|
||||||
|
let animationIndex = sprite.animation.getIndexAndAdvanceAnimation();
|
||||||
|
|
||||||
|
let animationOffset = sprite.getAnimationOffset(animationIndex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Coordinates in the space of the image:
|
||||||
|
image crop start -> x, y
|
||||||
|
image crop size -> w, h
|
||||||
|
Coordinates in the space of the world
|
||||||
|
image draw start -> x, y
|
||||||
|
image draw size -> w, h
|
||||||
|
*/
|
||||||
|
this.ctx.drawImage(image,
|
||||||
|
sprite.imageOffset.x + animationOffset.x, sprite.imageOffset.y + animationOffset.y,
|
||||||
|
sprite.size.x, sprite.size.y,
|
||||||
|
(sprite.position.x - origin.x - sprite.size.x*sprite.scale.x/2)*zoom, (sprite.position.y - origin.y - sprite.size.y*sprite.scale.y/2)*zoom,
|
||||||
|
sprite.size.x * sprite.scale.x*zoom, sprite.size.y * sprite.scale.y*zoom);
|
||||||
|
|
||||||
|
// Debug mode
|
||||||
|
if(this.debug){
|
||||||
|
this.ctx.lineWidth = 4;
|
||||||
|
this.ctx.strokeStyle = "#00FF00"
|
||||||
|
let b = sprite.boundary;
|
||||||
|
this.ctx.strokeRect(b.x - b.hw - origin.x, b.y - b.hh - origin.y, b.hw*2*zoom, b.hh*2*zoom);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected renderGraphic(graphic: Graphic): void {
|
protected renderGraphic(graphic: Graphic): void {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import Map from "../DataTypes/Map";
|
import Map from "../DataTypes/Map";
|
||||||
import CanvasNode from "../Nodes/CanvasNode";
|
import CanvasNode from "../Nodes/CanvasNode";
|
||||||
import Graphic from "../Nodes/Graphic";
|
import Graphic from "../Nodes/Graphic";
|
||||||
|
import AnimatedSprite from "../Nodes/Sprites/AnimatedSprite";
|
||||||
import Sprite from "../Nodes/Sprites/Sprite";
|
import Sprite from "../Nodes/Sprites/Sprite";
|
||||||
import Tilemap from "../Nodes/Tilemap";
|
import Tilemap from "../Nodes/Tilemap";
|
||||||
import UIElement from "../Nodes/UIElement";
|
import UIElement from "../Nodes/UIElement";
|
||||||
|
@ -29,7 +30,7 @@ export default abstract class RenderingManager {
|
||||||
|
|
||||||
protected abstract renderSprite(sprite: Sprite): void;
|
protected abstract renderSprite(sprite: Sprite): void;
|
||||||
|
|
||||||
protected abstract renderAnimatedSprite(): void;
|
protected abstract renderAnimatedSprite(sprite: AnimatedSprite): void;
|
||||||
|
|
||||||
protected abstract renderGraphic(graphic: Graphic): void;
|
protected abstract renderGraphic(graphic: Graphic): void;
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import Map from "../DataTypes/Map";
|
import Map from "../DataTypes/Map";
|
||||||
import Tilemap from "../Nodes/Tilemap";
|
|
||||||
import Queue from "../DataTypes/Queue";
|
import Queue from "../DataTypes/Queue";
|
||||||
import { TiledTilemapData } from "../DataTypes/Tilesets/TiledData";
|
import { TiledTilemapData } from "../DataTypes/Tilesets/TiledData";
|
||||||
import StringUtils from "../Utils/StringUtils";
|
import StringUtils from "../Utils/StringUtils";
|
||||||
import AudioManager from "../Sound/AudioManager";
|
import AudioManager from "../Sound/AudioManager";
|
||||||
|
import Spritesheet from "../DataTypes/Spritesheet";
|
||||||
|
|
||||||
export default class ResourceManager {
|
export default class ResourceManager {
|
||||||
// Instance for the singleton class
|
// Instance for the singleton class
|
||||||
|
@ -18,60 +18,43 @@ export default class ResourceManager {
|
||||||
public onLoadComplete: Function;
|
public onLoadComplete: Function;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/** Number to keep track of how many images need to be loaded*/
|
||||||
* Number to keep track of how many images need to be loaded
|
|
||||||
*/
|
|
||||||
private loadonly_imagesLoaded: number;
|
private loadonly_imagesLoaded: number;
|
||||||
/**
|
/** Number to keep track of how many images are loaded */
|
||||||
* Number to keep track of how many images are loaded
|
|
||||||
*/
|
|
||||||
private loadonly_imagesToLoad: number;
|
private loadonly_imagesToLoad: number;
|
||||||
/**
|
/** The queue of images we must load */
|
||||||
* The queue of images we must load
|
|
||||||
*/
|
|
||||||
private loadonly_imageLoadingQueue: Queue<{key: string, path: string}>;
|
private loadonly_imageLoadingQueue: Queue<{key: string, path: string}>;
|
||||||
/**
|
/** A map of the images that are currently loaded and (presumably) being used by the scene */
|
||||||
* A map of the images that are currently loaded and (presumably) being used by the scene
|
|
||||||
*/
|
|
||||||
private images: Map<HTMLImageElement>;
|
private images: Map<HTMLImageElement>;
|
||||||
|
|
||||||
/**
|
/** Number to keep track of how many tilemaps need to be loaded */
|
||||||
* Number to keep track of how many tilemaps need to be loaded
|
private loadonly_spritesheetsLoaded: number;
|
||||||
*/
|
/** Number to keep track of how many tilemaps are loaded */
|
||||||
|
private loadonly_spritesheetsToLoad: number;
|
||||||
|
/** The queue of tilemaps we must load */
|
||||||
|
private loadonly_spritesheetLoadingQueue: Queue<{key: string, path: string}>;
|
||||||
|
/** A map of the tilemaps that are currently loaded and (presumably) being used by the scene */
|
||||||
|
private spritesheets: Map<Spritesheet>;
|
||||||
|
|
||||||
|
/** Number to keep track of how many tilemaps need to be loaded */
|
||||||
private loadonly_tilemapsLoaded: number;
|
private loadonly_tilemapsLoaded: number;
|
||||||
/**
|
/** Number to keep track of how many tilemaps are loaded */
|
||||||
* Number to keep track of how many tilemaps are loaded
|
|
||||||
*/
|
|
||||||
private loadonly_tilemapsToLoad: number;
|
private loadonly_tilemapsToLoad: number;
|
||||||
/**
|
/** The queue of tilemaps we must load */
|
||||||
* The queue of tilemaps we must load
|
|
||||||
*/
|
|
||||||
private loadonly_tilemapLoadingQueue: Queue<{key: string, path: string}>;
|
private loadonly_tilemapLoadingQueue: Queue<{key: string, path: string}>;
|
||||||
/**
|
/** A map of the tilemaps that are currently loaded and (presumably) being used by the scene */
|
||||||
* A map of the tilemaps that are currently loaded and (presumably) being used by the scene
|
|
||||||
*/
|
|
||||||
private tilemaps: Map<TiledTilemapData>;
|
private tilemaps: Map<TiledTilemapData>;
|
||||||
|
|
||||||
/**
|
/** Number to keep track of how many sounds need to be loaded */
|
||||||
* Number to keep track of how many sounds need to be loaded
|
|
||||||
*/
|
|
||||||
private loadonly_audioLoaded: number;
|
private loadonly_audioLoaded: number;
|
||||||
/**
|
/** Number to keep track of how many sounds are loaded */
|
||||||
* Number to keep track of how many sounds are loaded
|
|
||||||
*/
|
|
||||||
private loadonly_audioToLoad: number;
|
private loadonly_audioToLoad: number;
|
||||||
/**
|
/** The queue of sounds we must load */
|
||||||
* The queue of sounds we must load
|
|
||||||
*/
|
|
||||||
private loadonly_audioLoadingQueue: Queue<{key: string, path: string}>;
|
private loadonly_audioLoadingQueue: Queue<{key: string, path: string}>;
|
||||||
/**
|
/** A map of the sounds that are currently loaded and (presumably) being used by the scene */
|
||||||
* A map of the sounds that are currently loaded and (presumably) being used by the scene
|
|
||||||
*/
|
|
||||||
private audioBuffers: Map<AudioBuffer>;
|
private audioBuffers: Map<AudioBuffer>;
|
||||||
|
|
||||||
/**
|
/** The total number of "types" of things that need to be loaded (i.e. images and tilemaps) */
|
||||||
* The total number of "types" of things that need to be loaded (i.e. images and tilemaps)
|
|
||||||
*/
|
|
||||||
private loadonly_typesToLoad: number;
|
private loadonly_typesToLoad: number;
|
||||||
|
|
||||||
private constructor(){
|
private constructor(){
|
||||||
|
@ -83,6 +66,11 @@ export default class ResourceManager {
|
||||||
this.loadonly_imageLoadingQueue = new Queue();
|
this.loadonly_imageLoadingQueue = new Queue();
|
||||||
this.images = new Map();
|
this.images = new Map();
|
||||||
|
|
||||||
|
this.loadonly_spritesheetsLoaded = 0;
|
||||||
|
this.loadonly_spritesheetsToLoad = 0;
|
||||||
|
this.loadonly_spritesheetLoadingQueue = new Queue();
|
||||||
|
this.spritesheets = new Map();
|
||||||
|
|
||||||
this.loadonly_tilemapsLoaded = 0;
|
this.loadonly_tilemapsLoaded = 0;
|
||||||
this.loadonly_tilemapsToLoad = 0;
|
this.loadonly_tilemapsToLoad = 0;
|
||||||
this.loadonly_tilemapLoadingQueue = new Queue();
|
this.loadonly_tilemapLoadingQueue = new Queue();
|
||||||
|
@ -122,8 +110,12 @@ export default class ResourceManager {
|
||||||
return this.images.get(key);
|
return this.images.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public spritesheet(key: string, path: string, frames: {hFrames: number, vFrames: number}): void {
|
public spritesheet(key: string, path: string): void {
|
||||||
|
this.loadonly_spritesheetLoadingQueue.enqueue({key: key, path: path});
|
||||||
|
}
|
||||||
|
|
||||||
|
public getSpritesheet(key: string): Spritesheet {
|
||||||
|
return this.spritesheets.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -160,7 +152,6 @@ export default class ResourceManager {
|
||||||
return this.tilemaps.get(key);
|
return this.tilemaps.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO - Should everything be loaded in order, one file at a time?
|
|
||||||
/**
|
/**
|
||||||
* Loads all resources currently in the queue
|
* Loads all resources currently in the queue
|
||||||
* @param callback
|
* @param callback
|
||||||
|
@ -173,14 +164,17 @@ export default class ResourceManager {
|
||||||
// Load everything in the queues. Tilemaps have to come before images because they will add new images to the queue
|
// Load everything in the queues. Tilemaps have to come before images because they will add new images to the queue
|
||||||
this.loadTilemapsFromQueue(() => {
|
this.loadTilemapsFromQueue(() => {
|
||||||
console.log("Loaded Tilemaps");
|
console.log("Loaded Tilemaps");
|
||||||
this.loadImagesFromQueue(() => {
|
this.loadSpritesheetsFromQueue(() => {
|
||||||
console.log("Loaded Images");
|
console.log("Loaded Spritesheets");
|
||||||
this.loadAudioFromQueue(() => {
|
this.loadImagesFromQueue(() => {
|
||||||
console.log("Loaded Audio");
|
console.log("Loaded Images");
|
||||||
// Done loading
|
this.loadAudioFromQueue(() => {
|
||||||
this.loading = false;
|
console.log("Loaded Audio");
|
||||||
this.justLoaded = true;
|
// Done loading
|
||||||
callback();
|
this.loading = false;
|
||||||
|
this.justLoaded = true;
|
||||||
|
callback();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -198,6 +192,10 @@ export default class ResourceManager {
|
||||||
this.loadonly_imagesToLoad = 0;
|
this.loadonly_imagesToLoad = 0;
|
||||||
this.images.clear();
|
this.images.clear();
|
||||||
|
|
||||||
|
this.loadonly_spritesheetsLoaded = 0;
|
||||||
|
this.loadonly_spritesheetsToLoad = 0;
|
||||||
|
this.spritesheets.clear();
|
||||||
|
|
||||||
this.loadonly_tilemapsLoaded = 0;
|
this.loadonly_tilemapsLoaded = 0;
|
||||||
this.loadonly_tilemapsToLoad = 0;
|
this.loadonly_tilemapsToLoad = 0;
|
||||||
this.tilemaps.clear();
|
this.tilemaps.clear();
|
||||||
|
@ -252,7 +250,6 @@ export default class ResourceManager {
|
||||||
this.loadonly_imageLoadingQueue.enqueue({key: key, path: path});
|
this.loadonly_imageLoadingQueue.enqueue({key: key, path: path});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish loading
|
// Finish loading
|
||||||
|
@ -273,8 +270,62 @@ export default class ResourceManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads all spritesheets currently in the spritesheet loading queue
|
||||||
|
* @param onFinishLoading
|
||||||
|
*/
|
||||||
|
private loadSpritesheetsFromQueue(onFinishLoading: Function): void {
|
||||||
|
this.loadonly_spritesheetsToLoad = this.loadonly_spritesheetLoadingQueue.getSize();
|
||||||
|
this.loadonly_spritesheetsLoaded = 0;
|
||||||
|
|
||||||
|
// If no items to load, we're finished
|
||||||
|
if(this.loadonly_spritesheetsToLoad === 0){
|
||||||
|
onFinishLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
while(this.loadonly_spritesheetLoadingQueue.hasItems()){
|
||||||
|
let spritesheet = this.loadonly_spritesheetLoadingQueue.dequeue();
|
||||||
|
this.loadSpritesheet(spritesheet.key, spritesheet.path, onFinishLoading);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all images currently in the tilemap loading queue
|
* Loads a singular spritesheet
|
||||||
|
* @param key
|
||||||
|
* @param pathToSpritesheetJSON
|
||||||
|
* @param callbackIfLast
|
||||||
|
*/
|
||||||
|
private loadSpritesheet(key: string, pathToSpritesheetJSON: string, callbackIfLast: Function): void {
|
||||||
|
this.loadTextFile(pathToSpritesheetJSON, (fileText: string) => {
|
||||||
|
let spritesheet = <Spritesheet>JSON.parse(fileText);
|
||||||
|
|
||||||
|
// We can parse the object later - it's much faster than loading
|
||||||
|
this.spritesheets.add(key, spritesheet);
|
||||||
|
|
||||||
|
// Grab the image we need to load and add it to the imageloading queue
|
||||||
|
let path = StringUtils.getPathFromFilePath(pathToSpritesheetJSON) + spritesheet.spriteSheetImage;
|
||||||
|
this.loadonly_imageLoadingQueue.enqueue({key: spritesheet.name, path: path});
|
||||||
|
|
||||||
|
// Finish loading
|
||||||
|
this.finishLoadingSpritesheet(callbackIfLast);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finish loading a spritesheet. Calls the callback function if this is the last spritesheet being loaded
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
private finishLoadingSpritesheet(callback: Function): void {
|
||||||
|
this.loadonly_spritesheetsLoaded += 1;
|
||||||
|
|
||||||
|
if(this.loadonly_spritesheetsLoaded === this.loadonly_spritesheetsToLoad){
|
||||||
|
// We're done loading spritesheets
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads all images currently in the image loading queue
|
||||||
* @param onFinishLoading
|
* @param onFinishLoading
|
||||||
*/
|
*/
|
||||||
private loadImagesFromQueue(onFinishLoading: Function): void {
|
private loadImagesFromQueue(onFinishLoading: Function): void {
|
||||||
|
@ -398,6 +449,7 @@ export default class ResourceManager {
|
||||||
|
|
||||||
private getLoadPercent(): number {
|
private getLoadPercent(): number {
|
||||||
return (this.loadonly_tilemapsLoaded/this.loadonly_tilemapsToLoad
|
return (this.loadonly_tilemapsLoaded/this.loadonly_tilemapsToLoad
|
||||||
|
+ this.loadonly_spritesheetsLoaded/this.loadonly_spritesheetsToLoad
|
||||||
+ this.loadonly_imagesLoaded/this.loadonly_imagesToLoad
|
+ this.loadonly_imagesLoaded/this.loadonly_imagesToLoad
|
||||||
+ this.loadonly_audioLoaded/this.loadonly_audioToLoad)
|
+ this.loadonly_audioLoaded/this.loadonly_audioToLoad)
|
||||||
/ this.loadonly_typesToLoad;
|
/ this.loadonly_typesToLoad;
|
||||||
|
|
|
@ -2,6 +2,7 @@ import Scene from "../Scene";
|
||||||
import UIElement from "../../Nodes/UIElement";
|
import UIElement from "../../Nodes/UIElement";
|
||||||
import Graphic from "../../Nodes/Graphic";
|
import Graphic from "../../Nodes/Graphic";
|
||||||
import Sprite from "../../Nodes/Sprites/Sprite";
|
import Sprite from "../../Nodes/Sprites/Sprite";
|
||||||
|
import AnimatedSprite from "../../Nodes/Sprites/AnimatedSprite";
|
||||||
import { GraphicType } from "../../Nodes/Graphics/GraphicTypes";
|
import { GraphicType } from "../../Nodes/Graphics/GraphicTypes";
|
||||||
import { UIElementType } from "../../Nodes/UIElements/UIElementTypes";
|
import { UIElementType } from "../../Nodes/UIElements/UIElementTypes";
|
||||||
import Point from "../../Nodes/Graphics/Point";
|
import Point from "../../Nodes/Graphics/Point";
|
||||||
|
@ -11,12 +12,15 @@ import Label from "../../Nodes/UIElements/Label";
|
||||||
import Slider from "../../Nodes/UIElements/Slider";
|
import Slider from "../../Nodes/UIElements/Slider";
|
||||||
import TextInput from "../../Nodes/UIElements/TextInput";
|
import TextInput from "../../Nodes/UIElements/TextInput";
|
||||||
import Rect from "../../Nodes/Graphics/Rect";
|
import Rect from "../../Nodes/Graphics/Rect";
|
||||||
|
import ResourceManager from "../../ResourceManager/ResourceManager";
|
||||||
|
|
||||||
export default class CanvasNodeFactory {
|
export default class CanvasNodeFactory {
|
||||||
private scene: Scene;
|
protected scene: Scene;
|
||||||
|
protected resourceManager: ResourceManager;
|
||||||
|
|
||||||
init(scene: Scene): void {
|
init(scene: Scene): void {
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
|
this.resourceManager = ResourceManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,6 +83,22 @@ export default class CanvasNodeFactory {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addAnimatedSprite = (key: string, layerName: string): AnimatedSprite => {
|
||||||
|
let layer = this.scene.getLayer(layerName);
|
||||||
|
let spritesheet = this.resourceManager.getSpritesheet(key);
|
||||||
|
let instance = new AnimatedSprite(spritesheet);
|
||||||
|
|
||||||
|
// Add instance fo scene
|
||||||
|
instance.setScene(this.scene);
|
||||||
|
instance.id = this.scene.generateId();
|
||||||
|
this.scene.getSceneGraph().addNode(instance);
|
||||||
|
|
||||||
|
// Add instance to layer
|
||||||
|
layer.addNode(instance);
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new graphic element to the current Scene
|
* Adds a new graphic element to the current Scene
|
||||||
* @param type The type of graphic to add
|
* @param type The type of graphic to add
|
||||||
|
|
|
@ -17,6 +17,7 @@ export default class FactoryManager {
|
||||||
// Expose all of the factories through the factory manager
|
// Expose all of the factories through the factory manager
|
||||||
uiElement = this.canvasNodeFactory.addUIElement;
|
uiElement = this.canvasNodeFactory.addUIElement;
|
||||||
sprite = this.canvasNodeFactory.addSprite;
|
sprite = this.canvasNodeFactory.addSprite;
|
||||||
|
animatedSprite = this.canvasNodeFactory.addAnimatedSprite;
|
||||||
graphic = this.canvasNodeFactory.addGraphic;
|
graphic = this.canvasNodeFactory.addGraphic;
|
||||||
tilemap = this.tilemapFactory.add;
|
tilemap = this.tilemapFactory.add;
|
||||||
}
|
}
|
|
@ -11,8 +11,13 @@ import Level1 from "./Level1";
|
||||||
|
|
||||||
export default class MainMenu extends Scene {
|
export default class MainMenu extends Scene {
|
||||||
|
|
||||||
|
loadScene(): void {
|
||||||
|
this.load.spritesheet("walker", "assets/spritesheets/walking.json");
|
||||||
|
}
|
||||||
|
|
||||||
startScene(): void {
|
startScene(): void {
|
||||||
this.addUILayer("Main");
|
this.addUILayer("Main");
|
||||||
|
this.addLayer("Sprite");
|
||||||
|
|
||||||
let size = this.viewport.getHalfSize();
|
let size = this.viewport.getHalfSize();
|
||||||
this.viewport.setFocus(size);
|
this.viewport.setFocus(size);
|
||||||
|
@ -37,10 +42,11 @@ export default class MainMenu extends Scene {
|
||||||
this.sceneManager.changeScene(Level1, sceneOptions);
|
this.sceneManager.changeScene(Level1, sceneOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
let slider = <Slider>this.add.uiElement(UIElementType.SLIDER, "Main", {position: new Vec2(size.x, size.y*1.5)});
|
let animatedSprite = this.add.animatedSprite("walker", "Sprite");
|
||||||
let label = this.add.uiElement(UIElementType.LABEL, "Main", {position: new Vec2(size.x + 150, size.y*1.5), text: ""});
|
animatedSprite.position.set(100, 100);
|
||||||
slider.onValueChange = (value) => (<Label>label).setText(value.toString());
|
animatedSprite.scale.set(4, 4);
|
||||||
this.add.uiElement(UIElementType.TEXT_INPUT, "Main", {position: new Vec2(size.x, size.y*1.7)});
|
animatedSprite.animation.play("JUMP");
|
||||||
|
animatedSprite.animation.queue("WALK", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateScene(): void {
|
updateScene(): void {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user