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