added basic collisions
This commit is contained in:
		
							parent
							
								
									e6d4d75cd5
								
							
						
					
					
						commit
						201e1624c4
					
				| 
						 | 
					@ -1,6 +1,8 @@
 | 
				
			||||||
export class TiledTilemapData {
 | 
					export class TiledTilemapData {
 | 
				
			||||||
    height: number;
 | 
					    height: number;
 | 
				
			||||||
    width: number;
 | 
					    width: number;
 | 
				
			||||||
 | 
					    tileheight: number;
 | 
				
			||||||
 | 
					    tilewidth: number;
 | 
				
			||||||
    orientation: string;
 | 
					    orientation: string;
 | 
				
			||||||
    layers: TiledLayerData[];
 | 
					    layers: TiledLayerData[];
 | 
				
			||||||
    tilesets: TiledTilesetData[];
 | 
					    tilesets: TiledTilesetData[];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,8 @@ import Tilemap from "../../Nodes/Tilemap"
 | 
				
			||||||
import ResourceManager from "../../ResourceManager/ResourceManager";
 | 
					import ResourceManager from "../../ResourceManager/ResourceManager";
 | 
				
			||||||
import { TiledTilemapData } from "../../DataTypes/Tilesets/TiledData";
 | 
					import { TiledTilemapData } from "../../DataTypes/Tilesets/TiledData";
 | 
				
			||||||
import StringUtils from "../../Utils/StringUtils";
 | 
					import StringUtils from "../../Utils/StringUtils";
 | 
				
			||||||
 | 
					import StaticBody from "../../Physics/StaticBody";
 | 
				
