finished implementing physics layers and added support for tilemap editing with code
This commit is contained in:
		
							parent
							
								
									9dc8cd29d1
								
							
						
					
					
						commit
						6149b983a5
					
				| 
						 | 
					@ -1,4 +1,3 @@
 | 
				
			||||||
import GameEvent from "../../Events/GameEvent";
 | 
					 | 
				
			||||||
import Map from "../Map";
 | 
					import Map from "../Map";
 | 
				
			||||||
import AABB from "../Shapes/AABB";
 | 
					import AABB from "../Shapes/AABB";
 | 
				
			||||||
import Shape from "../Shapes/Shape";
 | 
					import Shape from "../Shapes/Shape";
 | 
				
			||||||
| 
						 | 
					@ -77,6 +76,12 @@ export interface Physical {
 | 
				
			||||||
    /** The rectangle swept by the movement of this object, if dynamic */
 | 
					    /** The rectangle swept by the movement of this object, if dynamic */
 | 
				
			||||||
    sweptRect: AABB;
 | 
					    sweptRect: AABB;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** A boolean representing whether or not the node just collided with the tilemap */
 | 
				
			||||||
 | 
					    collidedWithTilemap: boolean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** The physics layer this node belongs to */
 | 
				
			||||||
 | 
					    physicsLayer: number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    isPlayer: boolean;
 | 
					    isPlayer: boolean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /*---------- FUNCTIONS ----------*/
 | 
					    /*---------- FUNCTIONS ----------*/
 | 
				
			||||||
| 
						 | 
					@ -107,6 +112,12 @@ export interface Physical {
 | 
				
			||||||
     * @param eventType The name of the event to send when this trigger is activated
 | 
					     * @param eventType The name of the event to send when this trigger is activated
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    addTrigger: (group: string, eventType: string) => void;
 | 
					    addTrigger: (group: string, eventType: string) => void;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Sets the physics layer of this node
 | 
				
			||||||
 | 
					     * @param layer The name of the layer
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    setPhysicsLayer: (layer: String) => void;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,4 +66,12 @@ export default class Map<T> implements Collection {
 | 
				
			||||||
	clear(): void {
 | 
						clear(): void {
 | 
				
			||||||
		this.forEach(key => delete this.map[key]);
 | 
							this.forEach(key => delete this.map[key]);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						toString(): string {
 | 
				
			||||||
 | 
							let str = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.forEach((key) => str += key + " -> " + this.get(key).toString() + "\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return str;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -234,6 +234,10 @@ export default class AABB extends Shape {
 | 
				
			||||||
    clone(): AABB {
 | 
					    clone(): AABB {
 | 
				
			||||||
        return new AABB(this.center.clone(), this.halfSize.clone());
 | 
					        return new AABB(this.center.clone(), this.halfSize.clone());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    toString(): string {
 | 
				
			||||||
 | 
					        return "(center: " + this.center.toString() + ", half-size: " + this.halfSize.toString() + ")"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class Hit {
 | 
					export class Hit {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -74,6 +74,10 @@ export default class Tileset {
 | 
				
			||||||
        return this.numCols;
 | 
					        return this.numCols;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getTileCount(): number {
 | 
				
			||||||
 | 
					        return this.endIndex - this.startIndex + 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    hasTile(tileIndex: number): boolean {
 | 
					    hasTile(tileIndex: number): boolean {
 | 
				
			||||||
        return tileIndex >= this.startIndex && tileIndex <= this.endIndex;
 | 
					        return tileIndex >= this.startIndex && tileIndex <= this.endIndex;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -87,7 +91,7 @@ export default class Tileset {
 | 
				
			||||||
     * @param origin The viewport origin in the current layer
 | 
					     * @param origin The viewport origin in the current layer
 | 
				
			||||||
     * @param scale The scale of the tilemap
 | 
					     * @param scale The scale of the tilemap
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    renderTile(ctx: CanvasRenderingContext2D, tileIndex: number, dataIndex: number, worldSize: Vec2, origin: Vec2, scale: Vec2, zoom: number): void {
 | 
					    renderTile(ctx: CanvasRenderingContext2D, tileIndex: number, dataIndex: number, maxCols: number, origin: Vec2, scale: Vec2, zoom: number): void {
 | 
				
			||||||
        let image = ResourceManager.getInstance().getImage(this.imageKey);
 | 
					        let image = ResourceManager.getInstance().getImage(this.imageKey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Get the true index
 | 
					        // Get the true index
 | 
				
			||||||
| 
						 | 
					@ -102,8 +106,8 @@ export default class Tileset {
 | 
				
			||||||
        let top = row * height;
 | 
					        let top = row * height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Calculate the position in the world to render the tile
 | 
					        // Calculate the position in the world to render the tile
 | 
				
			||||||
        let x = Math.floor((dataIndex % worldSize.x) * width * scale.x);
 | 
					        let x = Math.floor((dataIndex % maxCols) * width * scale.x);
 | 
				
			||||||
        let y = Math.floor(Math.floor(dataIndex / worldSize.x) * height * scale.y);
 | 
					        let y = Math.floor(Math.floor(dataIndex / maxCols) * height * scale.y);
 | 
				
			||||||
        ctx.drawImage(image, left, top, width, height, Math.floor((x - origin.x)*zoom), Math.floor((y - origin.y)*zoom), Math.ceil(width * scale.x * zoom), Math.ceil(height * scale.y * zoom));
 | 
					        ctx.drawImage(image, left, top, width, height, Math.floor((x - origin.x)*zoom), Math.floor((y - origin.y)*zoom), Math.ceil(width * scale.x * zoom), Math.ceil(height * scale.y * zoom));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -286,29 +286,12 @@ export default class GameLoop {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GameOptions {
 | 
					class GameOptions {
 | 
				
			||||||
    viewportSize: {x: number, y: number}
 | 
					    viewportSize: {x: number, y: number}
 | 
				
			||||||
    physics: {
 | 
					 | 
				
			||||||
        numPhysicsLayers: number,
 | 
					 | 
				
			||||||
        physicsLayerNames: Array<string>,
 | 
					 | 
				
			||||||
        physicsLayerCollisions: Array<Array<number>>;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static parse(options: Record<string, any>): GameOptions {
 | 
					    static parse(options: Record<string, any>): GameOptions {
 | 
				
			||||||
        let gOpt = new GameOptions();
 | 
					        let gOpt = new GameOptions();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gOpt.viewportSize = options.viewportSize ? options.viewportSize : {x: 800, y: 600};
 | 
					        gOpt.viewportSize = options.viewportSize ? options.viewportSize : {x: 800, y: 600};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gOpt.physics = {
 | 
					 | 
				
			||||||
            numPhysicsLayers: 10,
 | 
					 | 
				
			||||||
            physicsLayerNames: null,
 | 
					 | 
				
			||||||
            physicsLayerCollisions: ArrayUtils.ones2d(10, 10)
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(options.physics){
 | 
					 | 
				
			||||||
            if(options.physics.numPhysicsLayers)        gOpt.physics.numPhysicsLayers = options.physics.numPhysicsLayers;
 | 
					 | 
				
			||||||
            if(options.physics.physicsLayerNames)       gOpt.physics.physicsLayerNames = options.physics.physicsLayerNames;
 | 
					 | 
				
			||||||
            if(options.physics.physicsLayerCollisions)  gOpt.physics.physicsLayerCollisions = options.physics.physicsLayerCollisions;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return gOpt;
 | 
					        return gOpt;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -35,6 +35,8 @@ export default abstract class GameNode implements Positioned, Unique, Updateable
 | 
				
			||||||
	triggers: Map<string>;
 | 
						triggers: Map<string>;
 | 
				
			||||||
	_velocity: Vec2;
 | 
						_velocity: Vec2;
 | 
				
			||||||
	sweptRect: AABB;
 | 
						sweptRect: AABB;
 | 
				
			||||||
 | 
						collidedWithTilemap: boolean;
 | 
				
			||||||
 | 
						physicsLayer: number;
 | 
				
			||||||
	isPlayer: boolean;
 | 
						isPlayer: boolean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*---------- ACTOR ----------*/
 | 
						/*---------- ACTOR ----------*/
 | 
				
			||||||
| 
						 | 
					@ -124,6 +126,8 @@ export default abstract class GameNode implements Positioned, Unique, Updateable
 | 
				
			||||||
		this.triggers = new Map();
 | 
							this.triggers = new Map();
 | 
				
			||||||
		this._velocity = Vec2.ZERO;
 | 
							this._velocity = Vec2.ZERO;
 | 
				
			||||||
		this.sweptRect = new AABB();
 | 
							this.sweptRect = new AABB();
 | 
				
			||||||
 | 
							this.collidedWithTilemap = false;
 | 
				
			||||||
 | 
							this.physicsLayer = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(collisionShape){
 | 
							if(collisionShape){
 | 
				
			||||||
			this.collisionShape = collisionShape;
 | 
								this.collisionShape = collisionShape;
 | 
				
			||||||
| 
						 | 
					@ -147,6 +151,10 @@ export default abstract class GameNode implements Positioned, Unique, Updateable
 | 
				
			||||||
		this.triggers.add(group, eventType);
 | 
							this.triggers.add(group, eventType);
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						setPhysicsLayer = (layer: string): void => {
 | 
				
			||||||
 | 
							this.scene.getPhysicsManager().setLayer(this, layer);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*---------- ACTOR ----------*/
 | 
						/*---------- ACTOR ----------*/
 | 
				
			||||||
	get ai(): AI {
 | 
						get ai(): AI {
 | 
				
			||||||
		return this._ai;
 | 
							return this._ai;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,62 +1,83 @@
 | 
				
			||||||
import Vec2 from "../DataTypes/Vec2";
 | 
					import Vec2 from "../DataTypes/Vec2";
 | 
				
			||||||
import GameNode from "./GameNode";
 | 
					 | 
				
			||||||
import Tileset from "../DataTypes/Tilesets/Tileset";
 | 
					import Tileset from "../DataTypes/Tilesets/Tileset";
 | 
				
			||||||
import { TiledTilemapData, TiledLayerData } from "../DataTypes/Tilesets/TiledData"
 | 
					import { TiledTilemapData, TiledLayerData } from "../DataTypes/Tilesets/TiledData"
 | 
				
			||||||
 | 
					import CanvasNode from "./CanvasNode";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * The representation of a tilemap - this can consist of a combination of tilesets in one layer
 | 
					 * The representation of a tilemap - this can consist of a combination of tilesets in one layer
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default abstract class Tilemap extends GameNode {
 | 
					export default abstract class Tilemap extends CanvasNode {
 | 
				
			||||||
    // A tileset represents the tiles within one specific image loaded from a file
 | 
					 | 
				
			||||||
    protected tilesets: Array<Tileset>;
 | 
					    protected tilesets: Array<Tileset>;
 | 
				
			||||||
    protected size: Vec2;
 | 
					 | 
				
			||||||
    protected tileSize: Vec2;
 | 
					    protected tileSize: Vec2;
 | 
				
			||||||
    protected scale: Vec2;
 | 
					    protected data: Array<number>;
 | 
				
			||||||
    public data: Array<number>;
 | 
					    protected collisionMap: Array<boolean>;
 | 
				
			||||||
	public visible: boolean;
 | 
					    name: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO: Make this no longer be specific to Tiled
 | 
					    // TODO: Make this no longer be specific to Tiled
 | 
				
			||||||
    constructor(tilemapData: TiledTilemapData, layer: TiledLayerData, tilesets: Array<Tileset>, scale: Vec2) {
 | 
					    constructor(tilemapData: TiledTilemapData, layer: TiledLayerData, tilesets: Array<Tileset>, scale: Vec2) {
 | 
				
			||||||
        super();
 | 
					        super();
 | 
				
			||||||
        this.tilesets = tilesets;
 | 
					        this.tilesets = tilesets;
 | 
				
			||||||
        this.size = new Vec2(0, 0);
 | 
					 | 
				
			||||||
        this.tileSize = new Vec2(0, 0);
 | 
					        this.tileSize = new Vec2(0, 0);
 | 
				
			||||||
 | 
					        this.name = layer.name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let tilecount = 0;
 | 
				
			||||||
 | 
					        for(let tileset of tilesets){
 | 
				
			||||||
 | 
					            tilecount += tileset.getTileCount();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.collisionMap = new Array(tilecount);
 | 
				
			||||||
 | 
					        for(let i = 0; i < this.collisionMap.length; i++){
 | 
				
			||||||
 | 
					            this.collisionMap[i] = false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Defer parsing of the data to child classes - this allows for isometric vs. orthographic tilemaps and handling of Tiled data or other data
 | 
					        // Defer parsing of the data to child classes - this allows for isometric vs. orthographic tilemaps and handling of Tiled data or other data
 | 
				
			||||||
        this.parseTilemapData(tilemapData, layer);
 | 
					        this.parseTilemapData(tilemapData, layer);
 | 
				
			||||||
        this.scale = scale.clone();
 | 
					        this.scale.set(scale.x, scale.y);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Returns an array of the tilesets associated with this tilemap
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    getTilesets(): Tileset[] {
 | 
					    getTilesets(): Tileset[] {
 | 
				
			||||||
        return this.tilesets;
 | 
					        return this.tilesets;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getsize(): Vec2 {
 | 
					    /**
 | 
				
			||||||
        return this.size;
 | 
					     * Returns the size of tiles in this tilemap as they appear in the game world after scaling
 | 
				
			||||||
    }
 | 
					     */
 | 
				
			||||||
 | 
					 | 
				
			||||||
    getTileSize(): Vec2 {
 | 
					    getTileSize(): Vec2 {
 | 
				
			||||||
        return this.tileSize.clone().scale(this.scale.x, this.scale.y);
 | 
					        return this.tileSize.scaled(this.scale.x, this.scale.y);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getScale(): Vec2 {
 | 
					    /** Adds this tilemap to the physics system */
 | 
				
			||||||
        return this.scale;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    setScale(scale: Vec2): void {
 | 
					 | 
				
			||||||
        this.scale = scale;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    isVisible(): boolean {
 | 
					 | 
				
			||||||
        return this.visible;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /** Adds this tilemaps to the physics system */
 | 
					 | 
				
			||||||
    addPhysics = (): void => {
 | 
					    addPhysics = (): void => {
 | 
				
			||||||
        this.scene.getPhysicsManager().registerTilemap(this);
 | 
					        this.scene.getPhysicsManager().registerTilemap(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    abstract getTileAt(worldCoords: Vec2): number;
 | 
					    /**
 | 
				
			||||||
 | 
					     * Returns the value of the tile at the specified position
 | 
				
			||||||
 | 
					     * @param worldCoords The position in world coordinates
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    abstract getTileAtWorldPosition(worldCoords: Vec2): number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Returns the world position of the top left corner of the tile at the specified index
 | 
				
			||||||
 | 
					     * @param index 
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    abstract getTileWorldPosition(index: number): Vec2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Returns the value of the tile at the specified index
 | 
				
			||||||
 | 
					     * @param index
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    abstract getTile(index: number): number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Sets the value of the tile at the specified index
 | 
				
			||||||
 | 
					     * @param index
 | 
				
			||||||
 | 
					     * @param type
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    abstract setTile(index: number, type: number): void;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Sets up the tileset using the data loaded from file
 | 
					     * Sets up the tileset using the data loaded from file
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,38 +8,84 @@ import Tileset from "../../DataTypes/Tilesets/Tileset";
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default class OrthogonalTilemap extends Tilemap {
 | 
					export default class OrthogonalTilemap extends Tilemap {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected numCols: number;
 | 
				
			||||||
 | 
					    protected numRows: number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Parses the tilemap data loaded from the json file. DOES NOT process images automatically - the ResourceManager class does this while loading tilemaps
 | 
					     * Parses the tilemap data loaded from the json file. DOES NOT process images automatically - the ResourceManager class does this while loading tilemaps
 | 
				
			||||||
     * @param tilemapData 
 | 
					     * @param tilemapData 
 | 
				
			||||||
     * @param layer 
 | 
					     * @param layer 
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected parseTilemapData(tilemapData: TiledTilemapData, layer: TiledLayerData): void {
 | 
					    protected parseTilemapData(tilemapData: TiledTilemapData, layer: TiledLayerData): void {
 | 
				
			||||||
        this.size.set(tilemapData.width, tilemapData.height);
 | 
					        // The size of the tilemap in local space
 | 
				
			||||||
 | 
					        this.numCols = tilemapData.width;
 | 
				
			||||||
 | 
					        this.numRows = tilemapData.height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // The size of tiles
 | 
				
			||||||
        this.tileSize.set(tilemapData.tilewidth, tilemapData.tileheight);
 | 
					        this.tileSize.set(tilemapData.tilewidth, tilemapData.tileheight);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // The size of the tilemap on the canvas
 | 
				
			||||||
 | 
					        this.size.set(this.numCols * this.tileSize.x, this.numRows * this.tileSize.y);
 | 
				
			||||||
 | 
					        this.position.copy(this.size);
 | 
				
			||||||
        this.data = layer.data;
 | 
					        this.data = layer.data;
 | 
				
			||||||
        this.visible = layer.visible;
 | 
					        this.visible = layer.visible;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Whether the tilemap is collidable or not
 | 
				
			||||||
        this.isCollidable = false;
 | 
					        this.isCollidable = false;
 | 
				
			||||||
        if(layer.properties){
 | 
					        if(layer.properties){
 | 
				
			||||||
            for(let item of layer.properties){
 | 
					            for(let item of layer.properties){
 | 
				
			||||||
                if(item.name === "Collidable"){
 | 
					                if(item.name === "Collidable"){
 | 
				
			||||||
                    this.isCollidable = item.value;
 | 
					                    this.isCollidable = item.value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // Set all tiles besides "empty: 0" to be collidable
 | 
				
			||||||
 | 
					                    for(let i = 1; i < this.collisionMap.length; i++){
 | 
				
			||||||
 | 
					                        this.collisionMap[i] = true;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getTileAtWorldPosition(worldCoords: Vec2): number {
 | 
				
			||||||
 | 
					        let localCoords = this.getColRowAt(worldCoords);
 | 
				
			||||||
 | 
					        return this.getTileAtRowCol(localCoords);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Get the value of the tile at the coordinates in the vector worldCoords
 | 
					     * Get the tile at the specified row and column
 | 
				
			||||||
     * @param worldCoords 
 | 
					     * @param rowCol 
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    getTileAt(worldCoords: Vec2): number {
 | 
					    getTileAtRowCol(rowCol: Vec2): number {
 | 
				
			||||||
        let localCoords = this.getColRowAt(worldCoords);
 | 
					        if(rowCol.x < 0 || rowCol.x >= this.numCols || rowCol.y < 0 || rowCol.y >= this.numRows){
 | 
				
			||||||
        if(localCoords.x < 0 || localCoords.x >= this.size.x || localCoords.y < 0 || localCoords.y >= this.size.y){
 | 
					            return -1;
 | 
				
			||||||
            // There are no tiles in negative positions or out of bounds positions
 | 
					 | 
				
			||||||
            return 0;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return this.data[localCoords.y * this.size.x + localCoords.x]
 | 
					        return this.data[rowCol.y * this.numCols + rowCol.x];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getTileWorldPosition(index: number): Vec2 {
 | 
				
			||||||
 | 
					        // Get the local position
 | 
				
			||||||
 | 
					        let col = index % this.numCols;
 | 
				
			||||||
 | 
					        let row = Math.floor(index / this.numCols);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Get the world position
 | 
				
			||||||
 | 
					        let x = col * this.tileSize.x;
 | 
				
			||||||
 | 
					        let y = row * this.tileSize.y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Vec2(x, y);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getTile(index: number): number {
 | 
				
			||||||
 | 
					        return this.data[index];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setTile(index: number, type: number): void {
 | 
				
			||||||
 | 
					        this.data[index] = type;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setTileAtRowCol(rowCol: Vec2, type: number): void {
 | 
				
			||||||
 | 
					        let index = rowCol.y * this.numCols + rowCol.x;
 | 
				
			||||||
 | 
					        this.setTile(index, type);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					@ -48,33 +94,36 @@ export default class OrthogonalTilemap extends Tilemap {
 | 
				
			||||||
     * @param row 
 | 
					     * @param row 
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    isTileCollidable(indexOrCol: number, row?: number): boolean {
 | 
					    isTileCollidable(indexOrCol: number, row?: number): boolean {
 | 
				
			||||||
        let index = 0;
 | 
					        // The value of the tile
 | 
				
			||||||
 | 
					        let tile = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(row){
 | 
					        if(row){
 | 
				
			||||||
            if(indexOrCol < 0 || indexOrCol >= this.size.x || row < 0 || row >= this.size.y){
 | 
					            // We have a column and a row
 | 
				
			||||||
                // There are no tiles in negative positions or out of bounds positions
 | 
					            tile = this.getTileAtRowCol(new Vec2(indexOrCol, row));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(tile < 0){
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            index = row * this.size.x + indexOrCol;
 | 
					 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            if(indexOrCol < 0 || indexOrCol >= this.data.length){
 | 
					            if(indexOrCol < 0 || indexOrCol >= this.data.length){
 | 
				
			||||||
                // Tiles that don't exist aren't collidable
 | 
					                // Tiles that don't exist aren't collidable
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            index = indexOrCol;
 | 
					            // We have an index
 | 
				
			||||||
 | 
					            tile = this.getTile(indexOrCol);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // TODO - Currently, all tiles in a collidable layer are collidable
 | 
					        return this.collisionMap[tile];
 | 
				
			||||||
        return this.data[index] !== 0 && this.isCollidable;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Takes in world coordinates and returns the row and column of the tile at that position
 | 
					     * Takes in world coordinates and returns the row and column of the tile at that position
 | 
				
			||||||
     * @param worldCoords 
 | 
					     * @param worldCoords 
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    // TODO: Should this throw an error if someone tries to access an out of bounds value?
 | 
					 | 
				
			||||||
    getColRowAt(worldCoords: Vec2): Vec2 {
 | 
					    getColRowAt(worldCoords: Vec2): Vec2 {
 | 
				
			||||||
        let col = Math.floor(worldCoords.x / this.tileSize.x / this.scale.x);
 | 
					        let col = Math.floor(worldCoords.x / this.tileSize.x / this.scale.x);
 | 
				
			||||||
        let row = Math.floor(worldCoords.y / this.tileSize.y / this.scale.y);
 | 
					        let row = Math.floor(worldCoords.y / this.tileSize.y / this.scale.y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return new Vec2(col, row);
 | 
					        return new Vec2(col, row);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -94,7 +143,7 @@ export default class OrthogonalTilemap extends Tilemap {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                for(let tileset of this.tilesets){
 | 
					                for(let tileset of this.tilesets){
 | 
				
			||||||
                    if(tileset.hasTile(tileIndex)){
 | 
					                    if(tileset.hasTile(tileIndex)){
 | 
				
			||||||
                        tileset.renderTile(ctx, tileIndex, i, this.size, origin, this.scale, zoom);
 | 
					                        tileset.renderTile(ctx, tileIndex, i, this.numCols, origin, this.scale, zoom);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,9 +8,7 @@ import SweepAndPrune from "./BroadPhaseAlgorithms/SweepAndPrune";
 | 
				
			||||||
import Shape from "../DataTypes/Shapes/Shape";
 | 
					import Shape from "../DataTypes/Shapes/Shape";
 | 
				
			||||||
import MathUtils from "../Utils/MathUtils";
 | 
					import MathUtils from "../Utils/MathUtils";
 | 
				
			||||||
import OrthogonalTilemap from "../Nodes/Tilemaps/OrthogonalTilemap";
 | 
					import OrthogonalTilemap from "../Nodes/Tilemaps/OrthogonalTilemap";
 | 
				
			||||||
import Debug from "../Debug/Debug";
 | 
					 | 
				
			||||||
import AABB from "../DataTypes/Shapes/AABB";
 | 
					import AABB from "../DataTypes/Shapes/AABB";
 | 
				
			||||||
import Map from "../DataTypes/Map";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class BasicPhysicsManager extends PhysicsManager {
 | 
					export default class BasicPhysicsManager extends PhysicsManager {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,8 +24,8 @@ export default class BasicPhysicsManager extends PhysicsManager {
 | 
				
			||||||
	/** The broad phase collision detection algorithm used by this physics system */
 | 
						/** The broad phase collision detection algorithm used by this physics system */
 | 
				
			||||||
	protected broadPhase: BroadPhase;
 | 
						protected broadPhase: BroadPhase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	protected layerMap: Map<number>;
 | 
						/** A 2D array that contains information about which layers interact with each other */
 | 
				
			||||||
	protected layerNames: Array<string>;
 | 
						protected layerMask: number[][];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	constructor(physicsOptions: Record<string, any>){
 | 
						constructor(physicsOptions: Record<string, any>){
 | 
				
			||||||
		super();
 | 
							super();
 | 
				
			||||||
| 
						 | 
					@ -35,8 +33,6 @@ export default class BasicPhysicsManager extends PhysicsManager {
 | 
				
			||||||
		this.dynamicNodes = new Array();
 | 
							this.dynamicNodes = new Array();
 | 
				
			||||||
		this.tilemaps = new Array();
 | 
							this.tilemaps = new Array();
 | 
				
			||||||
		this.broadPhase = new SweepAndPrune();
 | 
							this.broadPhase = new SweepAndPrune();
 | 
				
			||||||
		this.layerMap = new Map();
 | 
					 | 
				
			||||||
		this.layerNames = new Array();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let i = 0;
 | 
							let i = 0;
 | 
				
			||||||
		if(physicsOptions.physicsLayerNames !== null){
 | 
							if(physicsOptions.physicsLayerNames !== null){
 | 
				
			||||||
| 
						 | 
					@ -56,7 +52,7 @@ export default class BasicPhysicsManager extends PhysicsManager {
 | 
				
			||||||
			this.layerMap.add("" + i, i);
 | 
								this.layerMap.add("" + i, i);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		console.log(this.layerNames);
 | 
							this.layerMask = physicsOptions.physicsLayerCollisions;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
| 
						 | 
					@ -101,14 +97,12 @@ export default class BasicPhysicsManager extends PhysicsManager {
 | 
				
			||||||
			// TODO - This is problematic if a collision happens, but it is later learned that another collision happens before it
 | 
								// TODO - This is problematic if a collision happens, but it is later learned that another collision happens before it
 | 
				
			||||||
			if(node1.triggers.has(group2)){
 | 
								if(node1.triggers.has(group2)){
 | 
				
			||||||
				// Node1 should send an event
 | 
									// Node1 should send an event
 | 
				
			||||||
				console.log("Trigger")
 | 
					 | 
				
			||||||
				let eventType = node1.triggers.get(group2);
 | 
									let eventType = node1.triggers.get(group2);
 | 
				
			||||||
				this.emitter.fireEvent(eventType, {node: node1, other: node2, collision: {firstContact: firstContact}});
 | 
									this.emitter.fireEvent(eventType, {node: node1, other: node2, collision: {firstContact: firstContact}});
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if(node2.triggers.has(group1)){
 | 
								if(node2.triggers.has(group1)){
 | 
				
			||||||
				// Node2 should send an event
 | 
									// Node2 should send an event
 | 
				
			||||||
				console.log("Trigger")
 | 
					 | 
				
			||||||
				let eventType = node2.triggers.get(group1);
 | 
									let eventType = node2.triggers.get(group1);
 | 
				
			||||||
				this.emitter.fireEvent(eventType, {node: node2, other: node1, collision: {firstContact: firstContact}});
 | 
									this.emitter.fireEvent(eventType, {node: node2, other: node1, collision: {firstContact: firstContact}});
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -191,13 +185,10 @@ export default class BasicPhysicsManager extends PhysicsManager {
 | 
				
			||||||
        let tilemapCollisions = new Array<TileCollisionData>();
 | 
					        let tilemapCollisions = new Array<TileCollisionData>();
 | 
				
			||||||
        let tileSize = tilemap.getTileSize();
 | 
					        let tileSize = tilemap.getTileSize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Debug.log("tilemapCollision", "");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Loop over all possible tiles (which isn't many in the scope of the velocity per frame)
 | 
					        // Loop over all possible tiles (which isn't many in the scope of the velocity per frame)
 | 
				
			||||||
        for(let col = minIndex.x; col <= maxIndex.x; col++){
 | 
					        for(let col = minIndex.x; col <= maxIndex.x; col++){
 | 
				
			||||||
            for(let row = minIndex.y; row <= maxIndex.y; row++){
 | 
					            for(let row = minIndex.y; row <= maxIndex.y; row++){
 | 
				
			||||||
                if(tilemap.isTileCollidable(col, row)){
 | 
					                if(tilemap.isTileCollidable(col, row)){
 | 
				
			||||||
                    Debug.log("tilemapCollision", "Colliding with Tile");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // Get the position of this tile
 | 
					                    // Get the position of this tile
 | 
				
			||||||
                    let tilePos = new Vec2(col * tileSize.x + tileSize.x/2, row * tileSize.y + tileSize.y/2);
 | 
					                    let tilePos = new Vec2(col * tileSize.x + tileSize.x/2, row * tileSize.y + tileSize.y/2);
 | 
				
			||||||
| 
						 | 
					@ -223,16 +214,15 @@ export default class BasicPhysicsManager extends PhysicsManager {
 | 
				
			||||||
        // Now that we have all collisions, sort by collision area highest to lowest
 | 
					        // Now that we have all collisions, sort by collision area highest to lowest
 | 
				
			||||||
		tilemapCollisions = tilemapCollisions.sort((a, b) => a.overlapArea - b.overlapArea);
 | 
							tilemapCollisions = tilemapCollisions.sort((a, b) => a.overlapArea - b.overlapArea);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let areas = "";
 | 
					 | 
				
			||||||
        tilemapCollisions.forEach(col => areas += col.overlapArea + ", ")
 | 
					 | 
				
			||||||
        Debug.log("cols", areas)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Resolve the collisions in order of collision area (i.e. "closest" tiles are collided with first, so we can slide along a surface of tiles)
 | 
					        // Resolve the collisions in order of collision area (i.e. "closest" tiles are collided with first, so we can slide along a surface of tiles)
 | 
				
			||||||
        tilemapCollisions.forEach(collision => {
 | 
					        tilemapCollisions.forEach(collision => {
 | 
				
			||||||
            let [firstContact, _, collidingX, collidingY] = Shape.getTimeOfCollision(node.collisionShape, velocity, collision.collider, Vec2.ZERO);
 | 
					            let [firstContact, _, collidingX, collidingY] = Shape.getTimeOfCollision(node.collisionShape, velocity, collision.collider, Vec2.ZERO);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Handle collision
 | 
					            // Handle collision
 | 
				
			||||||
            if( (firstContact.x < 1 || collidingX) && (firstContact.y < 1 || collidingY)){
 | 
					            if( (firstContact.x < 1 || collidingX) && (firstContact.y < 1 || collidingY)){
 | 
				
			||||||
 | 
									// We are definitely colliding, so add to this node's tilemap collision list
 | 
				
			||||||
 | 
									node.collidedWithTilemap = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if(collidingX && collidingY){
 | 
					                if(collidingX && collidingY){
 | 
				
			||||||
                    // If we're already intersecting, freak out I guess? Probably should handle this in some way for if nodes get spawned inside of tiles
 | 
					                    // If we're already intersecting, freak out I guess? Probably should handle this in some way for if nodes get spawned inside of tiles
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
| 
						 | 
					@ -265,7 +255,6 @@ export default class BasicPhysicsManager extends PhysicsManager {
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
	update(deltaT: number): void {
 | 
						update(deltaT: number): void {
 | 
				
			||||||
		/*---------- INITIALIZATION PHASE ----------*/
 | 
							/*---------- INITIALIZATION PHASE ----------*/
 | 
				
			||||||
		for(let node of this.dynamicNodes){
 | 
							for(let node of this.dynamicNodes){
 | 
				
			||||||
| 
						 | 
					@ -273,6 +262,7 @@ export default class BasicPhysicsManager extends PhysicsManager {
 | 
				
			||||||
			node.onGround = false;
 | 
								node.onGround = false;
 | 
				
			||||||
			node.onCeiling = false;
 | 
								node.onCeiling = false;
 | 
				
			||||||
			node.onWall = false;
 | 
								node.onWall = false;
 | 
				
			||||||
 | 
								node.collidedWithTilemap = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Update the swept shapes of each node
 | 
								// Update the swept shapes of each node
 | 
				
			||||||
			if(node.moving){
 | 
								if(node.moving){
 | 
				
			||||||
| 
						 | 
					@ -303,17 +293,15 @@ export default class BasicPhysicsManager extends PhysicsManager {
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Make sure both nodes can collide with each other based on their physics layer
 | 
				
			||||||
 | 
								if(!(node1.physicsLayer === -1 || node2.physicsLayer === -1 || this.layerMask[node1.physicsLayer][node2.physicsLayer] === 1)){
 | 
				
			||||||
 | 
									// Nodes do not collide. Continue onto the next pair
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Get Collision (which may or may not happen)
 | 
								// Get Collision (which may or may not happen)
 | 
				
			||||||
			let [firstContact, lastContact, collidingX, collidingY] = Shape.getTimeOfCollision(node1.collisionShape, node1._velocity, node2.collisionShape, node2._velocity);
 | 
								let [firstContact, lastContact, collidingX, collidingY] = Shape.getTimeOfCollision(node1.collisionShape, node1._velocity, node2.collisionShape, node2._velocity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if(node1.isPlayer){
 | 
					 | 
				
			||||||
				if(firstContact.x !== Infinity || firstContact.y !== Infinity)
 | 
					 | 
				
			||||||
					Debug.log("playercol", "First Contact: " + firstContact.toFixed(4))
 | 
					 | 
				
			||||||
			} else if(node2.isPlayer) {
 | 
					 | 
				
			||||||
				if(firstContact.x !== Infinity || firstContact.y !== Infinity)
 | 
					 | 
				
			||||||
					Debug.log("playercol", "First Contact: " + firstContact.toFixed(4))
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			this.resolveCollision(node1, node2, firstContact, lastContact, collidingX, collidingY);
 | 
								this.resolveCollision(node1, node2, firstContact, lastContact, collidingX, collidingY);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -322,10 +310,13 @@ export default class BasicPhysicsManager extends PhysicsManager {
 | 
				
			||||||
			if(node.moving && node.isCollidable){
 | 
								if(node.moving && node.isCollidable){
 | 
				
			||||||
				// If a node is moving and can collide, check it against every tilemap
 | 
									// If a node is moving and can collide, check it against every tilemap
 | 
				
			||||||
				for(let tilemap of this.tilemaps){
 | 
									for(let tilemap of this.tilemaps){
 | 
				
			||||||
 | 
										// Check if there could even be a collision
 | 
				
			||||||
 | 
										if(node.sweptRect.overlaps(tilemap.boundary)){
 | 
				
			||||||
						this.collideWithTilemap(node, tilemap, node._velocity);
 | 
											this.collideWithTilemap(node, tilemap, node._velocity);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*---------- ENDING PHASE ----------*/
 | 
							/*---------- ENDING PHASE ----------*/
 | 
				
			||||||
		for(let node of this.dynamicNodes){
 | 
							for(let node of this.dynamicNodes){
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,4 @@
 | 
				
			||||||
import { Physical } from "../DataTypes/Interfaces/Descriptors";
 | 
					import { Physical } from "../DataTypes/Interfaces/Descriptors";
 | 
				
			||||||
import AABB from "../DataTypes/Shapes/AABB";
 | 
					 | 
				
			||||||
import Vec2 from "../DataTypes/Vec2";
 | 
					import Vec2 from "../DataTypes/Vec2";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class Collision {
 | 
					export class Collision {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,21 +4,52 @@ import { Debug_Renderable, Updateable } from "../DataTypes/Interfaces/Descriptor
 | 
				
			||||||
import Tilemap from "../Nodes/Tilemap";
 | 
					import Tilemap from "../Nodes/Tilemap";
 | 
				
			||||||
import Receiver from "../Events/Receiver";
 | 
					import Receiver from "../Events/Receiver";
 | 
				
			||||||
import Emitter from "../Events/Emitter";
 | 
					import Emitter from "../Events/Emitter";
 | 
				
			||||||
 | 
					import Map from "../DataTypes/Map";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default abstract class PhysicsManager implements Updateable, Debug_Renderable {
 | 
					export default abstract class PhysicsManager implements Updateable, Debug_Renderable {
 | 
				
			||||||
	protected receiver: Receiver;
 | 
						protected receiver: Receiver;
 | 
				
			||||||
	protected emitter: Emitter;
 | 
						protected emitter: Emitter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**	Layer names to numbers */
 | 
				
			||||||
 | 
						protected layerMap: Map<number>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Layer numbers to names */
 | 
				
			||||||
 | 
						protected layerNames: Array<string>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	constructor(){
 | 
						constructor(){
 | 
				
			||||||
		this.receiver = new Receiver();
 | 
							this.receiver = new Receiver();
 | 
				
			||||||
		this.emitter = new Emitter();
 | 
							this.emitter = new Emitter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// The creation and implementation of layers is deferred to the subclass
 | 
				
			||||||
 | 
							this.layerMap = new Map();
 | 
				
			||||||
 | 
							this.layerNames = new Array();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Registers a gamenode with this physics manager
 | 
				
			||||||
 | 
						 * @param object 
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
	abstract registerObject(object: GameNode): void;
 | 
						abstract registerObject(object: GameNode): void;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Registers a tilemap with this physics manager
 | 
				
			||||||
 | 
						 * @param tilemap 
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
	abstract registerTilemap(tilemap: Tilemap): void;
 | 
						abstract registerTilemap(tilemap: Tilemap): void;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Updates the physics
 | 
				
			||||||
 | 
						 * @param deltaT 
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
	abstract update(deltaT: number): void;
 | 
						abstract update(deltaT: number): void;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Renders any debug shapes or graphics
 | 
				
			||||||
 | 
						 * @param ctx 
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
	abstract debug_render(ctx: CanvasRenderingContext2D): void;
 | 
						abstract debug_render(ctx: CanvasRenderingContext2D): void;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						setLayer(node: GameNode, layer: string): void {
 | 
				
			||||||
 | 
							node.physicsLayer = this.layerMap.get(layer);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,7 @@ import ParallaxLayer from "./Layers/ParallaxLayer";
 | 
				
			||||||
import UILayer from "./Layers/UILayer";
 | 
					import UILayer from "./Layers/UILayer";
 | 
				
			||||||
import CanvasNode from "../Nodes/CanvasNode";
 | 
					import CanvasNode from "../Nodes/CanvasNode";
 | 
				
			||||||
import GameNode from "../Nodes/GameNode";
 | 
					import GameNode from "../Nodes/GameNode";
 | 
				
			||||||
 | 
					import ArrayUtils from "../Utils/ArrayUtils";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class Scene implements Updateable, Renderable {
 | 
					export default class Scene implements Updateable, Renderable {
 | 
				
			||||||
    /** The size of the game world. */
 | 
					    /** The size of the game world. */
 | 
				
			||||||
| 
						 | 
					@ -73,7 +74,12 @@ export default class Scene implements Updateable, Renderable {
 | 
				
			||||||
    /** An interface that allows the loading of different files for use in the scene */
 | 
					    /** An interface that allows the loading of different files for use in the scene */
 | 
				
			||||||
    public load: ResourceManager;
 | 
					    public load: ResourceManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(viewport: Viewport, sceneManager: SceneManager, game: GameLoop){
 | 
					    /** The configuration options for this scene */
 | 
				
			||||||
 | 
					    public sceneOptions: SceneOptions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor(viewport: Viewport, sceneManager: SceneManager, game: GameLoop, options: Record<string, any>){
 | 
				
			||||||
 | 
					        this.sceneOptions = SceneOptions.parse(options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.worldSize = new Vec2(500, 500);
 | 
					        this.worldSize = new Vec2(500, 500);
 | 
				
			||||||
        this.viewport = viewport;
 | 
					        this.viewport = viewport;
 | 
				
			||||||
        this.viewport.setBounds(0, 0, 2560, 1280);
 | 
					        this.viewport.setBounds(0, 0, 2560, 1280);
 | 
				
			||||||
| 
						 | 
					@ -90,7 +96,7 @@ export default class Scene implements Updateable, Renderable {
 | 
				
			||||||
        this.uiLayers = new Map();
 | 
					        this.uiLayers = new Map();
 | 
				
			||||||
        this.parallaxLayers = new Map();
 | 
					        this.parallaxLayers = new Map();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.physicsManager = new BasicPhysicsManager(this.game.gameOptions.physics);
 | 
					        this.physicsManager = new BasicPhysicsManager(this.sceneOptions.physics);
 | 
				
			||||||
        this.navManager = new NavigationManager();
 | 
					        this.navManager = new NavigationManager();
 | 
				
			||||||
        this.aiManager = new AIManager();
 | 
					        this.aiManager = new AIManager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -325,4 +331,40 @@ export default class Scene implements Updateable, Renderable {
 | 
				
			||||||
    generateId(): number {
 | 
					    generateId(): number {
 | 
				
			||||||
        return this.sceneManager.generateId();
 | 
					        return this.sceneManager.generateId();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getTilemap(name: string): Tilemap {
 | 
				
			||||||
 | 
					        for(let tilemap of this .tilemaps){
 | 
				
			||||||
 | 
					            if(tilemap.name === name){
 | 
				
			||||||
 | 
					                return tilemap;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SceneOptions {
 | 
				
			||||||
 | 
					    physics: {
 | 
				
			||||||
 | 
					        numPhysicsLayers: number,
 | 
				
			||||||
 | 
					        physicsLayerNames: Array<string>,
 | 
				
			||||||
 | 
					        physicsLayerCollisions: Array<Array<number>>;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static parse(options: Record<string, any>): SceneOptions{
 | 
				
			||||||
 | 
					        let sOpt = new SceneOptions();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        sOpt.physics = {
 | 
				
			||||||
 | 
					            numPhysicsLayers: 10,
 | 
				
			||||||
 | 
					            physicsLayerNames: null,
 | 
				
			||||||
 | 
					            physicsLayerCollisions: ArrayUtils.ones2d(10, 10)
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(options.physics){
 | 
				
			||||||
 | 
					            if(options.physics.numPhysicsLayers)        sOpt.physics.numPhysicsLayers = options.physics.numPhysicsLayers;
 | 
				
			||||||
 | 
					            if(options.physics.physicsLayerNames)       sOpt.physics.physicsLayerNames = options.physics.physicsLayerNames;
 | 
				
			||||||
 | 
					            if(options.physics.physicsLayerCollisions)  sOpt.physics.physicsLayerCollisions = options.physics.physicsLayerCollisions;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return sOpt;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -22,9 +22,8 @@ export default class SceneManager {
 | 
				
			||||||
	 * Add a scene as the main scene
 | 
						 * Add a scene as the main scene
 | 
				
			||||||
	 * @param constr The constructor of the scene to add
 | 
						 * @param constr The constructor of the scene to add
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public addScene<T extends Scene>(constr: new (...args: any) => T): void {
 | 
						public addScene<T extends Scene>(constr: new (...args: any) => T, options: Record<string, any>): void {
 | 
				
			||||||
		console.log("Adding Scene");
 | 
							let scene = new constr(this.viewport, this, this.game, options);
 | 
				
			||||||
		let scene = new constr(this.viewport, this, this.game);
 | 
					 | 
				
			||||||
		this.currentScene = scene;
 | 
							this.currentScene = scene;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Enqueue all scene asset loads
 | 
							// Enqueue all scene asset loads
 | 
				
			||||||
| 
						 | 
					@ -43,7 +42,7 @@ export default class SceneManager {
 | 
				
			||||||
	 * Change from the current scene to this new scene
 | 
						 * Change from the current scene to this new scene
 | 
				
			||||||
	 * @param constr The constructor of the scene to change to
 | 
						 * @param constr The constructor of the scene to change to
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public changeScene<T extends Scene>(constr: new (...args: any) => T): void {
 | 
						public changeScene<T extends Scene>(constr: new (...args: any) => T, options: Record<string, any>): void {
 | 
				
			||||||
		// unload current scene
 | 
							// unload current scene
 | 
				
			||||||
		this.currentScene.unloadScene();
 | 
							this.currentScene.unloadScene();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,7 +50,7 @@ export default class SceneManager {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.viewport.setCenter(0, 0);
 | 
							this.viewport.setCenter(0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.addScene(constr);
 | 
							this.addScene(constr, options);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public generateId(): number {
 | 
						public generateId(): number {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,7 @@ import ParallaxLayer from "../../Scene/Layers/ParallaxLayer";
 | 
				
			||||||
import Scene from "../../Scene/Scene";
 | 
					import Scene from "../../Scene/Scene";
 | 
				
			||||||
import PlayerController from "../Player/PlayerController";
 | 
					import PlayerController from "../Player/PlayerController";
 | 
				
			||||||
import GoombaController from "../Enemies/GoombaController";
 | 
					import GoombaController from "../Enemies/GoombaController";
 | 
				
			||||||
 | 
					import OrthogonalTilemap from "../../Nodes/Tilemaps/OrthogonalTilemap";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export enum MarioEvents {
 | 
					export enum MarioEvents {
 | 
				
			||||||
    PLAYER_HIT_COIN = "PlayerHitCoin",
 | 
					    PLAYER_HIT_COIN = "PlayerHitCoin",
 | 
				
			||||||
| 
						 | 
					@ -27,7 +28,11 @@ export default class Level1 extends Scene {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    startScene(): void {
 | 
					    startScene(): void {
 | 
				
			||||||
        this.add.tilemap("level1", new Vec2(2, 2));
 | 
					        let tilemap = this.add.tilemap("level1", new Vec2(2, 2))[0].getItems()[0];
 | 
				
			||||||
 | 
					        console.log(tilemap);
 | 
				
			||||||
 | 
					        console.log((tilemap as OrthogonalTilemap).getTileAtRowCol(new Vec2(8, 17)));
 | 
				
			||||||
 | 
					        (tilemap as OrthogonalTilemap).setTileAtRowCol(new Vec2(8, 17), 1);
 | 
				
			||||||
 | 
					        console.log((tilemap as OrthogonalTilemap).getTileAtRowCol(new Vec2(8, 17)));
 | 
				
			||||||
        this.viewport.setBounds(0, 0, 150*64, 20*64);
 | 
					        this.viewport.setBounds(0, 0, 150*64, 20*64);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Give parallax to the parallax layers
 | 
					        // Give parallax to the parallax layers
 | 
				
			||||||
| 
						 | 
					@ -37,33 +42,34 @@ export default class Level1 extends Scene {
 | 
				
			||||||
        // Add the player (a rect for now)
 | 
					        // Add the player (a rect for now)
 | 
				
			||||||
        this.player = this.add.graphic(GraphicType.RECT, "Main", {position: new Vec2(192, 1152), size: new Vec2(64, 64)});
 | 
					        this.player = this.add.graphic(GraphicType.RECT, "Main", {position: new Vec2(192, 1152), size: new Vec2(64, 64)});
 | 
				
			||||||
        this.player.addPhysics();
 | 
					        this.player.addPhysics();
 | 
				
			||||||
        this.player.addAI(PlayerController, {playerType: "platformer"});
 | 
					        this.player.addAI(PlayerController, {playerType: "platformer", tilemap: "Main"});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Add triggers on colliding with coins or coinBlocks
 | 
					        // Add triggers on colliding with coins or coinBlocks
 | 
				
			||||||
        this.player.addTrigger("coin", MarioEvents.PLAYER_HIT_COIN);
 | 
					        this.player.addTrigger("coin", MarioEvents.PLAYER_HIT_COIN);
 | 
				
			||||||
        this.player.addTrigger("coinBlock", MarioEvents.PLAYER_HIT_COIN_BLOCK);
 | 
					        this.player.addTrigger("coinBlock", MarioEvents.PLAYER_HIT_COIN_BLOCK);
 | 
				
			||||||
 | 
					        this.player.setPhysicsLayer("player");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.receiver.subscribe([MarioEvents.PLAYER_HIT_COIN, MarioEvents.PLAYER_HIT_COIN_BLOCK]);
 | 
					        this.receiver.subscribe([MarioEvents.PLAYER_HIT_COIN, MarioEvents.PLAYER_HIT_COIN_BLOCK]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.viewport.follow(this.player);
 | 
					        this.viewport.follow(this.player);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Add enemies
 | 
					        // Add enemies
 | 
				
			||||||
        // Goombas
 | 
					 | 
				
			||||||
        for(let pos of [{x: 21, y: 18}, {x: 30, y: 18}, {x: 37, y: 18}, {x: 41, y: 18}, {x: 105, y: 8}, {x: 107, y: 8}, {x: 125, y: 18}]){
 | 
					        for(let pos of [{x: 21, y: 18}, {x: 30, y: 18}, {x: 37, y: 18}, {x: 41, y: 18}, {x: 105, y: 8}, {x: 107, y: 8}, {x: 125, y: 18}]){
 | 
				
			||||||
            let goomba = this.add.sprite("goomba", "Main");
 | 
					            let goomba = this.add.sprite("goomba", "Main");
 | 
				
			||||||
            goomba.position.set(pos.x*64, pos.y*64);
 | 
					            goomba.position.set(pos.x*64, pos.y*64);
 | 
				
			||||||
            goomba.scale.set(2, 2);
 | 
					            goomba.scale.set(2, 2);
 | 
				
			||||||
            goomba.addPhysics();
 | 
					            goomba.addPhysics();
 | 
				
			||||||
            goomba.addAI(GoombaController, {jumpy: false});
 | 
					            goomba.addAI(GoombaController, {jumpy: false});
 | 
				
			||||||
 | 
					            goomba.setPhysicsLayer("enemy");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        for(let pos of [{x: 67, y: 18}, {x: 86, y: 21}, {x: 128, y: 18}]){
 | 
					        for(let pos of [{x: 67, y: 18}, {x: 86, y: 21}, {x: 128, y: 18}]){
 | 
				
			||||||
            let koopa = this.add.sprite("koopa", "Main");
 | 
					            let koopa = this.add.sprite("koopa", "Main");
 | 
				
			||||||
            koopa.position.set(pos.x*64, pos.y*64);
 | 
					            koopa.position.set(pos.x*64, pos.y*64);
 | 
				
			||||||
            koopa.scale.set(2, 2);
 | 
					            koopa.scale.set(2, 2);
 | 
				
			||||||
            koopa.addPhysics();
 | 
					            koopa.addPhysics();
 | 
				
			||||||
            koopa.addAI(GoombaController, {jumpy: true});
 | 
					            koopa.addAI(GoombaController, {jumpy: true});
 | 
				
			||||||
 | 
					            koopa.setPhysicsLayer("enemy");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Add UI
 | 
					        // Add UI
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ import StateMachineAI from "../../AI/StateMachineAI";
 | 
				
			||||||
import Vec2 from "../../DataTypes/Vec2";
 | 
					import Vec2 from "../../DataTypes/Vec2";
 | 
				
			||||||
import Debug from "../../Debug/Debug";
 | 
					import Debug from "../../Debug/Debug";
 | 
				
			||||||
import GameNode from "../../Nodes/GameNode";
 | 
					import GameNode from "../../Nodes/GameNode";
 | 
				
			||||||
 | 
					import OrthogonalTilemap from "../../Nodes/Tilemaps/OrthogonalTilemap";
 | 
				
			||||||
import IdleTopDown from "./PlayerStates/IdleTopDown";
 | 
					import IdleTopDown from "./PlayerStates/IdleTopDown";
 | 
				
			||||||
import MoveTopDown from "./PlayerStates/MoveTopDown";
 | 
					import MoveTopDown from "./PlayerStates/MoveTopDown";
 | 
				
			||||||
import Idle from "./PlayerStates/Platformer/Idle";
 | 
					import Idle from "./PlayerStates/Platformer/Idle";
 | 
				
			||||||
| 
						 | 
					@ -29,6 +30,7 @@ export default class PlayerController extends StateMachineAI {
 | 
				
			||||||
	speed: number = 400;
 | 
						speed: number = 400;
 | 
				
			||||||
	MIN_SPEED: number = 400;
 | 
						MIN_SPEED: number = 400;
 | 
				
			||||||
    MAX_SPEED: number = 1000;
 | 
					    MAX_SPEED: number = 1000;
 | 
				
			||||||
 | 
					    tilemap: OrthogonalTilemap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    initializeAI(owner: GameNode, options: Record<string, any>){
 | 
					    initializeAI(owner: GameNode, options: Record<string, any>){
 | 
				
			||||||
        this.owner = owner;
 | 
					        this.owner = owner;
 | 
				
			||||||
| 
						 | 
					@ -38,6 +40,8 @@ export default class PlayerController extends StateMachineAI {
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            this.initializePlatformer();
 | 
					            this.initializePlatformer();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.tilemap = this.owner.getScene().getTilemap(options.tilemap) as OrthogonalTilemap;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,23 @@ export default class Jump extends PlayerState {
 | 
				
			||||||
	update(deltaT: number): void {
 | 
						update(deltaT: number): void {
 | 
				
			||||||
		super.update(deltaT);
 | 
							super.update(deltaT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(this.owner.collidedWithTilemap && this.owner.onCeiling){
 | 
				
			||||||
 | 
								// We collided with a tilemap above us. First, get the tile right above us
 | 
				
			||||||
 | 
								let pos = this.owner.position.clone();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Go up plus some extra
 | 
				
			||||||
 | 
								pos.y -= (this.owner.collisionShape.halfSize.y + 10);
 | 
				
			||||||
 | 
								pos = this.parent.tilemap.getColRowAt(pos);
 | 
				
			||||||
 | 
								let tile = this.parent.tilemap.getTileAtRowCol(pos);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								console.log("Hit tile: " + tile);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// If coin block, change to empty coin block
 | 
				
			||||||
 | 
								if(tile === 4){
 | 
				
			||||||
 | 
									this.parent.tilemap.setTileAtRowCol(pos, 12);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(this.owner.onGround){
 | 
							if(this.owner.onGround){
 | 
				
			||||||
			this.finished(PlayerStates.PREVIOUS);
 | 
								this.finished(PlayerStates.PREVIOUS);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@ import StateMachine from "../../../../DataTypes/State/StateMachine";
 | 
				
			||||||
import Vec2 from "../../../../DataTypes/Vec2";
 | 
					import Vec2 from "../../../../DataTypes/Vec2";
 | 
				
			||||||
import InputReceiver from "../../../../Input/InputReceiver";
 | 
					import InputReceiver from "../../../../Input/InputReceiver";
 | 
				
			||||||
import GameNode from "../../../../Nodes/GameNode";
 | 
					import GameNode from "../../../../Nodes/GameNode";
 | 
				
			||||||
import PlayerController from "./PlayerController";
 | 
					import PlayerController from "../../PlayerController";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default abstract class PlayerState extends State {
 | 
					export default abstract class PlayerState extends State {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										20
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								src/main.ts
									
									
									
									
									
								
							| 
						 | 
					@ -6,15 +6,27 @@ function main(){
 | 
				
			||||||
    // Create the game object
 | 
					    // Create the game object
 | 
				
			||||||
    let options = {
 | 
					    let options = {
 | 
				
			||||||
        viewportSize: {x: 800, y: 600},
 | 
					        viewportSize: {x: 800, y: 600},
 | 
				
			||||||
        physics: {
 | 
					 | 
				
			||||||
            physicsLayerNames: ["ground", "player", "enemy", "coin"]
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let game = new GameLoop(options);
 | 
					    let game = new GameLoop(options);
 | 
				
			||||||
    game.start();
 | 
					    game.start();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let sceneOptions = {
 | 
				
			||||||
 | 
					        physics: {
 | 
				
			||||||
 | 
					            physicsLayerNames: ["ground", "player", "enemy", "coin"],
 | 
				
			||||||
 | 
					            numPhyiscsLayers: 4,
 | 
				
			||||||
 | 
					            physicsLayerCollisions:
 | 
				
			||||||
 | 
					            [
 | 
				
			||||||
 | 
					                [0, 1, 1, 1],
 | 
				
			||||||
 | 
					                [1, 0, 0, 1],
 | 
				
			||||||
 | 
					                [1, 0, 0, 1],
 | 
				
			||||||
 | 
					                [1, 1, 1, 0]
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let sm = game.getSceneManager();
 | 
					    let sm = game.getSceneManager();
 | 
				
			||||||
    sm.addScene(Level1);
 | 
					    sm.addScene(Level1, sceneOptions);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CanvasRenderingContext2D.prototype.roundedRect = function(x: number, y: number, w: number, h: number, r: number): void {
 | 
					CanvasRenderingContext2D.prototype.roundedRect = function(x: number, y: number, w: number, h: number, r: number): void {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user