UNPKG

blaze-2d

Version:

A fast and simple WebGL 2 2D game engine written in TypeScript

159 lines 5.38 kB
import AABB from "../aabb/aabb"; import AABBTree from "../aabb/aabbTree"; import Manifold from "../manifold"; import ManifoldMap from "../manifoldMap"; import Space from "./space"; /** * Represents an infinite space containing {@link CollisionObject}s. * * Can be used to test for and solve collisions between objects in the space. */ export default class CollisionsSpace extends Space { /** * Creates a {@link CollisionSpace} instance. * * @param gravity The gravity vector to use in the collision space */ constructor(gravity) { super(); this.collisionManifolds = []; this.triggerManifolds = []; /** * Collision manifolds map. */ this.collisions = new ManifoldMap(); /** * Trigger manifolds map. */ this.triggers = new ManifoldMap(); /** * The {@link AABBTree} used for broadphase and raycasting. */ this.aabbTree = new AABBTree(); this.gravity = gravity; } /** * Executes a solver on every collision manifold in the space. * * Make sure to call `this.obtainManifolds` before executing any solvers. * * @param id The id of the solver to execute * @param delta The time since the last update */ solve(id, delta) { const solver = this.solvers[id]; if (!solver) return; for (let i = 0; i < solver.iterations; i++) { for (const m of this.collisionManifolds) { solver.cb(m, delta, i, solver.iterations); } } } /** * Fire "collision" and "trigger" events on objects in `this.manifolds`. * * If both objects in a collision are triggers object `a` will recieve the "trigger" the event. */ fireEvents() { for (const m of this.collisionManifolds) { m.a.fireEvent("collision", m); m.b.fireEvent("collision", m); } for (const m of this.triggerManifolds) { if (m.a.isTrigger) { m.a.fireEvent("trigger", m); } else if (m.b.isTrigger) { m.b.fireEvent("trigger", m); } } } /** * Performs the broadphase collision detection. * * The broadphase will update the {@link AABBTree} and then obtain possible collision pairs for the narrow phase. */ broadphase() { this.aabbTree.update(); this.collisionPairs = this.aabbTree.collectPairs(); } /** * Obtains all collision and trigger manifolds for the current frame. * * Manifolds are stored in `this.manifolds` * * obtainManifolds should only be called once per frame. * * @param delta Time since last frame */ obtainManifolds(delta) { // invalidate all manifolds this.collisions.killAllManifolds(); this.triggers.killAllManifolds(); for (const pair of this.collisionPairs) { let A = pair.a; let B = pair.b; // swap A and B if a manifold already exists for this pair of objects // this increases the possibility of contact point caching const key = this.collisions.getManifoldKey(A, B) || this.triggers.getManifoldKey(A, B); if (key && key.top === B) { A = pair.b; B = pair.a; // console.log("swap"); } // test collision const res = A.testCollision(B); if (res.hasCollision) { const manifold = new Manifold(A, B, res, this.gravity, delta); if (A.isTrigger || B.isTrigger) { this.triggers.addManifold(A, B, manifold); } else { this.collisions.addManifold(A, B, manifold); } } } // remove dead manifolds this.collisions.removeDeadManifolds(); this.triggers.removeDeadManifolds(); // update manifold arrays this.getCollisionManifolds(); this.getTriggerManifolds(); } /** * Gets all the manifolds in the collisions {@link ManifoldMap} and stores them in `this.collisionManifolds`. */ getCollisionManifolds() { this.collisionManifolds = this.collisions.getAllManifolds(); } /** * Gets all the manifolds in the triggers {@link ManifoldMap} and stores them in `this.triggersManifolds`. */ getTriggerManifolds() { this.triggerManifolds = this.triggers.getAllManifolds(); } /** * Adds an object to the space. * * @param obj The {@link CollisionObject} to add to the space */ addObject(obj) { const vel = obj.velocity; const margin = Math.max(Math.abs(vel[0]), Math.abs(vel[1])); this.aabbTree.add(new AABB(obj, margin)); super.addObject(obj); } /** * Removes an object from the space and deletes any manifolds associated with it. * * @param obj The {@link CollisionObject} to remove from the space */ removeObject(obj) { this.collisions.removeManifoldsInvolving(obj); this.triggers.removeManifoldsInvolving(obj); this.aabbTree.remove(obj); return super.removeObject(obj); } } //# sourceMappingURL=collisions.js.map