			||||||
 | 
					import Vec2 from "../../DataTypes/Vec2";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class TilemapFactory {
 | 
					export default class TilemapFactory {
 | 
				
			||||||
    private scene: Scene;
 | 
					    private scene: Scene;
 | 
				
			||||||
| 
						 | 
					@ -25,6 +27,17 @@ export default class TilemapFactory {
 | 
				
			||||||
                // Add to scene
 | 
					                // Add to scene
 | 
				
			||||||
                this.scene.addTilemap(tilemap);
 | 
					                this.scene.addTilemap(tilemap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                let worldSize = tilemap.getWorldSize();
 | 
				
			||||||
 | 
					                let tileSize = tilemap.getTileSize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                tilemap.forEachTile((tileIndex: number, i: number) => {
 | 
				
			||||||
 | 
					                    if(tileIndex !== 0){
 | 
				
			||||||
 | 
					                        let x = (i % worldSize.x) * tileSize.x * 4;
 | 
				
			||||||
 | 
					                        let y = Math.floor(i / worldSize.y) * tileSize.y * 4;
 | 
				
			||||||
 | 
					                        this.scene.physics.add(StaticBody, new Vec2(x, y), new Vec2(tileSize.x * 4, tileSize.y * 4));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Load images for the tilesets
 | 
					                // Load images for the tilesets
 | 
				
			||||||
                tilemap.getTilesets().forEach(tileset => {
 | 
					                tilemap.getTilesets().forEach(tileset => {
 | 
				
			||||||
                    let imagePath = StringUtils.getPathFromFilePath(path) + tileset.getImageUrl();
 | 
					                    let imagePath = StringUtils.getPathFromFilePath(path) + tileset.getImageUrl();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,11 +10,13 @@ export default abstract class Tilemap extends GameNode {
 | 
				
			||||||
    protected data: number[];
 | 
					    protected data: number[];
 | 
				
			||||||
    protected tilesets: Tileset[];
 | 
					    protected tilesets: Tileset[];
 | 
				
			||||||
    protected worldSize: Vec2;
 | 
					    protected worldSize: Vec2;
 | 
				
			||||||
 | 
					    protected tileSize: Vec2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(tilemapData: TiledTilemapData, layerData: TiledLayerData){
 | 
					    constructor(tilemapData: TiledTilemapData, layerData: TiledLayerData){
 | 
				
			||||||
        super();
 | 
					        super();
 | 
				
			||||||
        this.tilesets = new Array<Tileset>();
 | 
					        this.tilesets = new Array<Tileset>();
 | 
				
			||||||
        this.worldSize = new Vec2(0, 0);
 | 
					        this.worldSize = new Vec2(0, 0);
 | 
				
			||||||
 | 
					        this.tileSize = new Vec2(0, 0);
 | 
				
			||||||
        this.parseTilemapData(tilemapData, layerData);
 | 
					        this.parseTilemapData(tilemapData, layerData);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +24,14 @@ export default abstract class Tilemap extends GameNode {
 | 
				
			||||||
        return this.tilesets;
 | 
					        return this.tilesets;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getWorldSize(): Vec2 {
 | 
				
			||||||
 | 
					        return this.worldSize;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getTileSize(): Vec2 {
 | 
				
			||||||
 | 
					        return this.tileSize;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    isReady(): boolean {
 | 
					    isReady(): boolean {
 | 
				
			||||||
        if(this.tilesets.length !== 0){
 | 
					        if(this.tilesets.length !== 0){
 | 
				
			||||||
            for(let tileset of this.tilesets){
 | 
					            for(let tileset of this.tilesets){
 | 
				
			||||||
| 
						 | 
					@ -33,6 +43,8 @@ export default abstract class Tilemap extends GameNode {
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    abstract forEachTile(func: Function): void;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Sets up the tileset using the data loaded from file
 | 
					     * Sets up the tileset using the data loaded from file
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,10 +7,17 @@ import Tileset from "../../DataTypes/Tilesets/Tileset";
 | 
				
			||||||
export default class OrthogonalTilemap extends Tilemap {
 | 
					export default class OrthogonalTilemap extends Tilemap {
 | 
				
			||||||
    parseTilemapData(tilemapData: TiledTilemapData, layer: TiledLayerData): void {
 | 
					    parseTilemapData(tilemapData: TiledTilemapData, layer: TiledLayerData): void {
 | 
				
			||||||
        this.worldSize.set(tilemapData.width, tilemapData.height);
 | 
					        this.worldSize.set(tilemapData.width, tilemapData.height);
 | 
				
			||||||
 | 
					        this.tileSize.set(tilemapData.tilewidth, tilemapData.tileheight);
 | 
				
			||||||
        this.data = layer.data;
 | 
					        this.data = layer.data;
 | 
				
			||||||
        tilemapData.tilesets.forEach(tilesetData => this.tilesets.push(new Tileset(tilesetData)));
 | 
					        tilemapData.tilesets.forEach(tilesetData => this.tilesets.push(new Tileset(tilesetData)));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    forEachTile(func: Function){
 | 
				
			||||||
 | 
					        for(let i = 0; i < this.data.length; i++){
 | 
				
			||||||
 | 
					            func(this.data[i], i);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    update(deltaT: number): void {}
 | 
					    update(deltaT: number): void {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render(ctx: CanvasRenderingContext2D, origin: Vec2, viewportSize: Vec2) {
 | 
					    render(ctx: CanvasRenderingContext2D, origin: Vec2, viewportSize: Vec2) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
import PhysicsNode from "./PhysicsNode";
 | 
					import PhysicsNode from "./PhysicsNode";
 | 
				
			||||||
import Vec2 from "../DataTypes/Vec2";
 | 
					import Vec2 from "../DataTypes/Vec2";
 | 
				
			||||||
 | 
					import StaticBody from "./StaticBody";
 | 
				
			||||||
 | 
					import Debug from "../Debug/Debug";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class PhysicsManager {
 | 
					export default class PhysicsManager {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,11 +49,8 @@ export default class PhysicsManager {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
            for(let staticNode of staticSet){
 | 
					            for(let staticNode of staticSet){
 | 
				
			||||||
                if(movingNode.getCollider().willCollideWith(staticNode.getCollider(), velocity, new Vec2(0, 0))){
 | 
					                this.handleCollision(movingNode, staticNode, velocity, (<StaticBody>staticNode).id);
 | 
				
			||||||
                    this.handleCollision(movingNode, staticNode, velocity);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            movingNode.finishMove(velocity);
 | 
					            movingNode.finishMove(velocity);
 | 
				
			||||||
| 
						 | 
					@ -61,20 +60,94 @@ export default class PhysicsManager {
 | 
				
			||||||
        this.movements = new Array();
 | 
					        this.movements = new Array();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    handleCollision(movingNode: PhysicsNode, staticNode: PhysicsNode, velocity: Vec2){
 | 
					    handleCollision(movingNode: PhysicsNode, staticNode: PhysicsNode, velocity: Vec2, id: String){
 | 
				
			||||||
        let ASize = movingNode.getCollider().getSize();
 | 
					        let sizeA = movingNode.getCollider().getSize();
 | 
				
			||||||
        let A = new Vec2(movingNode.getPosition().x + ASize.x, movingNode.getPosition().y + ASize.y);
 | 
					        let A = movingNode.getPosition();
 | 
				
			||||||
        let BSize = staticNode.getCollider().getSize();
 | 
					        let velA = velocity;
 | 
				
			||||||
        let B = new Vec2(staticNode.getPosition().x + BSize.x, staticNode.getPosition().y + BSize.y);
 | 
					        let sizeB = staticNode.getCollider().getSize();
 | 
				
			||||||
 | 
					        let B = staticNode.getPosition();
 | 
				
			||||||
 | 
					        let velB = new Vec2(0, 0);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        let firstContact = new Vec2(0, 0);
 | 
					        let firstContact = new Vec2(0, 0);
 | 
				
			||||||
        firstContact.x = (B.x-(BSize.x/2) - (A.x + (ASize.x/2)))/(velocity.x - 0);
 | 
					        let lastContact = new Vec2(0, 0);
 | 
				
			||||||
        firstContact.y = (B.y-(BSize.y/2) - (A.y + (ASize.y/2)))/(velocity.y - 0);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(firstContact.x < 1 || firstContact.y < 1){
 | 
					        let collidingX = false;
 | 
				
			||||||
            // We collided
 | 
					        let collidingY = false;
 | 
				
			||||||
            let firstCollisionTime = Math.min(firstContact.x, firstContact.y);
 | 
					
 | 
				
			||||||
            velocity.scale(firstCollisionTime);
 | 
					        // Sort by position
 | 
				
			||||||
 | 
					        if(B.x < A.x){
 | 
				
			||||||
 | 
					            // Swap, because B is to the left of A
 | 
				
			||||||
 | 
					            let temp: Vec2;
 | 
				
			||||||
 | 
					            temp = sizeA;
 | 
				
			||||||
 | 
					            sizeA = sizeB;
 | 
				
			||||||
 | 
					            sizeB = temp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            temp = A;
 | 
				
			||||||
 | 
					            A = B;
 | 
				
			||||||
 | 
					            B = temp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            temp = velA;
 | 
				
			||||||
 | 
					            velA = velB;
 | 
				
			||||||
 | 
					            velB = temp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // A is left, B is right
 | 
				
			||||||
 | 
					        firstContact.x = Infinity;
 | 
				
			||||||
 | 
					        lastContact.x = Infinity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (B.x >= A.x + sizeA.x){
 | 
				
			||||||
 | 
					            // If we aren't currently colliding
 | 
				
			||||||
 | 
					            let relVel = velA.x - velB.x;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if(relVel > 0){
 | 
				
			||||||
 | 
					                // If they are moving towards each other
 | 
				
			||||||
 | 
					                firstContact.x = (B.x - (A.x + (sizeA.x)))/(relVel);
 | 
				
			||||||
 | 
					                lastContact.x = ((B.x + sizeB.x) - A.x)/(relVel);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            collidingX = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(B.y < A.y){
 | 
				
			||||||
 | 
					            // Swap, because B is above A
 | 
				
			||||||
 | 
					            let temp: Vec2;
 | 
				
			||||||
 | 
					            temp = sizeA;
 | 
				
			||||||
 | 
					            sizeA = sizeB;
 | 
				
			||||||
 | 
					            sizeB = temp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            temp = A;
 | 
				
			||||||
 | 
					            A = B;
 | 
				
			||||||
 | 
					            B = temp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            temp = velA;
 | 
				
			||||||
 | 
					            velA = velB;
 | 
				
			||||||
 | 
					            velB = temp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // A is top, B is bottom
 | 
				
			||||||
 | 
					        firstContact.y = Infinity;
 | 
				
			||||||
 | 
					        lastContact.y = Infinity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (B.y >= A.y + sizeA.y){
 | 
				
			||||||
 | 
					            // If we aren't currently colliding
 | 
				
			||||||
 | 
					            let relVel = velA.y - velB.y;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if(relVel > 0){
 | 
				
			||||||
 | 
					                // If they are moving towards each other
 | 
				
			||||||
 | 
					                firstContact.y = (B.y - (A.y + (sizeA.y)))/(relVel);
 | 
				
			||||||
 | 
					                lastContact.y = ((B.y + sizeB.y) - A.y)/(relVel);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            collidingY = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if( (firstContact.x < 1 || collidingX) && (firstContact.y < 1 || collidingY)){
 | 
				
			||||||
 | 
					            if(collidingX && collidingY){
 | 
				
			||||||
 | 
					                // If we're already intersecting, freak out I guess?
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                let contactTime = Math.min(firstContact.x, firstContact.y);
 | 
				
			||||||
 | 
					                velocity.scale(contactTime);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,6 +35,7 @@ export default abstract class PhysicsNode extends GameNode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    finishMove(velocity: Vec2): void {
 | 
					    finishMove(velocity: Vec2): void {
 | 
				
			||||||
        this.position.add(velocity);
 | 
					        this.position.add(velocity);
 | 
				
			||||||
 | 
					        this.collider.getPosition().add(velocity);
 | 
				
			||||||
        for(let child of this.children){
 | 
					        for(let child of this.children){
 | 
				
			||||||
            child.getPosition().add(velocity);
 | 
					            child.getPosition().add(velocity);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										24
									
								
								src/Physics/StaticBody.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/Physics/StaticBody.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,24 @@
 | 
				
			||||||
 | 
					import PhysicsNode from "./PhysicsNode";
 | 
				
			||||||
 | 
					import Vec2 from "../DataTypes/Vec2";
 | 
				
			||||||
 | 
					import AABB from "./Colliders/AABB";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default class StaticBody extends PhysicsNode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    id: string;
 | 
				
			||||||
 | 
					    static numCreated: number = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor(position: Vec2, size: Vec2){
 | 
				
			||||||
 | 
					        super();
 | 
				
			||||||
 | 
					        this.setPosition(position.x, position.y);
 | 
				
			||||||
 | 
					        this.collider = new AABB();
 | 
				
			||||||
 | 
					        this.collider.setPosition(position.x, position.y);
 | 
				
			||||||
 | 
					        this.collider.setSize(new Vec2(size.x, size.y));
 | 
				
			||||||
 | 
					        this.id = StaticBody.numCreated.toString();
 | 
				
			||||||
 | 
					        StaticBody.numCreated += 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    create(): void {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    update(deltaT: number): void {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -8,13 +8,15 @@ export default class Player extends PhysicsNode {
 | 
				
			||||||
	velocity: Vec2;
 | 
						velocity: Vec2;
 | 
				
			||||||
	speed: number;
 | 
						speed: number;
 | 
				
			||||||
    debug: Debug;
 | 
					    debug: Debug;
 | 
				
			||||||
 | 
					    size: Vec2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(){
 | 
					    constructor(){
 | 
				
			||||||
        super();
 | 
					        super();
 | 
				
			||||||
        this.velocity = new Vec2(0, 0);
 | 
					        this.velocity = new Vec2(0, 0);
 | 
				
			||||||
        this.speed = 300;
 | 
					        this.speed = 300;
 | 
				
			||||||
 | 
					        this.size = new Vec2(50, 50);
 | 
				
			||||||
        this.collider = new AABB();
 | 
					        this.collider = new AABB();
 | 
				
			||||||
        this.collider.setSize(new Vec2(50, 50));
 | 
					        this.collider.setSize(this.size);
 | 
				
			||||||
        this.position = new Vec2(0, 0);
 | 
					        this.position = new Vec2(0, 0);
 | 
				
			||||||
		this.debug = Debug.getInstance();
 | 
							this.debug = Debug.getInstance();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -22,7 +24,7 @@ export default class Player extends PhysicsNode {
 | 
				
			||||||
    create(): void {
 | 
					    create(): void {
 | 
				
			||||||
        let sprite = this.scene.canvasNode.add(PlayerSprite);
 | 
					        let sprite = this.scene.canvasNode.add(PlayerSprite);
 | 
				
			||||||
        sprite.setPosition(this.position);
 | 
					        sprite.setPosition(this.position);
 | 
				
			||||||
        sprite.setSize(50, 50);
 | 
					        sprite.setSize(this.size);
 | 
				
			||||||
        this.children.push(sprite);
 | 
					        this.children.push(sprite);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,7 +40,7 @@ export default class Player extends PhysicsNode {
 | 
				
			||||||
        this.velocity = dir.scale(this.speed);
 | 
					        this.velocity = dir.scale(this.speed);
 | 
				
			||||||
		this.move(this.velocity.scale(deltaT));
 | 
							this.move(this.velocity.scale(deltaT));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.debug.log("player", "Player Pos: " + this.position.toFixed());
 | 
							this.debug.log("player", "Player Pos: " + this.position.toFixed() + " " + this.velocity.toFixed());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -78,7 +78,7 @@ function main(){
 | 
				
			||||||
        pauseMenu.disable();
 | 
					        pauseMenu.disable();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mainScene.tilemap.add(OrthogonalTilemap, "assets/tilemaps/MultiLayer.json");
 | 
					    mainScene.tilemap.add(OrthogonalTilemap, "assets/tilemaps/SmallTest.json");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for(let i = 0; i < 30; i++){
 | 
					    for(let i = 0; i < 30; i++){
 | 
				
			||||||
        let cc = foregroundLayer.canvasNode.add(ColoredCircle);
 | 
					        let cc = foregroundLayer.canvasNode.add(ColoredCircle);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user