UNPKG

2d-physics-engine

Version:

A lightweight, flexible 2D physics engine with ECS architecture, built with TypeScript

59 lines 3.14 kB
import { CircleCollider } from '../../components/ColliderComponents/CircleCollider.component'; export class CollisionResolver { constructor() { Object.defineProperty(this, "collisionMatrix", { enumerable: true, configurable: true, writable: true, value: new Map() }); // Register circle vs circle collision this.registerCollisionResolver(CircleCollider.COLLIDER_ID, CircleCollider.COLLIDER_ID, this.circleVsCircleResolver); } registerCollisionResolver(typeA, typeB, resolver) { if (!this.collisionMatrix.has(typeA)) { this.collisionMatrix.set(typeA, new Map()); } this.collisionMatrix.get(typeA).set(typeB, resolver); } resolveCollision(collision) { const handlersForA = this.collisionMatrix.get(collision.colliderA.colliderId); if (!handlersForA) return false; const resolver = handlersForA.get(collision.colliderB.colliderId); if (!resolver) return false; return resolver(collision); } circleVsCircleResolver(collision) { const { transformA, transformB, rigidbodyA, rigidbodyB } = collision; const { penetration, normal } = collision.info; if (!rigidbodyA || !rigidbodyB) { return false; // No rigidbodies attached, cannot resolve collision } // Coefficient of Restitution (average of both colliders) const effectiveCR = (rigidbodyA.getRestitution() + rigidbodyB.getRestitution()) / 2; // Velocity components along the collision normal const vANormal = normal.dotProduct(rigidbodyA.getVelocity()); const vBNormal = normal.dotProduct(rigidbodyB.getVelocity()); // Velocity components along the tangent (perpendicular to normal) const tangent = normal.getTangent(); const vATangent = tangent.dotProduct(rigidbodyA.getVelocity()); const vBTangent = tangent.dotProduct(rigidbodyB.getVelocity()); // Total momentum and mass const totalMomentum = rigidbodyA.getMass() * vANormal + rigidbodyB.getMass() * vBNormal; const totalMass = rigidbodyA.getMass() + rigidbodyB.getMass(); // New normal velocities after collision const vANormalAfter = (effectiveCR * rigidbodyB.getMass() * (vBNormal - vANormal) + totalMomentum) / totalMass; const vBNormalAfter = (effectiveCR * rigidbodyA.getMass() * (vANormal - vBNormal) + totalMomentum) / totalMass; // Update velocities rigidbodyA.setVelocity(normal.scale(vANormalAfter).add(tangent.scale(vATangent))); rigidbodyB.setVelocity(normal.scale(vBNormalAfter).add(tangent.scale(vBTangent))); // Resolve penetration by adjusting positions const resolutionVector = normal.scale(penetration / totalMass); transformA.setPosition(transformA.getPosition().subtract(resolutionVector.scale(rigidbodyB.getMass()))); transformB.setPosition(transformB.getPosition().add(resolutionVector.scale(rigidbodyA.getMass()))); return true; } } //# sourceMappingURL=CollisionResolver.js.map