added support for Tiled object layers
This commit is contained in:
		
							parent
							
								
									a67521ea26
								
							
						
					
					
						commit
						9cb4f55d9a
					
				| 
						 | 
					@ -35,6 +35,7 @@ export class TiledTilesetData {
 | 
				
			||||||
    spacing: number;
 | 
					    spacing: number;
 | 
				
			||||||
    name: string;
 | 
					    name: string;
 | 
				
			||||||
    image: string;
 | 
					    image: string;
 | 
				
			||||||
 | 
					    tiles: Array<TiledCollectionTile>
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -50,5 +51,27 @@ export class TiledLayerData {
 | 
				
			||||||
    opacity: number;
 | 
					    opacity: number;
 | 
				
			||||||
    visible: boolean;
 | 
					    visible: boolean;
 | 
				
			||||||
    properties: TiledLayerProperty[];
 | 
					    properties: TiledLayerProperty[];
 | 
				
			||||||
 | 
					    type: string;
 | 
				
			||||||
 | 
					    objects: Array<TiledObject>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class TiledObject {
 | 
				
			||||||
 | 
					    gid: number;
 | 
				
			||||||
 | 
					    height: number;
 | 
				
			||||||
 | 
					    width: number;
 | 
				
			||||||
 | 
					    id: number;
 | 
				
			||||||
 | 
					    name: string;;
 | 
				
			||||||
 | 
					    properties: Array<TiledLayerProperty>;
 | 
				
			||||||
 | 
					    rotation: number;
 | 
				
			||||||
 | 
					    type: string;
 | 
				
			||||||
 | 
					    visible: boolean;
 | 
				
			||||||
 | 
					    x: number;
 | 
				
			||||||
 | 
					    y: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class TiledCollectionTile {
 | 
				
			||||||
 | 
					    id: number;
 | 
				
			||||||
 | 
					    image: string;
 | 
				
			||||||
 | 
					    imageheight: number;
 | 
				
			||||||
 | 
					    imagewidth: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,4 @@
 | 
				
			||||||
 | 
					import ResourceManager from "../../ResourceManager/ResourceManager";
 | 
				
			||||||
import Vec2 from "../Vec2";
 | 
					import Vec2 from "../Vec2";
 | 
				
			||||||
import { TiledTilesetData } from "./TiledData";
 | 
					import { TiledTilesetData } from "./TiledData";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,8 +7,7 @@ import { TiledTilesetData } from "./TiledData";
 | 
				
			||||||
 * with a startIndex if required (as it is with Tiled using two images in one tilset).
 | 
					 * with a startIndex if required (as it is with Tiled using two images in one tilset).
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default class Tileset {
 | 
					export default class Tileset {
 | 
				
			||||||
    protected imageUrl: string;
 | 
					    protected imageKey: string;
 | 
				
			||||||
    protected image: HTMLImageElement = null;
 | 
					 | 
				
			||||||
    protected imageSize: Vec2;
 | 
					    protected imageSize: Vec2;
 | 
				
			||||||
    protected startIndex: number;
 | 
					    protected startIndex: number;
 | 
				
			||||||
    protected endIndex: number;
 | 
					    protected endIndex: number;
 | 
				
			||||||
| 
						 | 
					@ -31,20 +31,31 @@ export default class Tileset {
 | 
				
			||||||
        this.startIndex = tiledData.firstgid;
 | 
					        this.startIndex = tiledData.firstgid;
 | 
				
			||||||
        this.endIndex = this.startIndex + tiledData.tilecount - 1;
 | 
					        this.endIndex = this.startIndex + tiledData.tilecount - 1;
 | 
				
			||||||
        this.tileSize = new Vec2(tiledData.tilewidth, tiledData.tilewidth);
 | 
					        this.tileSize = new Vec2(tiledData.tilewidth, tiledData.tilewidth);
 | 
				
			||||||
        this.imageUrl = tiledData.image;
 | 
					        this.imageKey = tiledData.image;
 | 
				
			||||||
        this.imageSize = new Vec2(tiledData.imagewidth, tiledData.imageheight);
 | 
					        this.imageSize = new Vec2(tiledData.imagewidth, tiledData.imageheight);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getImageUrl(): string {
 | 
					    getImageKey(): string {
 | 
				
			||||||
        return this.imageUrl
 | 
					        return this.imageKey;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getImage(): HTMLImageElement {
 | 
					    /**
 | 
				
			||||||
        return this.image;
 | 
					     * Returns a Vec2 containing the left and top offset from the image origin for this tile.
 | 
				
			||||||
    }
 | 
					     * @param tileIndex The index of the tile from startIndex to endIndex of this tileset
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    getImageOffsetForTile(tileIndex: number): Vec2 {
 | 
				
			||||||
 | 
					        // Get the true index
 | 
				
			||||||
 | 
					        let index = tileIndex - this.startIndex;
 | 
				
			||||||
 | 
					        let row = Math.floor(index / this.numCols);
 | 
				
			||||||
 | 
					        let col = index % this.numCols;
 | 
				
			||||||
 | 
					        let width = this.tileSize.x;
 | 
				
			||||||
 | 
					        let height = this.tileSize.y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    setImage(image: HTMLImageElement){
 | 
					        // Calculate the position to start a crop in the tileset image
 | 
				
			||||||
        this.image = image;
 | 
					        let left = col * width;
 | 
				
			||||||
 | 
					        let top = row * height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Vec2(left, top);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getStartIndex(): number {
 | 
					    getStartIndex(): number {
 | 
				
			||||||
| 
						 | 
					@ -77,6 +88,8 @@ export default class Tileset {
 | 
				
			||||||
     * @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): void {
 | 
					    renderTile(ctx: CanvasRenderingContext2D, tileIndex: number, dataIndex: number, worldSize: Vec2, origin: Vec2, scale: Vec2): void {
 | 
				
			||||||
 | 
					        let image = ResourceManager.getInstance().getImage(this.imageKey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Get the true index
 | 
					        // Get the true index
 | 
				
			||||||
        let index = tileIndex - this.startIndex;
 | 
					        let index = tileIndex - this.startIndex;
 | 
				
			||||||
        let row = Math.floor(index / this.numCols);
 | 
					        let row = Math.floor(index / this.numCols);
 | 
				
			||||||
| 
						 | 
					@ -91,6 +104,6 @@ export default class Tileset {
 | 
				
			||||||
        // Calculate the position in the world to render the tile
 | 
					        // Calculate the position in the world to render the tile
 | 
				
			||||||
        let x = (dataIndex % worldSize.x) * width * scale.x;
 | 
					        let x = (dataIndex % worldSize.x) * width * scale.x;
 | 
				
			||||||
        let y = Math.floor(dataIndex / worldSize.x) * height * scale.y;
 | 
					        let y = Math.floor(dataIndex / worldSize.x) * height * scale.y;
 | 
				
			||||||
        ctx.drawImage(this.image, left, top, width, height, x - origin.x, y - origin.y, width * scale.x, height * scale.y);
 | 
					        ctx.drawImage(image, left, top, width, height, x - origin.x, y - origin.y, width * scale.x, height * scale.y);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -147,6 +147,14 @@ export default class Vec2 {
 | 
				
			||||||
		return this;
 | 
							return this;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Returns the squared distance between this vector and another vector
 | 
				
			||||||
 | 
						 * @param other 
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						distanceSqTo(other: Vec2): number {
 | 
				
			||||||
 | 
							return (this.x - other.x)*(this.x - other.x) + (this.y - other.y)*(this.y - other.y);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Returns a string representation of this vector rounded to 1 decimal point
 | 
						 * Returns a string representation of this vector rounded to 1 decimal point
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,16 +36,16 @@ export default class MainScene extends Scene {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    startScene(){
 | 
					    startScene(){
 | 
				
			||||||
        // Add the background tilemap
 | 
					        // Add the background tilemap
 | 
				
			||||||
        let backgroundTilemap = this.add.tilemap("background", OrthogonalTilemap)[0];
 | 
					        let backgroundTilemapLayer = this.add.tilemap("background")[0];
 | 
				
			||||||
        // ...and make it have parallax
 | 
					        // ...and make it have parallax
 | 
				
			||||||
        backgroundTilemap.getLayer().setParallax(0.5, 0.8);
 | 
					        backgroundTilemapLayer.setParallax(0.5, 0.8);
 | 
				
			||||||
        backgroundTilemap.getLayer().setAlpha(0.5);
 | 
					        backgroundTilemapLayer.setAlpha(0.5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Add the music and start playing it on a loop
 | 
					        // Add the music and start playing it on a loop
 | 
				
			||||||
        this.emitter.fireEvent(GameEventType.PLAY_SOUND, {key: "level_music", loop: true, holdReference: true});
 | 
					        this.emitter.fireEvent(GameEventType.PLAY_SOUND, {key: "level_music", loop: true, holdReference: true});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Add the tilemap
 | 
					        // Add the tilemap
 | 
				
			||||||
        this.add.tilemap("platformer", OrthogonalTilemap);
 | 
					        this.add.tilemap("platformer");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Create the main game layer
 | 
					        // Create the main game layer
 | 
				
			||||||
        let mainLayer = this.addLayer();
 | 
					        let mainLayer = this.addLayer();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,12 +6,29 @@ import Vec2 from "../DataTypes/Vec2";
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default abstract class CanvasNode extends GameNode{
 | 
					export default abstract class CanvasNode extends GameNode{
 | 
				
			||||||
	protected size: Vec2;
 | 
						protected size: Vec2;
 | 
				
			||||||
 | 
						protected scale: Vec2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	constructor(){
 | 
						constructor(){
 | 
				
			||||||
		super();
 | 
							super();
 | 
				
			||||||
		this.size = new Vec2(0, 0);
 | 
							this.size = new Vec2(0, 0);
 | 
				
			||||||
 | 
							this.scale = new Vec2(1, 1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
					     * Returns the scale of the sprite
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    getScale(): Vec2 {
 | 
				
			||||||
 | 
					        return this.scale;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Sets the scale of the sprite to the value provided
 | 
				
			||||||
 | 
					     * @param scale 
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    setScale(scale: Vec2): void {
 | 
				
			||||||
 | 
							this.scale = scale;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	getSize(): Vec2 {
 | 
						getSize(): Vec2 {
 | 
				
			||||||
		return this.size;
 | 
							return this.size;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,29 +7,22 @@ import Vec2 from "../../DataTypes/Vec2";
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default class Sprite extends CanvasNode {
 | 
					export default class Sprite extends CanvasNode {
 | 
				
			||||||
    private imageId: string;
 | 
					    private imageId: string;
 | 
				
			||||||
    private scale: Vec2;
 | 
					    private imageOffset: Vec2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(imageId: string){
 | 
					    constructor(imageId: string){
 | 
				
			||||||
        super();
 | 
					        super();
 | 
				
			||||||
        this.imageId = imageId;
 | 
					        this.imageId = imageId;
 | 
				
			||||||
        let image = ResourceManager.getInstance().getImage(this.imageId);
 | 
					        let image = ResourceManager.getInstance().getImage(this.imageId);
 | 
				
			||||||
        this.size = new Vec2(image.width, image.height);
 | 
					        this.size = new Vec2(image.width, image.height);
 | 
				
			||||||
        this.scale = new Vec2(1, 1);
 | 
					        this.imageOffset = Vec2.ZERO;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Returns the scale of the sprite
 | 
					     * Sets the offset of the sprite from (0, 0) in the image's coordinates
 | 
				
			||||||
 | 
					     * @param offset 
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    getScale(): Vec2 {
 | 
					    setImageOffset(offset: Vec2): void {
 | 
				
			||||||
        return this.scale;
 | 
					        this.imageOffset = offset;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Sets the scale of the sprite to the value provided
 | 
					 | 
				
			||||||
     * @param scale 
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    setScale(scale: Vec2): void {
 | 
					 | 
				
			||||||
        this.scale = scale;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    update(deltaT: number): void {}
 | 
					    update(deltaT: number): void {}
 | 
				
			||||||
| 
						 | 
					@ -38,7 +31,7 @@ export default class Sprite extends CanvasNode {
 | 
				
			||||||
        let image = ResourceManager.getInstance().getImage(this.imageId);
 | 
					        let image = ResourceManager.getInstance().getImage(this.imageId);
 | 
				
			||||||
        let origin = this.getViewportOriginWithParallax();
 | 
					        let origin = this.getViewportOriginWithParallax();
 | 
				
			||||||
        ctx.drawImage(image,
 | 
					        ctx.drawImage(image,
 | 
				
			||||||
            0, 0, this.size.x, this.size.y,
 | 
					            this.imageOffset.x, this.imageOffset.y, this.size.x, this.size.y,
 | 
				
			||||||
            this.position.x - origin.x, this.position.y - origin.y, this.size.x * this.scale.x, this.size.y * this.scale.y);
 | 
					            this.position.x - origin.x, this.position.y - origin.y, this.size.x * this.scale.x, this.size.y * this.scale.y);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -17,9 +17,9 @@ export default abstract class Tilemap extends GameNode {
 | 
				
			||||||
	public visible: boolean;
 | 
						public visible: boolean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO: Make this no longer be specific to Tiled
 | 
					    // TODO: Make this no longer be specific to Tiled
 | 
				
			||||||
    constructor(tilemapData: TiledTilemapData, layer: TiledLayerData) {
 | 
					    constructor(tilemapData: TiledTilemapData, layer: TiledLayerData, tilesets: Array<Tileset>) {
 | 
				
			||||||
        super();
 | 
					        super();
 | 
				
			||||||
        this.tilesets = new Array<Tileset>();
 | 
					        this.tilesets = tilesets;
 | 
				
			||||||
        this.worldSize = new Vec2(0, 0);
 | 
					        this.worldSize = new Vec2(0, 0);
 | 
				
			||||||
        this.tileSize = new Vec2(0, 0);
 | 
					        this.tileSize = new Vec2(0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,8 +26,6 @@ export default class OrthogonalTilemap extends Tilemap {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        tilemapData.tilesets.forEach(tilesetData => this.tilesets.push(new Tileset(tilesetData)));
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -142,15 +142,14 @@ export default class PhysicsManager {
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private handleCollision(movingNode: PhysicsNode, staticNode: PhysicsNode, velocity: Vec2, id: String){
 | 
					    private collideWithStaticNode(movingNode: PhysicsNode, staticNode: PhysicsNode, velocity: Vec2){
 | 
				
			||||||
        let sizeA = movingNode.getCollider().getSize();
 | 
					        let sizeA = movingNode.getCollider().getSize();
 | 
				
			||||||
        let posA = movingNode.getPosition();
 | 
					        let posA = movingNode.getPosition();
 | 
				
			||||||
        let velA = velocity;
 | 
					        let velA = velocity;
 | 
				
			||||||
        let sizeB = staticNode.getCollider().getSize();
 | 
					        let sizeB = staticNode.getCollider().getSize();
 | 
				
			||||||
        let posB = staticNode.getPosition();
 | 
					        let posB = staticNode.getPosition();
 | 
				
			||||||
        let velB = new Vec2(0, 0);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let [firstContact, _, collidingX, collidingY] = this.getTimeOfAABBCollision(posA, sizeA, velA, posB, sizeB, velB);
 | 
					        let [firstContact, _, collidingX, collidingY] = this.getTimeOfAABBCollision(posA, sizeA, velA, posB, sizeB, new Vec2(0, 0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if( (firstContact.x < 1 || collidingX) && (firstContact.y < 1 || collidingY)){
 | 
					        if( (firstContact.x < 1 || collidingX) && (firstContact.y < 1 || collidingY)){
 | 
				
			||||||
            if(collidingX && collidingY){
 | 
					            if(collidingX && collidingY){
 | 
				
			||||||
| 
						 | 
					@ -160,9 +159,20 @@ export default class PhysicsManager {
 | 
				
			||||||
                // velocity.scale(contactTime);
 | 
					                // velocity.scale(contactTime);
 | 
				
			||||||
                let xScale = MathUtils.clamp(firstContact.x, 0, 1);
 | 
					                let xScale = MathUtils.clamp(firstContact.x, 0, 1);
 | 
				
			||||||
                let yScale = MathUtils.clamp(firstContact.y, 0, 1);
 | 
					                let yScale = MathUtils.clamp(firstContact.y, 0, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                 // Handle special case of stickiness on perfect corner to corner collisions
 | 
				
			||||||
 | 
					                 if(xScale === yScale){
 | 
				
			||||||
 | 
					                    xScale = 1;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // If we are scaling y, we're on the ground, so tell the node it's grounded
 | 
				
			||||||
 | 
					                // TODO - This is a bug, check to make sure our velocity is going downwards
 | 
				
			||||||
 | 
					                // Maybe feed in a downward direction to check to be sure
 | 
				
			||||||
                if(yScale !== 1){
 | 
					                if(yScale !== 1){
 | 
				
			||||||
                    movingNode.setGrounded(true);
 | 
					                    movingNode.setGrounded(true);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // Scale the velocity of the node
 | 
				
			||||||
                velocity.scale(xScale, yScale);
 | 
					                velocity.scale(xScale, yScale);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -284,7 +294,9 @@ export default class PhysicsManager {
 | 
				
			||||||
            // TODO handle collisions between dynamic nodes
 | 
					            // TODO handle collisions between dynamic nodes
 | 
				
			||||||
            // We probably want to sort them by their left edges
 | 
					            // We probably want to sort them by their left edges
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // TODO: handle collisions between dynamic nodes and static nodes
 | 
					            for(let staticNode of staticSet){
 | 
				
			||||||
 | 
					                this.collideWithStaticNode(movingNode, staticNode, velocity);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Handle Collisions with the tilemaps
 | 
					            // Handle Collisions with the tilemaps
 | 
				
			||||||
            for(let tilemap of this.tilemaps){
 | 
					            for(let tilemap of this.tilemaps){
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,6 +30,10 @@ export default abstract class PhysicsNode extends GameNode {
 | 
				
			||||||
        this.manager = manager;
 | 
					        this.manager = manager;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    addChild(child: GameNode): void {
 | 
				
			||||||
 | 
					        this.children.push(child);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    isCollidable(): boolean {
 | 
					    isCollidable(): boolean {
 | 
				
			||||||
        return this.collider !== null;
 | 
					        return this.collider !== null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,7 @@ export default class StaticBody extends PhysicsNode {
 | 
				
			||||||
        this.collider.setPosition(position.x, position.y);
 | 
					        this.collider.setPosition(position.x, position.y);
 | 
				
			||||||
        this.collider.setSize(new Vec2(size.x, size.y));
 | 
					        this.collider.setSize(new Vec2(size.x, size.y));
 | 
				
			||||||
        this.id = StaticBody.numCreated.toString();
 | 
					        this.id = StaticBody.numCreated.toString();
 | 
				
			||||||
 | 
					        this.moving = false;
 | 
				
			||||||
        StaticBody.numCreated += 1;
 | 
					        StaticBody.numCreated += 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -233,9 +233,18 @@ export default class ResourceManager {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Grab the tileset images we need to load and add them to the imageloading queue
 | 
					            // Grab the tileset images we need to load and add them to the imageloading queue
 | 
				
			||||||
            for(let tileset of tilemapObject.tilesets){
 | 
					            for(let tileset of tilemapObject.tilesets){
 | 
				
			||||||
                let key = tileset.image;
 | 
					                if(tileset.image){
 | 
				
			||||||
                let path = StringUtils.getPathFromFilePath(pathToTilemapJSON) + key;
 | 
					                    let key = tileset.image;
 | 
				
			||||||
                this.loadonly_imageLoadingQueue.enqueue({key: key, path: path});
 | 
					                    let path = StringUtils.getPathFromFilePath(pathToTilemapJSON) + key;
 | 
				
			||||||
 | 
					                    this.loadonly_imageLoadingQueue.enqueue({key: key, path: path});
 | 
				
			||||||
 | 
					                } else if(tileset.tiles){
 | 
				
			||||||
 | 
					                    for(let tile of tileset.tiles){
 | 
				
			||||||
 | 
					                        let key = tile.image;
 | 
				
			||||||
 | 
					                        let path = StringUtils.getPathFromFilePath(pathToTilemapJSON) + key;
 | 
				
			||||||
 | 
					                        this.loadonly_imageLoadingQueue.enqueue({key: key, path: path});
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Finish loading
 | 
					            // Finish loading
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,13 @@ import Scene from "../Scene";
 | 
				
			||||||
import Tilemap from "../../Nodes/Tilemap";
 | 
					import Tilemap from "../../Nodes/Tilemap";
 | 
				
			||||||
import PhysicsManager from "../../Physics/PhysicsManager";
 | 
					import PhysicsManager from "../../Physics/PhysicsManager";
 | 
				
			||||||
import ResourceManager from "../../ResourceManager/ResourceManager";
 | 
					import ResourceManager from "../../ResourceManager/ResourceManager";
 | 
				
			||||||
 | 
					import OrthogonalTilemap from "../../Nodes/Tilemaps/OrthogonalTilemap";
 | 
				
			||||||
 | 
					import Layer from "../Layer";
 | 
				
			||||||
 | 
					import Tileset from "../../DataTypes/Tilesets/Tileset";
 | 
				
			||||||
 | 
					import Vec2 from "../../DataTypes/Vec2";
 | 
				
			||||||
 | 
					import { TiledCollectionTile } from "../../DataTypes/Tilesets/TiledData";
 | 
				
			||||||
 | 
					import Sprite from "../../Nodes/Sprites/Sprite";
 | 
				
			||||||
 | 
					import StaticBody from "../../Physics/StaticBody";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class TilemapFactory {
 | 
					export default class TilemapFactory {
 | 
				
			||||||
    private scene: Scene;
 | 
					    private scene: Scene;
 | 
				
			||||||
| 
						 | 
					@ -22,40 +29,117 @@ export default class TilemapFactory {
 | 
				
			||||||
     * @param constr The constructor of the desired tilemap
 | 
					     * @param constr The constructor of the desired tilemap
 | 
				
			||||||
     * @param args Additional arguments to send to the tilemap constructor
 | 
					     * @param args Additional arguments to send to the tilemap constructor
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
	add = <T extends Tilemap>(key: string, constr: new (...a: any) => T, ...args: any): Array<Tilemap> => {
 | 
						add = (key: string): Array<Layer> => {
 | 
				
			||||||
        // Get Tilemap Data
 | 
					        // Get Tilemap Data
 | 
				
			||||||
        let tilemapData = this.resourceManager.getTilemap(key);
 | 
					        let tilemapData = this.resourceManager.getTilemap(key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Get the return values
 | 
					        // Set the constructor for this tilemap to either be orthographic or isometric
 | 
				
			||||||
        let tilemaps = new Array<Tilemap>();
 | 
					        let constr: new(...args: any) => Tilemap;
 | 
				
			||||||
 | 
					        if(tilemapData.orientation === "orthographic"){
 | 
				
			||||||
        for(let layer of tilemapData.layers){
 | 
					            constr = OrthogonalTilemap;
 | 
				
			||||||
            // Create a new tilemap object for the layer
 | 
					        } else {
 | 
				
			||||||
            let tilemap = new constr(tilemapData, layer);
 | 
					            // No isometric tilemap support right now, so Orthographic tilemap
 | 
				
			||||||
            tilemap.setScene(this.scene);
 | 
					            constr = OrthogonalTilemap;
 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Add tilemap to scene
 | 
					 | 
				
			||||||
            this.tilemaps.push(tilemap);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Create a new layer in the scene
 | 
					 | 
				
			||||||
            let sceneLayer = this.scene.addLayer();
 | 
					 | 
				
			||||||
            sceneLayer.addNode(tilemap);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Register tilemap with physics if it's collidable
 | 
					 | 
				
			||||||
            if(tilemap.isCollidable()){
 | 
					 | 
				
			||||||
                this.physicsManager.addTilemap(tilemap);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Assign each tileset it's image
 | 
					 | 
				
			||||||
            tilemap.getTilesets().forEach(tileset => {
 | 
					 | 
				
			||||||
                let image = this.resourceManager.getImage(tileset.getImageUrl());
 | 
					 | 
				
			||||||
                tileset.setImage(image);
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Update the return value
 | 
					 | 
				
			||||||
            tilemaps.push(tilemap);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return tilemaps;
 | 
					        // Initialize the return value array
 | 
				
			||||||
 | 
					        let sceneLayers = new Array<Layer>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Create all of the tilesets for this tilemap
 | 
				
			||||||
 | 
					        let tilesets = new Array<Tileset>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let collectionTiles = new Array<TiledCollectionTile>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for(let tileset of tilemapData.tilesets){
 | 
				
			||||||
 | 
					            if(tileset.image){
 | 
				
			||||||
 | 
					                // If this is a standard tileset and not a collection, create a tileset for it.
 | 
				
			||||||
 | 
					                // TODO - We are ignoring collection tilesets for now. This is likely not a great idea in practice,
 | 
				
			||||||
 | 
					                // as theoretically someone could want to use one for a standard tilemap. We are assuming for now
 | 
				
			||||||
 | 
					                // that we only want to use them for object layers
 | 
				
			||||||
 | 
					                tilesets.push(new Tileset(tileset));
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                tileset.tiles.forEach(tile => tile.id += tileset.firstgid);
 | 
				
			||||||
 | 
					                collectionTiles.push(...tileset.tiles);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Loop over the layers of the tilemap and create tiledlayers or object layers
 | 
				
			||||||
 | 
					        for(let layer of tilemapData.layers){
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            let sceneLayer = this.scene.addLayer();
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if(layer.type === "tilelayer"){
 | 
				
			||||||
 | 
					                // Create a new tilemap object for the layer
 | 
				
			||||||
 | 
					                let tilemap = new constr(tilemapData, layer, tilesets);
 | 
				
			||||||
 | 
					                tilemap.setScene(this.scene);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					                // Add tilemap to scene
 | 
				
			||||||
 | 
					                this.tilemaps.push(tilemap);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					                sceneLayer.addNode(tilemap);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					                // Register tilemap with physics if it's collidable
 | 
				
			||||||
 | 
					                if(tilemap.isCollidable()){
 | 
				
			||||||
 | 
					                    this.physicsManager.addTilemap(tilemap);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                // Layer is an object layer, so add each object as a sprite to a new layer
 | 
				
			||||||
 | 
					                for(let obj of layer.objects){
 | 
				
			||||||
 | 
					                    // Check if obj is collidable
 | 
				
			||||||
 | 
					                    let collidable = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    for(let prop of obj.properties){
 | 
				
			||||||
 | 
					                        if(prop.name === "Collidable"){
 | 
				
			||||||
 | 
					                            collidable = prop.value;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    let sprite: Sprite;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // Check if obj is a tile from a tileset
 | 
				
			||||||
 | 
					                    for(let tileset of tilesets){
 | 
				
			||||||
 | 
					                        if(tileset.hasTile(obj.gid)){
 | 
				
			||||||
 | 
					                            // The object is a tile from this set
 | 
				
			||||||
 | 
					                            let imageKey = tileset.getImageKey();
 | 
				
			||||||
 | 
					                            let offset = tileset.getImageOffsetForTile(obj.gid);
 | 
				
			||||||
 | 
					                            sprite = this.scene.add.sprite(imageKey, sceneLayer);
 | 
				
			||||||
 | 
					                            let size = tileset.getTileSize().clone();
 | 
				
			||||||
 | 
					                            sprite.setPosition(obj.x*4, (obj.y - size.y)*4);
 | 
				
			||||||
 | 
					                            sprite.setImageOffset(offset);
 | 
				
			||||||
 | 
					                            sprite.setSize(size);
 | 
				
			||||||
 | 
					                            sprite.setScale(new Vec2(4, 4));
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // Not in a tileset, must correspond to a collection
 | 
				
			||||||
 | 
					                    if(!sprite){
 | 
				
			||||||
 | 
					                        for(let tile of collectionTiles){
 | 
				
			||||||
 | 
					                            if(obj.gid === tile.id){
 | 
				
			||||||
 | 
					                                let imageKey = tile.image;
 | 
				
			||||||
 | 
					                                sprite = this.scene.add.sprite(imageKey, sceneLayer);
 | 
				
			||||||
 | 
					                                sprite.setPosition(obj.x*4, (obj.y - tile.imageheight)*4);
 | 
				
			||||||
 | 
					                                sprite.setScale(new Vec2(4, 4));
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // Now we have sprite. Associate it with our physics object if there is one
 | 
				
			||||||
 | 
					                    if(collidable){
 | 
				
			||||||
 | 
					                        let pos = sprite.getPosition().clone();
 | 
				
			||||||
 | 
					                        pos.x = Math.floor(pos.x);
 | 
				
			||||||
 | 
					                        pos.y = Math.floor(pos.y);
 | 
				
			||||||
 | 
					                        let size = sprite.getSize().clone().mult(sprite.getScale());
 | 
				
			||||||
 | 
					                        let staticBody = this.scene.add.physics(StaticBody, sceneLayer, pos, size);
 | 
				
			||||||
 | 
					                        staticBody.addChild(sprite);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Update the return value
 | 
				
			||||||
 | 
					            sceneLayers.push(sceneLayer);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return sceneLayers;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -89,11 +89,12 @@ export default class Viewport {
 | 
				
			||||||
    includes(node: CanvasNode): boolean {
 | 
					    includes(node: CanvasNode): boolean {
 | 
				
			||||||
        let nodePos = node.getPosition();
 | 
					        let nodePos = node.getPosition();
 | 
				
			||||||
        let nodeSize = node.getSize();
 | 
					        let nodeSize = node.getSize();
 | 
				
			||||||
 | 
					        let nodeScale = node.getScale();
 | 
				
			||||||
        let parallax = node.getLayer().getParallax();
 | 
					        let parallax = node.getLayer().getParallax();
 | 
				
			||||||
        let originX = this.position.x*parallax.x;
 | 
					        let originX = this.position.x*parallax.x;
 | 
				
			||||||
        let originY = this.position.y*parallax.y;
 | 
					        let originY = this.position.y*parallax.y;
 | 
				
			||||||
        if(nodePos.x + nodeSize.x > originX && nodePos.x < originX + this.size.x){
 | 
					        if(nodePos.x + nodeSize.x * nodeScale.x > originX && nodePos.x < originX + this.size.x){
 | 
				
			||||||
            if(nodePos.y + nodeSize.y > originY && nodePos.y < originY + this.size.y){
 | 
					            if(nodePos.y + nodeSize.y * nodeScale.y > originY && nodePos.y < originY + this.size.y){
 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,16 +35,16 @@ export default class SecondScene extends Scene {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    startScene(){
 | 
					    startScene(){
 | 
				
			||||||
        // Add the background tilemap
 | 
					        // Add the background tilemap
 | 
				
			||||||
        let backgroundTilemap = this.add.tilemap("background2", OrthogonalTilemap)[0];
 | 
					        let backgroundTilemapLayer = this.add.tilemap("background2")[0];
 | 
				
			||||||
        // ...and make it have parallax
 | 
					        // ...and make it have parallax
 | 
				
			||||||
        backgroundTilemap.getLayer().setParallax(1, 1);
 | 
					        backgroundTilemapLayer.setParallax(1, 1);
 | 
				
			||||||
        backgroundTilemap.getLayer().setAlpha(0.2);
 | 
					        backgroundTilemapLayer.setAlpha(0.2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Add the music and start playing it on a loop
 | 
					        // Add the music and start playing it on a loop
 | 
				
			||||||
        this.emitter.fireEvent(GameEventType.PLAY_SOUND, {key: "level_music", loop: true, holdReference: true});
 | 
					        this.emitter.fireEvent(GameEventType.PLAY_SOUND, {key: "level_music", loop: true, holdReference: true});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Add the tilemap
 | 
					        // Add the tilemap
 | 
				
			||||||
        this.add.tilemap("level2", OrthogonalTilemap);
 | 
					        this.add.tilemap("level2");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Create the main game layer
 | 
					        // Create the main game layer
 | 
				
			||||||
        let mainLayer = this.addLayer();
 | 
					        let mainLayer = this.addLayer();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user