pocket-physics
Version:
Verlet physics extracted from pocket-ces demos
67 lines (58 loc) • 1.78 kB
text/typescript
import { set, v2, Vector2 } from "./v2";
// https://github.com/noonat/intersect/blob/master/intersect.js
export type AABBOverlapResult<V2 extends Vector2> = {
resolve: V2;
hitPos: V2;
normal: V2;
};
/**
* Create a result object to use for overlap tests.
*/
export const createAABBOverlapResult = <V extends number>(): AABBOverlapResult<
Vector2<V>
> => {
return { resolve: v2(), hitPos: v2(), normal: v2() };
};
/**
* Compute the "collision manifold" for two AABB, storing the result in `result`.
* Note: The `normal` is always perpendicular to an AABB edge, which may produce
* some slighly weird-looking collisions. `collisionResponseAABB()` will compute
* a normal using the midpoints, which looks more natural.
*/
export const overlapAABBAABB = (
center1X: number,
center1Y: number,
width1: number,
height1: number,
center2X: number,
center2Y: number,
width2: number,
height2: number,
result: AABBOverlapResult<Vector2>
) => {
const dx = center2X - center1X;
const px = width2 / 2 + width1 / 2 - Math.abs(dx);
const dy = center2Y - center1Y;
const py = height2 / 2 + height1 / 2 - Math.abs(dy);
if (px <= 0) return null;
if (py <= 0) return null;
set(result.resolve, 0, 0);
set(result.hitPos, 0, 0);
set(result.normal, 0, 0);
if (px < py) {
const sx = dx < 0 ? -1 : 1;
result.resolve.x = px * sx;
result.normal.x = sx;
// Really not sure about these values.
result.hitPos.x = center1X + (width1 / 2) * sx;
result.hitPos.y = center2Y;
} else {
const sy = dy < 0 ? -1 : 1;
result.resolve.y = py * sy;
result.normal.y = sy;
// Really not sure about these values.
result.hitPos.x = center2X;
result.hitPos.y = center1Y + (height1 / 2) * sy;
}
return result;
};