import {Trait} from "../Entity.js"; import Vec2 from "../Vec2.js"; export default class TPhysics extends Trait { constructor(entity) { super(entity, "physics"); this.velocity = new Vec2(); this.gravity = 40; this.groundFriction = 6; this.airFriction = 2; this.timeLastOnGround = 0; this.onGround = false; this.groundBounds = null; this.groundVelocity = null; } collideTop(bounds, velocity) { if (!this.groundBounds || bounds.top < this.groundBounds.top) { this.groundBounds = bounds; this.groundVelocity = velocity; } } collideWall(bounds, velocity) { let side = this.entity.bounds.intersectSide(bounds); if (side === "top") { this.collideTop(bounds, velocity); } else if (side === "left" && this.velocity.x > velocity.x) { this.velocity.x = velocity.x; this.entity.bounds.right = bounds.left; } else if (side === "right" && this.velocity.x < velocity.x) { this.velocity.x = velocity.x; this.entity.bounds.left = bounds.right; } else if (side === "bottom" && this.velocity.y < velocity.y) { this.velocity.y = velocity.y; this.entity.bounds.top = bounds.bottom; } } collidePlatform(bounds, velocity) { let side = this.entity.bounds.intersectSide(bounds); if (side === "top") return this.collideTop(bounds, velocity); } update(dt) { // Collide if (this.entity.has("collider")) { let collider = this.entity.t.collider; this.groundBounds = null; this.groundVelocity = null; collider.entities.forEach(e => { let vel = Vec2.zero; if (e.has("physics")) vel = e.t.physics.velocity; if (e.has("wall")) this.collideWall(e.bounds, vel); else if (e.has("platform")) this.collidePlatform(e.bounds, vel); }); collider.structures.forEach((s) => { if (s.attrs.wall) this.collideWall(s.bounds, Vec2.zero); else if (s.attrs.platform) this.collidePlatform(s.bounds, Vec2.zero); }); } this.onGround = this.groundVelocity && this.velocity.y >= this.groundVelocity.y; if (this.onGround) { this.timeLastOnGround = this.entity.time; this.velocity.y = this.groundVelocity.y; } if (!this.onGround) this.velocity.y += this.gravity * dt; // Apply friction var fric = this.onGround ? this.groundFriction : this.airFriction; var xRatio = 1 / (1 + (dt * fric)); this.velocity.x *= xRatio; } postUpdate(dt) { // Move this.entity.pos.x += this.velocity.x * dt; this.entity.pos.y += this.velocity.y * dt; if (this.onGround) this.entity.bounds.bottom = this.groundBounds.top; } }