2d-physics-engine
Version:
A lightweight, flexible 2D physics engine with ECS architecture, built with TypeScript
59 lines • 3.14 kB
JavaScript
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