add Timers and Lines, and modified Registry
This commit is contained in:
		
							parent
							
								
									924469a2cd
								
							
						
					
					
						commit
						c241aa99bc
					
				| 
						 | 
				
			
			@ -50,6 +50,8 @@ export default class Graph {
 | 
			
		|||
	addEdge(x: number, y: number, weight?: number): void {
 | 
			
		||||
		let edge = new EdgeNode(y, weight);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		if(this.edges[x]){
 | 
			
		||||
			edge.next = this.edges[x];
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -69,6 +71,24 @@ export default class Graph {
 | 
			
		|||
		this.numEdges += 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Checks whether or not an edge exists between two nodes.
 | 
			
		||||
	 * This check is directional if this is a directed graph.
 | 
			
		||||
	 * @param x The first node
 | 
			
		||||
	 * @param y The second node
 | 
			
		||||
	 * @returns true if an edge exists, false otherwise
 | 
			
		||||
	 */
 | 
			
		||||
	edgeExists(x: number, y: number): boolean {
 | 
			
		||||
		let edge = this.edges[x];
 | 
			
		||||
 | 
			
		||||
		while(edge !== null){
 | 
			
		||||
			if(edge.y === y){
 | 
			
		||||
				return true;
 | 
			
		||||
			}
 | 
			
		||||
			edge = edge.next;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Gets the edge list associated with node x
 | 
			
		||||
	 * @param x The index of the node
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,4 +33,11 @@ export default interface Actor {
 | 
			
		|||
     * @param options An object that allows options to be pased to the activated AI
 | 
			
		||||
     */
 | 
			
		||||
    setAIActive(active: boolean, options: Record<string, any>): void;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Moves this GameNode along a path
 | 
			
		||||
     * @param speed The speed to move with
 | 
			
		||||
     * @param path The path we're moving along
 | 
			
		||||
     */
 | 
			
		||||
    moveOnPath(speed: number, path: NavigationPath): void;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -109,4 +109,22 @@ export default class Queue<T> implements Collection {
 | 
			
		|||
            i = (i + 1) % this.MAX_ELEMENTS;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Converts this queue into a string format
 | 
			
		||||
     * @returns A string representing this queue
 | 
			
		||||
     */
 | 
			
		||||
    toString(): string {
 | 
			
		||||
        let retval = "";
 | 
			
		||||
 | 
			
		||||
        this.forEach( (item, index) => {
 | 
			
		||||
            let str = item.toString()
 | 
			
		||||
            if(index !== 0){
 | 
			
		||||
                str += " -> "
 | 
			
		||||
            }
 | 
			
		||||
            retval = str + retval;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        return "Top -> " + retval;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -25,8 +25,9 @@ export default abstract class State implements Updateable {
 | 
			
		|||
 | 
			
		||||
    /**
 | 
			
		||||
     * A method that is called when this state is entered. Use this to initialize any variables before updates occur.
 | 
			
		||||
     * @param options Information to pass to this state
 | 
			
		||||
     */
 | 
			
		||||
    abstract onEnter(): void;
 | 
			
		||||
    abstract onEnter(options: Record<string, any>): void;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * A lifecycle method that handles an input event, such as taking damage.
 | 
			
		||||
| 
						 | 
				
			
			@ -42,11 +43,13 @@ export default abstract class State implements Updateable {
 | 
			
		|||
     * @param stateName The name of the state to transition to
 | 
			
		||||
     */
 | 
			
		||||
    protected finished(stateName: string): void {
 | 
			
		||||
        console.log("Finished");
 | 
			
		||||
        this.parent.changeState(stateName);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * A lifecycle method is called when the state is ending.
 | 
			
		||||
     * @returns info to pass to the next state
 | 
			
		||||
     */
 | 
			
		||||
    abstract onExit(): void;
 | 
			
		||||
    abstract onExit(): Record<string, any>;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -67,9 +67,10 @@ export default class StateMachine implements Updateable {
 | 
			
		|||
     * Initializes this state machine with an initial state and sets it running
 | 
			
		||||
     * @param initialState The name of initial state of the state machine
 | 
			
		||||
     */
 | 
			
		||||
    initialize(initialState: string): void {
 | 
			
		||||
    initialize(initialState: string, options: Record<string, any> = {}): void {
 | 
			
		||||
        this.stack.push(this.stateMap.get(initialState));
 | 
			
		||||
        this.currentState = this.stack.peek();
 | 
			
		||||
        this.currentState.onEnter(options);
 | 
			
		||||
        this.setActive(true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -88,7 +89,7 @@ export default class StateMachine implements Updateable {
 | 
			
		|||
     */
 | 
			
		||||
    changeState(state: string): void {
 | 
			
		||||
        // Exit the current state
 | 
			
		||||
        this.currentState.onExit();
 | 
			
		||||
        let options = this.currentState.onExit();
 | 
			
		||||
 | 
			
		||||
        // Make sure the correct state is at the top of the stack
 | 
			
		||||
        if(state === "previous"){
 | 
			
		||||
| 
						 | 
				
			
			@ -109,7 +110,7 @@ export default class StateMachine implements Updateable {
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        // Enter the new state
 | 
			
		||||
        this.currentState.onEnter();
 | 
			
		||||
        this.currentState.onEnter(options);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -124,6 +125,12 @@ export default class StateMachine implements Updateable {
 | 
			
		|||
 | 
			
		||||
    // @implemented
 | 
			
		||||
    update(deltaT: number): void {
 | 
			
		||||
        // Distribute events
 | 
			
		||||
        while(this.receiver.hasNextEvent()){
 | 
			
		||||
            let event = this.receiver.getNextEvent();
 | 
			
		||||
            this.handleEvent(event);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Delegate the update to the current state
 | 
			
		||||
        this.currentState.update(deltaT);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -110,6 +110,10 @@ export default class Vec2 {
 | 
			
		|||
	 * @returns A new vector that is the unit vector for this one
 | 
			
		||||
	 */
 | 
			
		||||
	normalized(): Vec2 {
 | 
			
		||||
		if(this.isZero()){
 | 
			
		||||
			return this;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		let mag = this.mag();
 | 
			
		||||
		return new Vec2(this.x/mag, this.y/mag);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -235,6 +239,23 @@ export default class Vec2 {
 | 
			
		|||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Increments the fields of this vector. Both are incremented with a, if only a is provided.
 | 
			
		||||
	 * @param a The first number to increment by
 | 
			
		||||
	 * @param b The second number to increment by
 | 
			
		||||
	 * @returnss This vector after incrementing
 | 
			
		||||
	 */
 | 
			
		||||
	inc(a: number, b?: number): Vec2 {
 | 
			
		||||
		if(b === undefined){
 | 
			
		||||
			this.x += a;
 | 
			
		||||
			this.y += a;
 | 
			
		||||
		} else {
 | 
			
		||||
			this.x += a;
 | 
			
		||||
			this.y += b;
 | 
			
		||||
		}
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Subtracts another vector from this vector
 | 
			
		||||
	 * @param other The Vec2 to subtract from this one
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -260,7 +260,7 @@ export default class Input {
 | 
			
		|||
	 * @returns The mouse position stored as a Vec2
 | 
			
		||||
	 */
 | 
			
		||||
	static getMousePosition(): Vec2 {
 | 
			
		||||
		return Input.mousePosition;
 | 
			
		||||
		return Input.mousePosition.scaled(1/this.viewport.getZoomLevel());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
| 
						 | 
				
			
			@ -269,7 +269,7 @@ export default class Input {
 | 
			
		|||
	 * @returns The mouse position stored as a Vec2
 | 
			
		||||
	 */
 | 
			
		||||
	static getGlobalMousePosition(): Vec2 {
 | 
			
		||||
		return Input.mousePosition.clone().add(Input.viewport.getOrigin());
 | 
			
		||||
		return Input.mousePosition.clone().scale(1/this.viewport.getZoomLevel()).add(Input.viewport.getOrigin());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ import GameLoop from "./GameLoop";
 | 
			
		|||
import FixedUpdateGameLoop from "./FixedUpdateGameLoop";
 | 
			
		||||
import EnvironmentInitializer from "./EnvironmentInitializer";
 | 
			
		||||
import Vec2 from "../DataTypes/Vec2";
 | 
			
		||||
import Registry from "../Registry/Registry";
 | 
			
		||||
import RegistryManager from "../Registry/RegistryManager";
 | 
			
		||||
import WebGLRenderer from "../Rendering/WebGLRenderer";
 | 
			
		||||
import Scene from "../Scene/Scene";
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -139,7 +139,7 @@ export default class Game {
 | 
			
		|||
        this.loop.doRender = () => this.render();
 | 
			
		||||
 | 
			
		||||
        // Preload registry items
 | 
			
		||||
        Registry.preload();
 | 
			
		||||
        RegistryManager.preload();
 | 
			
		||||
 | 
			
		||||
        // Load the items with the resource manager
 | 
			
		||||
        this.resourceManager.loadResourcesFromQueue(() => {
 | 
			
		||||
| 
						 | 
				
			
			@ -185,6 +185,11 @@ export default class Game {
 | 
			
		|||
 | 
			
		||||
        this.sceneManager.render();
 | 
			
		||||
 | 
			
		||||
        // Hacky debug mode
 | 
			
		||||
        if(Input.isKeyJustPressed("g")){
 | 
			
		||||
            this.showDebug = !this.showDebug;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Debug render
 | 
			
		||||
        if(this.showDebug){
 | 
			
		||||
            Debug.render();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -109,7 +109,6 @@ export default abstract class GameNode implements Positioned, Unique, Updateable
 | 
			
		|||
	inRelativeCoordinates(point: Vec2): Vec2 {
 | 
			
		||||
		let origin = this.scene.getViewTranslation(this);
 | 
			
		||||
		let zoom = this.scene.getViewScale();
 | 
			
		||||
 | 
			
		||||
		return point.clone().sub(origin).scale(zoom);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -137,6 +136,14 @@ export default abstract class GameNode implements Positioned, Unique, Updateable
 | 
			
		|||
		this._velocity = velocity;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	moveOnPath(speed: number, path: NavigationPath): void {
 | 
			
		||||
		this.path = path;
 | 
			
		||||
		let dir = path.getMoveDirection(this);
 | 
			
		||||
		this.moving = true;
 | 
			
		||||
		this.pathfinding = true;
 | 
			
		||||
		this._velocity = dir.scale(speed);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// @implemented
 | 
			
		||||
    /**
 | 
			
		||||
     * @param velocity The velocity with which the object will move.
 | 
			
		||||
| 
						 | 
				
			
			@ -146,6 +153,8 @@ export default abstract class GameNode implements Positioned, Unique, Updateable
 | 
			
		|||
		this.position.add(this._velocity);
 | 
			
		||||
		if(this.pathfinding){
 | 
			
		||||
			this.path.handlePathProgress(this);
 | 
			
		||||
			this.path = null;
 | 
			
		||||
			this.pathfinding = false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -266,7 +275,9 @@ export default abstract class GameNode implements Positioned, Unique, Updateable
 | 
			
		|||
	// @implemented
 | 
			
		||||
	setAIActive(active: boolean, options: Record<string, any>): void {
 | 
			
		||||
		this.aiActive = active;
 | 
			
		||||
		this.ai.activate(options);
 | 
			
		||||
		if(this.aiActive){
 | 
			
		||||
			this.ai.activate(options);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*---------- TWEENABLE PROPERTIES ----------*/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
export enum GraphicType {
 | 
			
		||||
	POINT = "POINT",
 | 
			
		||||
	RECT = "RECT",
 | 
			
		||||
	LINE = "LINE",
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								src/Wolfie2D/Nodes/Graphics/Line.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/Wolfie2D/Nodes/Graphics/Line.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
import Vec2 from "../../DataTypes/Vec2";
 | 
			
		||||
import Graphic from "../Graphic";
 | 
			
		||||
 | 
			
		||||
export default class Line extends Graphic {
 | 
			
		||||
    protected _end: Vec2;
 | 
			
		||||
    thickness: number;
 | 
			
		||||
 | 
			
		||||
    constructor(start: Vec2, end: Vec2){
 | 
			
		||||
        super();
 | 
			
		||||
        this.start = start;
 | 
			
		||||
        this.end = end;
 | 
			
		||||
        this.thickness = 2;
 | 
			
		||||
 | 
			
		||||
        // Does this really have a meaning for lines?
 | 
			
		||||
        this.size.set(5, 5);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    set start(pos: Vec2){
 | 
			
		||||
        this.position = pos;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get start(): Vec2 {
 | 
			
		||||
        return this.position;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    set end(pos: Vec2){
 | 
			
		||||
        this._end = pos;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get end(): Vec2 {
 | 
			
		||||
        return this._end;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ export default abstract class Tilemap extends CanvasNode {
 | 
			
		|||
 | 
			
		||||
        let tilecount = 0;
 | 
			
		||||
        for(let tileset of tilesets){
 | 
			
		||||
            tilecount += tileset.getTileCount();
 | 
			
		||||
            tilecount += tileset.getTileCount() + 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.collisionMap = new Array(tilecount);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,9 +19,8 @@ export default class NavigationPath {
 | 
			
		|||
	 */
 | 
			
		||||
	constructor(path: Stack<Vec2>){
 | 
			
		||||
		this.path = path;
 | 
			
		||||
		console.log(path.toString())
 | 
			
		||||
		this.currentMoveDirection = Vec2.ZERO;
 | 
			
		||||
		this.distanceThreshold = 20;
 | 
			
		||||
		this.distanceThreshold = 4;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
| 
						 | 
				
			
			@ -52,4 +51,8 @@ export default class NavigationPath {
 | 
			
		|||
			this.path.pop();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	toString(): string {
 | 
			
		||||
		return this.path.toString()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								src/Wolfie2D/Registry/Registries/Registry.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/Wolfie2D/Registry/Registries/Registry.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
import Map from "../../DataTypes/Map";
 | 
			
		||||
 | 
			
		||||
export default abstract class Registry<T> extends Map<T>{
 | 
			
		||||
 | 
			
		||||
    /** Preloads registry data */
 | 
			
		||||
    public abstract preload(): void;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Registers an item and preloads any necessary files
 | 
			
		||||
     * @param key The key to register this item with
 | 
			
		||||
     * @param args Any additional arguments needed for registration
 | 
			
		||||
     */
 | 
			
		||||
    public abstract registerAndPreloadItem(key: string, ...args: any): void;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Registers an item and preloads any necessary files
 | 
			
		||||
     * @param key The key to register this item with
 | 
			
		||||
     * @param args Any aditional arguments needed for registration
 | 
			
		||||
     */
 | 
			
		||||
    public abstract registerItem(key: string, ...args: any): void;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -5,11 +5,12 @@ import PointShaderType from "../../Rendering/WebGLRendering/ShaderTypes/PointSha
 | 
			
		|||
import RectShaderType from "../../Rendering/WebGLRendering/ShaderTypes/RectShaderType";
 | 
			
		||||
import SpriteShaderType from "../../Rendering/WebGLRendering/ShaderTypes/SpriteShaderType";
 | 
			
		||||
import ResourceManager from "../../ResourceManager/ResourceManager";
 | 
			
		||||
import Registry from "./Registry";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A registry that handles shaders
 | 
			
		||||
 */
 | 
			
		||||
export default class ShaderRegistry extends Map<ShaderType> {
 | 
			
		||||
export default class ShaderRegistry extends Registry<ShaderType> {
 | 
			
		||||
 | 
			
		||||
	// Shader names
 | 
			
		||||
	public static POINT_SHADER = "point";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,16 +0,0 @@
 | 
			
		|||
import ShaderRegistry from "./Registries/ShaderRegistry";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The Registry is the system's way of converting classes and types into string
 | 
			
		||||
 * representations for use elsewhere in the application.
 | 
			
		||||
 * It allows classes to be accessed without explicitly using constructors in code,
 | 
			
		||||
 * and for resources to be loaded at Game creation time.
 | 
			
		||||
 */
 | 
			
		||||
export default class Registry {
 | 
			
		||||
 | 
			
		||||
	public static shaders = new ShaderRegistry();
 | 
			
		||||
 | 
			
		||||
	static preload(){
 | 
			
		||||
		this.shaders.preload();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								src/Wolfie2D/Registry/RegistryManager.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/Wolfie2D/Registry/RegistryManager.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,31 @@
 | 
			
		|||
import Map from "../DataTypes/Map";
 | 
			
		||||
import Registry from "./Registries/Registry";
 | 
			
		||||
import ShaderRegistry from "./Registries/ShaderRegistry";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The Registry is the system's way of converting classes and types into string
 | 
			
		||||
 * representations for use elsewhere in the application.
 | 
			
		||||
 * It allows classes to be accessed without explicitly using constructors in code,
 | 
			
		||||
 * and for resources to be loaded at Game creation time.
 | 
			
		||||
 */
 | 
			
		||||
export default class RegistryManager {
 | 
			
		||||
 | 
			
		||||
	public static shaders = new ShaderRegistry();
 | 
			
		||||
 | 
			
		||||
	/** Additional custom registries to add to the registry manager */
 | 
			
		||||
	protected static registries: Map<Registry<any>> = new Map();
 | 
			
		||||
 | 
			
		||||
	static preload(){
 | 
			
		||||
		this.shaders.preload();
 | 
			
		||||
 | 
			
		||||
		this.registries.forEach((key: string) => this.registries.get(key).preload());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static addCustomRegistry(name: string, registry: Registry<any>){
 | 
			
		||||
		this.registries.add(name, registry);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static getRegistry(key: string){
 | 
			
		||||
		return this.registries.get(key);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -20,6 +20,8 @@ import TextInput from "../Nodes/UIElements/TextInput";
 | 
			
		|||
import AnimatedSprite from "../Nodes/Sprites/AnimatedSprite";
 | 
			
		||||
import Vec2 from "../DataTypes/Vec2";
 | 
			
		||||
import Color from "../Utils/Color";
 | 
			
		||||
import Line from "../Nodes/Graphics/Line";
 | 
			
		||||
import Debug from "../Debug/Debug";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * An implementation of the RenderingManager class using CanvasRenderingContext2D.
 | 
			
		||||
| 
						 | 
				
			
			@ -112,9 +114,19 @@ export default class CanvasRenderer extends RenderingManager {
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        // Render the uiLayers on top of everything else
 | 
			
		||||
        uiLayers.forEach(key => {
 | 
			
		||||
			if(!uiLayers.get(key).isHidden())
 | 
			
		||||
				uiLayers.get(key).getItems().forEach(node => this.renderNode(<CanvasNode>node))
 | 
			
		||||
        let sortedUILayers = new Array<UILayer>();
 | 
			
		||||
 | 
			
		||||
        uiLayers.forEach(key => sortedUILayers.push(uiLayers.get(key)));
 | 
			
		||||
 | 
			
		||||
        sortedUILayers = sortedUILayers.sort((ui1, ui2) => ui1.getDepth() - ui2.getDepth());
 | 
			
		||||
 | 
			
		||||
        sortedUILayers.forEach(uiLayer => {
 | 
			
		||||
			if(!uiLayer.isHidden())
 | 
			
		||||
				uiLayer.getItems().forEach(node => {
 | 
			
		||||
                    if((<CanvasNode>node).visible){
 | 
			
		||||
                        this.renderNode(<CanvasNode>node)
 | 
			
		||||
                    }
 | 
			
		||||
                })
 | 
			
		||||
		});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -141,7 +153,7 @@ export default class CanvasRenderer extends RenderingManager {
 | 
			
		|||
        this.ctx.setTransform(xScale, 0, 0, yScale, (node.position.x - this.origin.x)*this.zoom, (node.position.y - this.origin.y)*this.zoom);
 | 
			
		||||
        this.ctx.rotate(-node.rotation);
 | 
			
		||||
        let globalAlpha = this.ctx.globalAlpha;
 | 
			
		||||
        this.ctx.globalAlpha = node.alpha;
 | 
			
		||||
        this.ctx.globalAlpha = ((<any>node).color ? (<any>node).color.a : 1) * node.alpha;
 | 
			
		||||
        
 | 
			
		||||
        if(node instanceof AnimatedSprite){
 | 
			
		||||
            this.renderAnimatedSprite(<AnimatedSprite>node);
 | 
			
		||||
| 
						 | 
				
			
			@ -205,6 +217,8 @@ export default class CanvasRenderer extends RenderingManager {
 | 
			
		|||
    protected renderGraphic(graphic: Graphic): void {
 | 
			
		||||
        if(graphic instanceof Point){
 | 
			
		||||
            this.graphicRenderer.renderPoint(<Point>graphic, this.zoom);
 | 
			
		||||
        } else if(graphic instanceof Line){
 | 
			
		||||
            this.graphicRenderer.renderLine(<Line>graphic, this.origin, this.zoom);
 | 
			
		||||
        } else if(graphic instanceof Rect){
 | 
			
		||||
            this.graphicRenderer.renderRect(<Rect>graphic, this.zoom);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
import Vec2 from "../../DataTypes/Vec2";
 | 
			
		||||
import Line from "../../Nodes/Graphics/Line";
 | 
			
		||||
import Point from "../../Nodes/Graphics/Point";
 | 
			
		||||
import Rect from "../../Nodes/Graphics/Rect";
 | 
			
		||||
import ResourceManager from "../../ResourceManager/ResourceManager";
 | 
			
		||||
| 
						 | 
				
			
			@ -38,6 +40,16 @@ export default class GraphicRenderer {
 | 
			
		|||
        point.size.x*zoom, point.size.y*zoom);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    renderLine(line: Line, origin: Vec2, zoom: number): void {
 | 
			
		||||
        this.ctx.strokeStyle = line.color.toStringRGBA();
 | 
			
		||||
        this.ctx.lineWidth = line.thickness;
 | 
			
		||||
        this.ctx.beginPath();
 | 
			
		||||
        this.ctx.moveTo(0, 0);
 | 
			
		||||
        this.ctx.lineTo((line.end.x - line.start.x)*zoom, (line.end.y - line.start.y)*zoom);
 | 
			
		||||
        this.ctx.closePath();
 | 
			
		||||
        this.ctx.stroke();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Renders a rect
 | 
			
		||||
     * @param rect The rect to render
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,7 @@ import Tilemap from "../Nodes/Tilemap";
 | 
			
		|||
import UIElement from "../Nodes/UIElement";
 | 
			
		||||
import Label from "../Nodes/UIElements/Label";
 | 
			
		||||
import ShaderRegistry from "../Registry/Registries/ShaderRegistry";
 | 
			
		||||
import Registry from "../Registry/Registry";
 | 
			
		||||
import RegistryManager from "../Registry/RegistryManager";
 | 
			
		||||
import ResourceManager from "../ResourceManager/ResourceManager";
 | 
			
		||||
import ParallaxLayer from "../Scene/Layers/ParallaxLayer";
 | 
			
		||||
import UILayer from "../Scene/Layers/UILayer";
 | 
			
		||||
| 
						 | 
				
			
			@ -106,13 +106,13 @@ export default class WebGLRenderer extends RenderingManager {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	protected renderSprite(sprite: Sprite): void {
 | 
			
		||||
		let shader = Registry.shaders.get(ShaderRegistry.SPRITE_SHADER);
 | 
			
		||||
		let shader = RegistryManager.shaders.get(ShaderRegistry.SPRITE_SHADER);
 | 
			
		||||
		let options = this.addOptions(shader.getOptions(sprite), sprite);
 | 
			
		||||
		shader.render(this.gl, options);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected renderAnimatedSprite(sprite: AnimatedSprite): void {
 | 
			
		||||
		let shader = Registry.shaders.get(ShaderRegistry.SPRITE_SHADER);
 | 
			
		||||
		let shader = RegistryManager.shaders.get(ShaderRegistry.SPRITE_SHADER);
 | 
			
		||||
		let options = this.addOptions(shader.getOptions(sprite), sprite);
 | 
			
		||||
		shader.render(this.gl, options);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -120,11 +120,11 @@ export default class WebGLRenderer extends RenderingManager {
 | 
			
		|||
	protected renderGraphic(graphic: Graphic): void {
 | 
			
		||||
 | 
			
		||||
		if(graphic instanceof Point){
 | 
			
		||||
			let shader = Registry.shaders.get(ShaderRegistry.POINT_SHADER);
 | 
			
		||||
			let shader = RegistryManager.shaders.get(ShaderRegistry.POINT_SHADER);
 | 
			
		||||
			let options = this.addOptions(shader.getOptions(graphic), graphic);
 | 
			
		||||
			shader.render(this.gl, options);
 | 
			
		||||
		} else if(graphic instanceof Rect) {
 | 
			
		||||
			let shader = Registry.shaders.get(ShaderRegistry.RECT_SHADER);
 | 
			
		||||
			let shader = RegistryManager.shaders.get(ShaderRegistry.RECT_SHADER);
 | 
			
		||||
			let options = this.addOptions(shader.getOptions(graphic), graphic);
 | 
			
		||||
			shader.render(this.gl, options);
 | 
			
		||||
		} 
 | 
			
		||||
| 
						 | 
				
			
			@ -136,7 +136,7 @@ export default class WebGLRenderer extends RenderingManager {
 | 
			
		|||
 | 
			
		||||
	protected renderUIElement(uiElement: UIElement): void {
 | 
			
		||||
		if(uiElement instanceof Label){
 | 
			
		||||
			let shader = Registry.shaders.get(ShaderRegistry.LABEL_SHADER);
 | 
			
		||||
			let shader = RegistryManager.shaders.get(ShaderRegistry.LABEL_SHADER);
 | 
			
		||||
			let options = this.addOptions(shader.getOptions(uiElement), uiElement);
 | 
			
		||||
			shader.render(this.gl, options);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -158,7 +158,7 @@ export default class WebGLRenderer extends RenderingManager {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	protected renderCustom(node: CanvasNode): void {
 | 
			
		||||
		let shader = Registry.shaders.get(node.customShaderKey);
 | 
			
		||||
		let shader = RegistryManager.shaders.get(node.customShaderKey);
 | 
			
		||||
		let options = this.addOptions(shader.getOptions(node), node);
 | 
			
		||||
		shader.render(this.gl, options);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,6 +69,11 @@ export default class ResourceManager {
 | 
			
		|||
    /** The total number of "types" of things that need to be loaded (i.e. images and tilemaps) */
 | 
			
		||||
    private loadonly_typesToLoad: number;
 | 
			
		||||
 | 
			
		||||
    private loadonly_jsonLoaded: number;
 | 
			
		||||
    private loadonly_jsonToLoad: number;
 | 
			
		||||
    private loadonly_jsonLoadingQueue: Queue<KeyPathPair>;
 | 
			
		||||
    private jsonObjects: Map<Record<string, any>>;
 | 
			
		||||
 | 
			
		||||
    /* ########## INFORMATION SPECIAL TO WEBGL ########## */
 | 
			
		||||
    private gl_WebGLActive: boolean;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -109,6 +114,11 @@ export default class ResourceManager {
 | 
			
		|||
        this.loadonly_audioLoadingQueue = new Queue();
 | 
			
		||||
        this.audioBuffers = new Map();
 | 
			
		||||
 | 
			
		||||
        this.loadonly_jsonLoaded = 0;
 | 
			
		||||
        this.loadonly_jsonToLoad = 0;
 | 
			
		||||
        this.loadonly_jsonLoadingQueue = new Queue();
 | 
			
		||||
        this.jsonObjects = new Map();
 | 
			
		||||
 | 
			
		||||
        this.loadonly_gl_ShaderProgramsLoaded = 0;
 | 
			
		||||
        this.loadonly_gl_ShaderProgramsToLoad = 0;
 | 
			
		||||
        this.loadonly_gl_ShaderLoadingQueue = new Queue();
 | 
			
		||||
| 
						 | 
				
			
			@ -222,6 +232,24 @@ export default class ResourceManager {
 | 
			
		|||
        return this.tilemaps.get(key);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Loads an object from a json file.
 | 
			
		||||
     * @param key The key to associate with the loaded object
 | 
			
		||||
     * @param path The path to the json file to load
 | 
			
		||||
     */
 | 
			
		||||
    public object(key: string, path: string){
 | 
			
		||||
        this.loadonly_jsonLoadingQueue.enqueue({key: key, path: path});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Retreives a loaded object
 | 
			
		||||
     * @param key The key of the loaded object
 | 
			
		||||
     * @returns The object data associated with the key
 | 
			
		||||
     */
 | 
			
		||||
    public getObject(key: string){
 | 
			
		||||
        return this.jsonObjects.get(key);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Loads all resources currently in the queue
 | 
			
		||||
     * @param callback The function to cal when the resources are finished loading
 | 
			
		||||
| 
						 | 
				
			
			@ -240,15 +268,18 @@ export default class ResourceManager {
 | 
			
		|||
                    console.log("Loaded Images");
 | 
			
		||||
                    this.loadAudioFromQueue(() => {
 | 
			
		||||
                        console.log("Loaded Audio");
 | 
			
		||||
                        this.loadObjectsFromQueue(() => {
 | 
			
		||||
                            console.log("Loaded Objects");
 | 
			
		||||
                            
 | 
			
		||||
                        if(this.gl_WebGLActive){
 | 
			
		||||
                            this.gl_LoadShadersFromQueue(() => {
 | 
			
		||||
                                console.log("Loaded Shaders");
 | 
			
		||||
                            if(this.gl_WebGLActive){
 | 
			
		||||
                                this.gl_LoadShadersFromQueue(() => {
 | 
			
		||||
                                    console.log("Loaded Shaders");
 | 
			
		||||
                                    this.finishLoading(callback);
 | 
			
		||||
                                });
 | 
			
		||||
                            } else {
 | 
			
		||||
                                this.finishLoading(callback);
 | 
			
		||||
                            });
 | 
			
		||||
                        } else {
 | 
			
		||||
                            this.finishLoading(callback);
 | 
			
		||||
                        }
 | 
			
		||||
                            }
 | 
			
		||||
                        })
 | 
			
		||||
                    });
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
| 
						 | 
				
			
			@ -303,6 +334,7 @@ export default class ResourceManager {
 | 
			
		|||
        // If no items to load, we're finished
 | 
			
		||||
        if(this.loadonly_tilemapsToLoad === 0){
 | 
			
		||||
            onFinishLoading();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        while(this.loadonly_tilemapLoadingQueue.hasItems()){
 | 
			
		||||
| 
						 | 
				
			
			@ -368,6 +400,7 @@ export default class ResourceManager {
 | 
			
		|||
        // If no items to load, we're finished
 | 
			
		||||
        if(this.loadonly_spritesheetsToLoad === 0){
 | 
			
		||||
            onFinishLoading();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        while(this.loadonly_spritesheetLoadingQueue.hasItems()){
 | 
			
		||||
| 
						 | 
				
			
			@ -422,6 +455,7 @@ export default class ResourceManager {
 | 
			
		|||
        // If no items to load, we're finished
 | 
			
		||||
        if(this.loadonly_imagesToLoad === 0){
 | 
			
		||||
            onFinishLoading();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        while(this.loadonly_imageLoadingQueue.hasItems()){
 | 
			
		||||
| 
						 | 
				
			
			@ -479,6 +513,7 @@ export default class ResourceManager {
 | 
			
		|||
        // If no items to load, we're finished
 | 
			
		||||
        if(this.loadonly_audioToLoad === 0){
 | 
			
		||||
            onFinishLoading();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        while(this.loadonly_audioLoadingQueue.hasItems()){
 | 
			
		||||
| 
						 | 
				
			
			@ -527,6 +562,53 @@ export default class ResourceManager {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Loads all objects currently in the object loading queue
 | 
			
		||||
     * @param onFinishLoading The function to call when there are no more objects to load
 | 
			
		||||
     */
 | 
			
		||||
    private loadObjectsFromQueue(onFinishLoading: Function): void {
 | 
			
		||||
        this.loadonly_jsonToLoad = this.loadonly_jsonLoadingQueue.getSize();
 | 
			
		||||
        this.loadonly_jsonLoaded = 0;
 | 
			
		||||
 | 
			
		||||
        // If no items to load, we're finished
 | 
			
		||||
        if(this.loadonly_jsonToLoad === 0){
 | 
			
		||||
            onFinishLoading();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        while(this.loadonly_jsonLoadingQueue.hasItems()){
 | 
			
		||||
            let obj = this.loadonly_jsonLoadingQueue.dequeue();
 | 
			
		||||
            this.loadObject(obj.key, obj.path, onFinishLoading);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Loads a singular object
 | 
			
		||||
     * @param key The key of the object to load
 | 
			
		||||
     * @param path The path to the object to load
 | 
			
		||||
     * @param callbackIfLast The function to call if this is the last object
 | 
			
		||||
     */
 | 
			
		||||
    public loadObject(key: string, path: string, callbackIfLast: Function): void {
 | 
			
		||||
        this.loadTextFile(path, (fileText: string) => {
 | 
			
		||||
            let obj = JSON.parse(fileText);
 | 
			
		||||
            this.jsonObjects.add(key, obj);
 | 
			
		||||
            this.finishLoadingObject(callbackIfLast);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Finish loading an object. If this is the last object, it calls the callback function
 | 
			
		||||
     * @param callback The function to call if this is the last object
 | 
			
		||||
     */
 | 
			
		||||
    private finishLoadingObject(callback: Function): void {
 | 
			
		||||
        this.loadonly_jsonLoaded += 1;
 | 
			
		||||
 | 
			
		||||
        if(this.loadonly_jsonLoaded === this.loadonly_jsonToLoad){
 | 
			
		||||
            // We're done loading objects
 | 
			
		||||
            callback();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* ########## WEBGL SPECIFIC FUNCTIONS ########## */
 | 
			
		||||
 | 
			
		||||
    public getTexture(key: string): number {
 | 
			
		||||
| 
						 | 
				
			
			@ -631,6 +713,7 @@ export default class ResourceManager {
 | 
			
		|||
        // If webGL isn'active or there are no items to load, we're finished
 | 
			
		||||
        if(!this.gl_WebGLActive || this.loadonly_gl_ShaderProgramsToLoad === 0){
 | 
			
		||||
            onFinishLoading();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        while(this.loadonly_gl_ShaderLoadingQueue.hasItems()){
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,7 @@ import Slider from "../../Nodes/UIElements/Slider";
 | 
			
		|||
import TextInput from "../../Nodes/UIElements/TextInput";
 | 
			
		||||
import Rect from "../../Nodes/Graphics/Rect";
 | 
			
		||||
import ResourceManager from "../../ResourceManager/ResourceManager";
 | 
			
		||||
import Line from "../../Nodes/Graphics/Line";
 | 
			
		||||
 | 
			
		||||
// @ignorePage
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -135,10 +136,13 @@ export default class CanvasNodeFactory {
 | 
			
		|||
		switch(type){
 | 
			
		||||
			case GraphicType.POINT:
 | 
			
		||||
				instance = this.buildPoint(options);
 | 
			
		||||
			break;
 | 
			
		||||
				break;
 | 
			
		||||
			case GraphicType.LINE:
 | 
			
		||||
				instance = this.buildLine(options);
 | 
			
		||||
				break;
 | 
			
		||||
			case GraphicType.RECT:
 | 
			
		||||
				instance = this.buildRect(options);
 | 
			
		||||
			break;
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				throw `GraphicType '${type}' does not exist, or is registered incorrectly.`
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -191,6 +195,13 @@ export default class CanvasNodeFactory {
 | 
			
		|||
		return new Point(options.position);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buildLine(options?: Record<string, any>): Point {
 | 
			
		||||
		this.checkIfPropExists("Line", options, "start", Vec2, "Vec2");
 | 
			
		||||
		this.checkIfPropExists("Line", options, "end", Vec2, "Vec2");
 | 
			
		||||
 | 
			
		||||
		return new Line(options.start, options.end);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buildRect(options?: Record<string, any>): Rect {
 | 
			
		||||
		this.checkIfPropExists("Rect", options, "position", Vec2, "Vec2");
 | 
			
		||||
		this.checkIfPropExists("Rect", options, "size", Vec2, "Vec2");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -159,6 +159,24 @@ export default class Layer {
 | 
			
		|||
        node.setLayer(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Removes a node from this layer
 | 
			
		||||
     * @param node The node to remove
 | 
			
		||||
     * @returns true if the node was removed, false otherwise
 | 
			
		||||
     */
 | 
			
		||||
    removeNode(node: GameNode): boolean {
 | 
			
		||||
        // Find and remove the node
 | 
			
		||||
        for(let i = 0; i < this.items.length; i++){
 | 
			
		||||
            if(this.items[i].id === node.id){
 | 
			
		||||
                this.items.splice(i, 1);
 | 
			
		||||
                node.setLayer(null);
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Retreives all GameNodes from this layer
 | 
			
		||||
     * @returns an Array that contains all of the GameNodes in this layer.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,7 @@ import GameNode from "../Nodes/GameNode";
 | 
			
		|||
import SceneOptions from "./SceneOptions";
 | 
			
		||||
import RenderingManager from "../Rendering/RenderingManager";
 | 
			
		||||
import Debug from "../Debug/Debug";
 | 
			
		||||
import TimerManager from "../Timing/TimerManager";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Scenes are the main container in the game engine.
 | 
			
		||||
| 
						 | 
				
			
			@ -119,6 +120,9 @@ export default class Scene implements Updateable {
 | 
			
		|||
        this.add = new FactoryManager(this, this.tilemaps);
 | 
			
		||||
 | 
			
		||||
        this.load = ResourceManager.getInstance();
 | 
			
		||||
 | 
			
		||||
        // Get the timer manager and clear any existing timers
 | 
			
		||||
        TimerManager.getInstance().clearTimers();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** A lifecycle method that gets called immediately after a new scene is created, before anything else. */
 | 
			
		||||
| 
						 | 
				
			
			@ -142,6 +146,9 @@ export default class Scene implements Updateable {
 | 
			
		|||
    update(deltaT: number): void {
 | 
			
		||||
        this.updateScene(deltaT);
 | 
			
		||||
 | 
			
		||||
        // Do time updates
 | 
			
		||||
        TimerManager.getInstance().update(deltaT);
 | 
			
		||||
 | 
			
		||||
        // Do all AI updates
 | 
			
		||||
        this.aiManager.update(deltaT);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										80
									
								
								src/Wolfie2D/Timing/Timer.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								src/Wolfie2D/Timing/Timer.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,80 @@
 | 
			
		|||
import Updateable from "../DataTypes/Interfaces/Updateable";
 | 
			
		||||
import MathUtils from "../Utils/MathUtils";
 | 
			
		||||
import TimerManager from "./TimerManager";
 | 
			
		||||
 | 
			
		||||
export default class Timer implements Updateable {
 | 
			
		||||
 | 
			
		||||
    protected state: TimerState;
 | 
			
		||||
    protected onEnd: Function;
 | 
			
		||||
    protected loop: boolean;
 | 
			
		||||
    protected totalTime: number;
 | 
			
		||||
    protected timeLeft: number;
 | 
			
		||||
 | 
			
		||||
    constructor(time: number, onEnd?: Function, loop: boolean = false){
 | 
			
		||||
        // Register this timer
 | 
			
		||||
        TimerManager.getInstance().addTimer(this);
 | 
			
		||||
        
 | 
			
		||||
        this.totalTime = time;
 | 
			
		||||
        this.timeLeft = 0;
 | 
			
		||||
        this.onEnd = onEnd;
 | 
			
		||||
        this.loop = loop;
 | 
			
		||||
        this.state = TimerState.STOPPED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    isStopped(){
 | 
			
		||||
        return this.state === TimerState.STOPPED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    isPaused(){
 | 
			
		||||
        return this.state === TimerState.PAUSED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    start(time?: number){
 | 
			
		||||
        if(time !== undefined){
 | 
			
		||||
            this.totalTime = time;
 | 
			
		||||
        }
 | 
			
		||||
        this.state = TimerState.ACTIVE;
 | 
			
		||||
        this.timeLeft = this.totalTime;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pause(): void {
 | 
			
		||||
        this.state = TimerState.PAUSED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    update(deltaT: number){
 | 
			
		||||
        if(this.state === TimerState.ACTIVE){
 | 
			
		||||
            this.timeLeft -= deltaT*1000;
 | 
			
		||||
 | 
			
		||||
            if(this.timeLeft <= 0){
 | 
			
		||||
                this.timeLeft = MathUtils.clampLow0(this.timeLeft);
 | 
			
		||||
                this.end();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected end(){
 | 
			
		||||
        // Update the state
 | 
			
		||||
        this.state = TimerState.STOPPED;
 | 
			
		||||
 | 
			
		||||
        // Call the end function if there is one
 | 
			
		||||
        if(this.onEnd){
 | 
			
		||||
            this.onEnd();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Loop if we want to
 | 
			
		||||
        if(this.loop){
 | 
			
		||||
            this.state = TimerState.ACTIVE;
 | 
			
		||||
            this.timeLeft = this.totalTime;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    toString(): string{
 | 
			
		||||
        return "Timer: " + this.state + " - Time Left: " + this.timeLeft + "ms of " + this.totalTime + "ms";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export enum TimerState {
 | 
			
		||||
    ACTIVE = "ACTIVE",
 | 
			
		||||
    PAUSED = "PAUSED",
 | 
			
		||||
    STOPPED = "STOPPED"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								src/Wolfie2D/Timing/TimerManager.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/Wolfie2D/Timing/TimerManager.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
import Updateable from "../DataTypes/Interfaces/Updateable";
 | 
			
		||||
import Timer from "./Timer";
 | 
			
		||||
 | 
			
		||||
export default class TimerManager implements Updateable {
 | 
			
		||||
 | 
			
		||||
    protected timers: Array<Timer>;
 | 
			
		||||
 | 
			
		||||
    constructor(){
 | 
			
		||||
        this.timers = new Array();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected static instance: TimerManager;
 | 
			
		||||
 | 
			
		||||
    static getInstance(): TimerManager {
 | 
			
		||||
        if(!this.instance){
 | 
			
		||||
            this.instance = new TimerManager();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return this.instance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    addTimer(timer: Timer){
 | 
			
		||||
        this.timers.push(timer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    clearTimers(){
 | 
			
		||||
        this.timers = new Array();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    update(deltaT: number): void {
 | 
			
		||||
        this.timers.forEach(timer => timer.update(deltaT));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -185,4 +185,13 @@ export default class Color {
 | 
			
		|||
			this.a
 | 
			
		||||
		]);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static fromStringHex(str: string): Color {
 | 
			
		||||
		let i = 0;
 | 
			
		||||
		if(str.charAt(0) == "#") i+= 1;
 | 
			
		||||
		let r = MathUtils.fromHex(str.substring(i, i+2));
 | 
			
		||||
		let g = MathUtils.fromHex(str.substring(i+2, i+4));
 | 
			
		||||
		let b = MathUtils.fromHex(str.substring(i+4, i+6));
 | 
			
		||||
		return new Color(r, g, b);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -49,6 +49,25 @@ export default class MathUtils {
 | 
			
		|||
        return MathUtils.clamp(x, 0, 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Clamps the lower end of the value of x to the range to min
 | 
			
		||||
     * @param x The value to be clamped
 | 
			
		||||
     * @param min The minimum allowed value of x
 | 
			
		||||
     * @returns x, if it is greater than min, otherwise min
 | 
			
		||||
     */
 | 
			
		||||
    static clampLow(x: number, min: number): number {
 | 
			
		||||
        return x < min ? min : x;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Clamps the lower end of the value of x to zero
 | 
			
		||||
     * @param x The value to be clamped
 | 
			
		||||
     * @returns x, if it is greater than 0, otherwise 0
 | 
			
		||||
     */
 | 
			
		||||
    static clampLow0(x: number): number {
 | 
			
		||||
        return MathUtils.clampLow(x, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static clampMagnitude(v: Vec2, m: number): Vec2 {
 | 
			
		||||
        if(v.magSq() > m*m){
 | 
			
		||||
            return v.scaleTo(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -104,6 +123,15 @@ export default class MathUtils {
 | 
			
		|||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns a number from a hex string
 | 
			
		||||
     * @param str the string containing the hex number
 | 
			
		||||
     * @returns the number in decimal represented by the hex string
 | 
			
		||||
     */
 | 
			
		||||
    static fromHex(str: string): number {
 | 
			
		||||
        return parseInt(str, 16);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the number as a hexadecimal
 | 
			
		||||
     * @param num The number to convert to hex
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user