fixed tilemap physics
This commit is contained in:
parent
66ced08987
commit
2dd60b5197
|
@ -65,7 +65,7 @@ export default class Tileset {
|
|||
return tileIndex >= this.startIndex && tileIndex <= this.endIndex;
|
||||
}
|
||||
|
||||
renderTile(ctx: CanvasRenderingContext2D, tileIndex: number, dataIndex: number, worldSize: Vec2, origin: Vec2): void {
|
||||
renderTile(ctx: CanvasRenderingContext2D, tileIndex: number, dataIndex: number, worldSize: Vec2, origin: Vec2, scale: Vec2): void {
|
||||
let index = tileIndex - this.startIndex;
|
||||
let row = Math.floor(index / this.numCols);
|
||||
let col = index % this.numCols;
|
||||
|
@ -73,8 +73,8 @@ export default class Tileset {
|
|||
let height = this.tileSize.y;
|
||||
let left = col * width;
|
||||
let top = row * height;
|
||||
let x = (dataIndex % worldSize.x) * width * 4;
|
||||
let y = Math.floor(dataIndex / worldSize.x) * height * 4;
|
||||
ctx.drawImage(this.image, left, top, width, height, x - origin.x, y - origin.y, width * 4, height * 4);
|
||||
let x = (dataIndex % worldSize.x) * width * scale.x;
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -80,4 +80,8 @@ export default class Vec2 {
|
|||
toFixed(): string {
|
||||
return "(" + this.x.toFixed(1) + ", " + this.y.toFixed(1) + ")";
|
||||
}
|
||||
|
||||
clone(): Vec2 {
|
||||
return new Vec2(this.x, this.y);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ import Scene from "../Scene";
|
|||
import Viewport from "../../SceneGraph/Viewport";
|
||||
import PhysicsNode from "../../Physics/PhysicsNode";
|
||||
import PhysicsManager from "../../Physics/PhysicsManager";
|
||||
import Tilemap from "../../Nodes/Tilemap";
|
||||
|
||||
export default class PhysicsNodeFactory {
|
||||
private scene: Scene;
|
||||
|
@ -20,4 +21,8 @@ export default class PhysicsNodeFactory {
|
|||
this.physicsManager.add(instance);
|
||||
return instance;
|
||||
}
|
||||
|
||||
addTilemap(tilemap: Tilemap): void {
|
||||
this.physicsManager.addTilemap(tilemap);
|
||||
}
|
||||
}
|
|
@ -28,17 +28,20 @@ export default class TilemapFactory {
|
|||
this.scene.addTilemap(tilemap);
|
||||
|
||||
if(tilemap.isCollidable()){
|
||||
// Create colliders
|
||||
let worldSize = tilemap.getWorldSize();
|
||||
let tileSize = tilemap.getTileSize();
|
||||
// Register in physics as a tilemap
|
||||
this.scene.physics.addTilemap(tilemap);
|
||||
|
||||
tilemap.forEachTile((tileIndex: number, i: number) => {
|
||||
if(tileIndex !== 0){
|
||||
let x = (i % worldSize.x) * tileSize.x * 4;
|
||||
let y = Math.floor(i / worldSize.x) * tileSize.y * 4;
|
||||
this.scene.physics.add(StaticBody, new Vec2(x, y), new Vec2(tileSize.x * 4, tileSize.y * 4));
|
||||
}
|
||||
});
|
||||
// Create colliders
|
||||
// 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.x) * 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
|
||||
|
|
|
@ -8,11 +8,10 @@ export default class GameState{
|
|||
private worldSize: Vec2;
|
||||
private viewport: Viewport;
|
||||
|
||||
constructor(){
|
||||
constructor(viewport: Viewport){
|
||||
this.sceneStack = new Stack(10);
|
||||
this.worldSize = new Vec2(1600, 1000);
|
||||
this.viewport = new Viewport();
|
||||
this.viewport.setSize(800, 500);
|
||||
this.viewport = viewport;
|
||||
this.viewport.setBounds(0, 0, 2560, 1280);
|
||||
}
|
||||
|
||||
|
|
|
@ -98,6 +98,7 @@ export default class Scene {
|
|||
this.viewport.update(deltaT);
|
||||
this.physicsManager.update(deltaT);
|
||||
this.sceneGraph.update(deltaT);
|
||||
this.tilemaps.forEach((tilemap: Tilemap) => tilemap.update(deltaT));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import Receiver from "../Events/Receiver";
|
|||
import Map from "../DataTypes/Map";
|
||||
import Vec2 from "../DataTypes/Vec2";
|
||||
import EventQueue from "../Events/EventQueue";
|
||||
import Viewport from "../SceneGraph/Viewport";
|
||||
|
||||
export default class InputReceiver{
|
||||
private static instance: InputReceiver = null;
|
||||
|
@ -14,6 +15,7 @@ export default class InputReceiver{
|
|||
private mousePressPosition: Vec2;
|
||||
private eventQueue: EventQueue;
|
||||
private receiver: Receiver;
|
||||
private viewport: Viewport;
|
||||
|
||||
private constructor(){
|
||||
this.mousePressed = false;
|
||||
|
@ -108,7 +110,19 @@ export default class InputReceiver{
|
|||
return this.mousePosition;
|
||||
}
|
||||
|
||||
getGlobalMousePosition(): Vec2 {
|
||||
return this.mousePosition.clone().add(this.viewport.getPosition());
|
||||
}
|
||||
|
||||
getMousePressPosition(): Vec2 {
|
||||
return this.mousePressPosition;
|
||||
}
|
||||
|
||||
getGlobalMousePressPosition(): Vec2 {
|
||||
return this.mousePressPosition.clone().add(this.viewport.getPosition());
|
||||
}
|
||||
|
||||
setViewport(viewport: Viewport): void {
|
||||
this.viewport = viewport;
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import Recorder from "../Playback/Recorder";
|
|||
import GameState from "../GameState/GameState";
|
||||
import Debug from "../Debug/Debug";
|
||||
import ResourceManager from "../ResourceManager/ResourceManager";
|
||||
import Viewport from "../SceneGraph/Viewport";
|
||||
|
||||
export default class GameLoop{
|
||||
// The amount of time to spend on a physics step
|
||||
|
@ -29,7 +30,8 @@ export default class GameLoop{
|
|||
|
||||
readonly GAME_CANVAS: HTMLCanvasElement;
|
||||
readonly WIDTH: number;
|
||||
readonly HEIGHT: number;
|
||||
readonly HEIGHT: number;
|
||||
private viewport: Viewport;
|
||||
private ctx: CanvasRenderingContext2D;
|
||||
private eventQueue: EventQueue;
|
||||
private inputHandler: InputHandler;
|
||||
|
@ -57,12 +59,15 @@ export default class GameLoop{
|
|||
this.WIDTH = 800;
|
||||
this.HEIGHT = 500;
|
||||
this.ctx = this.initializeCanvas(this.GAME_CANVAS, this.WIDTH, this.HEIGHT);
|
||||
this.viewport = new Viewport();
|
||||
this.viewport.setSize(this.WIDTH, this.HEIGHT);
|
||||
|
||||
this.eventQueue = EventQueue.getInstance();
|
||||
this.inputHandler = new InputHandler(this.GAME_CANVAS);
|
||||
this.inputReceiver = InputReceiver.getInstance();
|
||||
this.inputReceiver.setViewport(this.viewport);
|
||||
this.recorder = new Recorder();
|
||||
this.gameState = new GameState();
|
||||
this.gameState = new GameState(this.viewport);
|
||||
this.debug = Debug.getInstance();
|
||||
this.resourceManager = ResourceManager.getInstance();
|
||||
}
|
||||
|
|
|
@ -8,11 +8,13 @@ import { TiledTilemapData, TiledLayerData } from "../DataTypes/Tilesets/TiledDat
|
|||
*/
|
||||
export default abstract class Tilemap extends GameNode {
|
||||
protected data: number[];
|
||||
protected collisionData: number [];
|
||||
protected tilesets: Tileset[];
|
||||
protected worldSize: Vec2;
|
||||
protected tileSize: Vec2;
|
||||
protected visible: boolean;
|
||||
protected collidable: boolean;
|
||||
protected scale: Vec2;
|
||||
|
||||
constructor(tilemapData: TiledTilemapData, layerData: TiledLayerData){
|
||||
super();
|
||||
|
@ -20,6 +22,7 @@ export default abstract class Tilemap extends GameNode {
|
|||
this.worldSize = new Vec2(0, 0);
|
||||
this.tileSize = new Vec2(0, 0);
|
||||
this.parseTilemapData(tilemapData, layerData);
|
||||
this.scale = new Vec2(4, 4);
|
||||
}
|
||||
|
||||
isCollidable(): boolean {
|
||||
|
@ -39,9 +42,19 @@ export default abstract class Tilemap extends GameNode {
|
|||
}
|
||||
|
||||
getTileSize(): Vec2 {
|
||||
return this.tileSize;
|
||||
return this.tileSize.clone().scale(this.scale.x, this.scale.y);
|
||||
}
|
||||
|
||||
getScale(): Vec2 {
|
||||
return this.scale;
|
||||
}
|
||||
|
||||
setScale(scale: Vec2): void {
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
abstract getTileAt(worldCoords: Vec2): number;
|
||||
|
||||
isReady(): boolean {
|
||||
if(this.tilesets.length !== 0){
|
||||
for(let tileset of this.tilesets){
|
||||
|
|
|
@ -10,6 +10,7 @@ export default class OrthogonalTilemap extends Tilemap {
|
|||
this.worldSize.set(tilemapData.width, tilemapData.height);
|
||||
this.tileSize.set(tilemapData.tilewidth, tilemapData.tileheight);
|
||||
this.data = layer.data;
|
||||
this.collisionData = this.data.map(tile => tile !== 0 ? 1 : 0);
|
||||
this.visible = layer.visible;
|
||||
this.collidable = false;
|
||||
if(layer.properties){
|
||||
|
@ -22,7 +23,40 @@ export default class OrthogonalTilemap extends Tilemap {
|
|||
tilemapData.tilesets.forEach(tilesetData => this.tilesets.push(new Tileset(tilesetData)));
|
||||
}
|
||||
|
||||
forEachTile(func: Function){
|
||||
getTileAt(worldCoords: Vec2): number {
|
||||
let localCoords = this.getColRowAt(worldCoords);
|
||||
if(localCoords.x < 0 || localCoords.x >= this.worldSize.x || localCoords.y < 0 || localCoords.y >= this.worldSize.y){
|
||||
// There are no tiles in negative positions or out of bounds positions
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this.data[localCoords.y * this.worldSize.x + localCoords.x];
|
||||
}
|
||||
|
||||
isTileCollidable(indexOrCol: number, row?: number): boolean {
|
||||
if(row){
|
||||
if(indexOrCol < 0 || indexOrCol >= this.worldSize.x || row < 0 || row >= this.worldSize.y){
|
||||
// There are no tiles in negative positions or out of bounds positions
|
||||
return false;
|
||||
}
|
||||
return this.collisionData[row * this.worldSize.x + indexOrCol] === 1 && this.collidable;
|
||||
} else {
|
||||
if(indexOrCol < 0 || indexOrCol >= this.collisionData.length){
|
||||
// Tiles that don't exist aren't collidable
|
||||
return false;
|
||||
}
|
||||
return this.collisionData[indexOrCol] === 1 && this.collidable;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Should this throw an error if someone tries to access an out of bounds value?
|
||||
getColRowAt(worldCoords: Vec2): Vec2 {
|
||||
let col = Math.floor(worldCoords.x / this.tileSize.x / this.scale.x);
|
||||
let row = Math.floor(worldCoords.y / this.tileSize.y / this.scale.y);
|
||||
return new Vec2(col, row);
|
||||
}
|
||||
|
||||
forEachTile(func: Function): void {
|
||||
for(let i = 0; i < this.data.length; i++){
|
||||
func(this.data[i], i);
|
||||
}
|
||||
|
@ -37,7 +71,7 @@ export default class OrthogonalTilemap extends Tilemap {
|
|||
|
||||
for(let tileset of this.tilesets){
|
||||
if(tileset.hasTile(tileIndex)){
|
||||
tileset.renderTile(ctx, tileIndex, i, this.worldSize, origin);
|
||||
tileset.renderTile(ctx, tileIndex, i, this.worldSize, origin, this.scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,14 +3,18 @@ import Vec2 from "../DataTypes/Vec2";
|
|||
import StaticBody from "./StaticBody";
|
||||
import Debug from "../Debug/Debug";
|
||||
import MathUtils from "../Utils/MathUtils";
|
||||
import Tilemap from "../Nodes/Tilemap";
|
||||
import OrthogonalTilemap from "../Nodes/Tilemaps/OrthogonalTilemap";
|
||||
|
||||
export default class PhysicsManager {
|
||||
|
||||
physicsNodes: Array<PhysicsNode>;
|
||||
tilemaps: Array<Tilemap>;
|
||||
movements: Array<MovementData>;
|
||||
|
||||
constructor(){
|
||||
this.physicsNodes = new Array();
|
||||
this.tilemaps = new Array();
|
||||
this.movements = new Array();
|
||||
}
|
||||
|
||||
|
@ -18,6 +22,10 @@ export default class PhysicsManager {
|
|||
this.physicsNodes.push(node);
|
||||
}
|
||||
|
||||
addTilemap(tilemap: Tilemap): void {
|
||||
this.tilemaps.push(tilemap);
|
||||
}
|
||||
|
||||
addMovement(node: PhysicsNode, velocity: Vec2){
|
||||
this.movements.push(new MovementData(node, velocity));
|
||||
}
|
||||
|
@ -51,8 +59,14 @@ export default class PhysicsManager {
|
|||
}
|
||||
}
|
||||
|
||||
for(let staticNode of staticSet){
|
||||
this.handleCollision(movingNode, staticNode, velocity, (<StaticBody>staticNode).id);
|
||||
// TODO handle collisions between dynamic nodes
|
||||
// We probably want to sort them by their left edges
|
||||
|
||||
// TODO: handle collisions between dynamic nodes and static nodes
|
||||
|
||||
// Handle Collisions with the tilemaps
|
||||
for(let tilemap of this.tilemaps){
|
||||
this.collideWithTilemap(movingNode, tilemap, velocity);
|
||||
}
|
||||
|
||||
movingNode.finishMove(velocity);
|
||||
|
@ -62,102 +76,90 @@ export default class PhysicsManager {
|
|||
this.movements = new Array();
|
||||
}
|
||||
|
||||
collideWithTilemap(node: PhysicsNode, tilemap: Tilemap, velocity: Vec2){
|
||||
if(tilemap instanceof OrthogonalTilemap){
|
||||
this.collideWithOrthogonalTilemap(node, tilemap, velocity);
|
||||
}
|
||||
}
|
||||
|
||||
collideWithOrthogonalTilemap(node: PhysicsNode, tilemap: OrthogonalTilemap, velocity: Vec2){
|
||||
let startPos = node.getPosition();
|
||||
let endPos = startPos.clone().add(velocity);
|
||||
let size = node.getCollider().getSize();
|
||||
let min = new Vec2(Math.min(startPos.x, endPos.x), Math.min(startPos.y, endPos.y));
|
||||
let max = new Vec2(Math.max(startPos.x + size.x, endPos.x + size.x), Math.max(startPos.y + size.y, endPos.y + size.y));
|
||||
|
||||
let minIndex = tilemap.getColRowAt(min);
|
||||
let maxIndex = tilemap.getColRowAt(max);
|
||||
|
||||
let tilemapCollisions = new Array<TileCollisionData>();
|
||||
let tileSize = tilemap.getTileSize();
|
||||
|
||||
Debug.getInstance().log("tilemapCollision", "");
|
||||
// Loop over all possible tiles
|
||||
for(let col = minIndex.x; col <= maxIndex.x; col++){
|
||||
for(let row = minIndex.y; row <= maxIndex.y; row++){
|
||||
if(tilemap.isTileCollidable(col, row)){
|
||||
Debug.getInstance().log("tilemapCollision", "Colliding with Tile");
|
||||
|
||||
// Tile position
|
||||
let tilePos = new Vec2(col * tileSize.x, row * tileSize.y);
|
||||
|
||||
// Calculate collision area
|
||||
let dx = Math.min(startPos.x, tilePos.x) - Math.max(startPos.x + size.x, tilePos.x + size.x);
|
||||
let dy = Math.min(startPos.y, tilePos.y) - Math.max(startPos.y + size.y, tilePos.y + size.y);
|
||||
|
||||
let overlap = 0;
|
||||
if(dx * dy > 0){
|
||||
overlap = dx * dy;
|
||||
}
|
||||
|
||||
tilemapCollisions.push(new TileCollisionData(tilePos, overlap));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we have all collisions, sort by collision area
|
||||
tilemapCollisions = tilemapCollisions.sort((a, b) => a.overlapArea - b.overlapArea);
|
||||
|
||||
// Resolve the collisions
|
||||
tilemapCollisions.forEach(collision => {
|
||||
let [firstContact, _, collidingX, collidingY] = this.getTimeOfCollision(startPos, size, velocity, collision.position, tileSize, new Vec2(0, 0));
|
||||
|
||||
// Handle collision
|
||||
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);
|
||||
let xScale = MathUtils.clamp(firstContact.x, 0, 1);
|
||||
let yScale = MathUtils.clamp(firstContact.y, 0, 1);
|
||||
|
||||
// Handle special case of stickiness on corner to corner collisions
|
||||
if(xScale === yScale){
|
||||
xScale = 1;
|
||||
}
|
||||
|
||||
if(yScale !== 1){
|
||||
node.setIsGrounded(true);
|
||||
}
|
||||
|
||||
velocity.scale(xScale, yScale);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
handleCollision(movingNode: PhysicsNode, staticNode: PhysicsNode, velocity: Vec2, id: String){
|
||||
let sizeA = movingNode.getCollider().getSize();
|
||||
let A = movingNode.getPosition();
|
||||
let posA = movingNode.getPosition();
|
||||
let velA = velocity;
|
||||
let sizeB = staticNode.getCollider().getSize();
|
||||
let B = staticNode.getPosition();
|
||||
let posB = staticNode.getPosition();
|
||||
let velB = new Vec2(0, 0);
|
||||
|
||||
let firstContact = new Vec2(0, 0);
|
||||
let lastContact = new Vec2(0, 0);
|
||||
|
||||
let collidingX = false;
|
||||
let collidingY = false;
|
||||
|
||||
// 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(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;
|
||||
}
|
||||
let [firstContact, _, collidingX, collidingY] = this.getTimeOfCollision(posA, sizeA, velA, posB, sizeB, velB);
|
||||
|
||||
if( (firstContact.x < 1 || collidingX) && (firstContact.y < 1 || collidingY)){
|
||||
if(collidingX && collidingY){
|
||||
|
@ -169,13 +171,96 @@ export default class PhysicsManager {
|
|||
let yScale = MathUtils.clamp(firstContact.y, 0, 1);
|
||||
if(yScale !== 1){
|
||||
movingNode.setIsGrounded(true);
|
||||
}
|
||||
}
|
||||
velocity.scale(xScale, yScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the collision time of two AABBs using continuous collision checking. Returns vectors representing the time
|
||||
* of the start and end of the collision and booleans for whether or not the objects are currently overlapping
|
||||
* (before they move).
|
||||
*/
|
||||
getTimeOfCollision(posA: Vec2, sizeA: Vec2, velA: Vec2, posB: Vec2, sizeB: Vec2, velB: Vec2): [Vec2, Vec2, boolean, boolean] {
|
||||
let firstContact = new Vec2(0, 0);
|
||||
let lastContact = new Vec2(0, 0);
|
||||
|
||||
let collidingX = false;
|
||||
let collidingY = false;
|
||||
|
||||
// Sort by position
|
||||
if(posB.x < posA.x){
|
||||
// Swap, because B is to the left of A
|
||||
let temp: Vec2;
|
||||
temp = sizeA;
|
||||
sizeA = sizeB;
|
||||
sizeB = temp;
|
||||
|
||||
temp = posA;
|
||||
posA = posB;
|
||||
posB = temp;
|
||||
|
||||
temp = velA;
|
||||
velA = velB;
|
||||
velB = temp;
|
||||
}
|
||||
|
||||
// A is left, B is right
|
||||
firstContact.x = Infinity;
|
||||
lastContact.x = Infinity;
|
||||
|
||||
if (posB.x >= posA.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 = (posB.x - (posA.x + (sizeA.x)))/(relVel);
|
||||
lastContact.x = ((posB.x + sizeB.x) - posA.x)/(relVel);
|
||||
}
|
||||
} else {
|
||||
collidingX = true;
|
||||
}
|
||||
|
||||
if(posB.y < posA.y){
|
||||
// Swap, because B is above A
|
||||
let temp: Vec2;
|
||||
temp = sizeA;
|
||||
sizeA = sizeB;
|
||||
sizeB = temp;
|
||||
|
||||
temp = posA;
|
||||
posA = posB;
|
||||
posB = temp;
|
||||
|
||||
temp = velA;
|
||||
velA = velB;
|
||||
velB = temp;
|
||||
}
|
||||
|
||||
// A is top, B is bottom
|
||||
firstContact.y = Infinity;
|
||||
lastContact.y = Infinity;
|
||||
|
||||
if (posB.y >= posA.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 = (posB.y - (posA.y + (sizeA.y)))/(relVel);
|
||||
lastContact.y = ((posB.y + sizeB.y) - posA.y)/(relVel);
|
||||
}
|
||||
} else {
|
||||
collidingY = true;
|
||||
}
|
||||
|
||||
return [firstContact, lastContact, collidingX, collidingY];
|
||||
}
|
||||
}
|
||||
|
||||
// Helper classes for internal data
|
||||
class MovementData{
|
||||
node: PhysicsNode;
|
||||
velocity: Vec2;
|
||||
|
@ -183,4 +268,13 @@ class MovementData{
|
|||
this.node = node;
|
||||
this.velocity = velocity;
|
||||
}
|
||||
}
|
||||
|
||||
class TileCollisionData {
|
||||
position: Vec2;
|
||||
overlapArea: number;
|
||||
constructor(position: Vec2, overlapArea: number){
|
||||
this.position = position;
|
||||
this.overlapArea = overlapArea;
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@ export default class Player extends PhysicsNode {
|
|||
super();
|
||||
this.type = type;
|
||||
this.velocity = new Vec2(0, 0);
|
||||
this.speed = 500;
|
||||
this.speed = 600;
|
||||
this.size = new Vec2(50, 50);
|
||||
this.collider = new AABB();
|
||||
this.collider.setSize(this.size);
|
||||
|
|
10
src/main.ts
10
src/main.ts
|
@ -74,12 +74,12 @@ function main(){
|
|||
pauseMenu.disable();
|
||||
}
|
||||
|
||||
// backgroundScene.tilemap.add(OrthogonalTilemap, "assets/tilemaps/Background.json");
|
||||
// mainScene.tilemap.add(OrthogonalTilemap, "assets/tilemaps/Platformer.json");
|
||||
// let player = mainScene.physics.add(Player, "platformer");
|
||||
backgroundScene.tilemap.add(OrthogonalTilemap, "assets/tilemaps/Background.json");
|
||||
mainScene.tilemap.add(OrthogonalTilemap, "assets/tilemaps/Platformer.json");
|
||||
let player = mainScene.physics.add(Player, "platformer");
|
||||
|
||||
mainScene.tilemap.add(OrthogonalTilemap, "assets/tilemaps/TopDown.json");
|
||||
let player = mainScene.physics.add(Player, "topdown");
|
||||
// mainScene.tilemap.add(OrthogonalTilemap, "assets/tilemaps/TopDown.json");
|
||||
// let player = mainScene.physics.add(Player, "topdown");
|
||||
|
||||
mainScene.getViewport().follow(player);
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
"src/Loop/GameLoop.ts",
|
||||
|
||||
"src/Nodes/Tilemaps/OrgthogonalTilemap.ts",
|
||||
"src/Nodes/Tilemaps/OrthogonalTilemap.ts",
|
||||
"src/Nodes/UIElements/Button.ts",
|
||||
"src/Nodes/UIElements/Label.ts",
|
||||
"src/Nodes/CanvasNode.ts",
|
||||
|
|
Loading…
Reference in New Issue
Block a user