ehm
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
import { expect, test } from "bun:test";
|
||||
import { type AABB, aabbOverlap, vec } from "./given.ts";
|
||||
import { penetrationVector, safeMoveAndSlide } from "./overlap.ts";
|
||||
|
||||
// --- penetrationVector -------------------------------------------------------
|
||||
|
||||
test("separated boxes -> null", () => {
|
||||
const a: AABB = { x: 0, y: 0, w: 2, h: 2 };
|
||||
const b: AABB = { x: 5, y: 5, w: 2, h: 2 };
|
||||
expect(penetrationVector(a, b)).toBeNull();
|
||||
});
|
||||
|
||||
test("touching edges (no strict overlap) -> null", () => {
|
||||
const a: AABB = { x: 0, y: 0, w: 2, h: 2 };
|
||||
const b: AABB = { x: 2, y: 0, w: 2, h: 2 };
|
||||
expect(penetrationVector(a, b)).toBeNull();
|
||||
});
|
||||
|
||||
test("shallow on x, deep on y -> pushes left (the short way out)", () => {
|
||||
// a pokes 1 unit into b's left side; getting out via y would cost 6
|
||||
const a: AABB = { x: 0, y: 0, w: 4, h: 4 };
|
||||
const b: AABB = { x: 3, y: -2, w: 4, h: 8 };
|
||||
expect(penetrationVector(a, b)).toEqual(vec(-1, 0));
|
||||
});
|
||||
|
||||
test("mirrored -> pushes right", () => {
|
||||
const a: AABB = { x: 4, y: 0, w: 4, h: 4 };
|
||||
const b: AABB = { x: 1, y: -2, w: 4, h: 8 };
|
||||
expect(penetrationVector(a, b)).toEqual(vec(1, 0));
|
||||
});
|
||||
|
||||
test("shallow on y -> pushes up", () => {
|
||||
const a: AABB = { x: 0, y: 0, w: 4, h: 4 };
|
||||
const b: AABB = { x: -2, y: 3, w: 8, h: 4 };
|
||||
expect(penetrationVector(a, b)).toEqual(vec(0, -1));
|
||||
});
|
||||
|
||||
test("fully contained -> still gets out (all the way past the nearest edge)", () => {
|
||||
// a is swallowed by b: the push must clear the whole distance to an edge,
|
||||
// not just the 2-unit "overlap" of the intervals
|
||||
const a: AABB = { x: 10, y: 10, w: 2, h: 2 };
|
||||
const b: AABB = { x: 0, y: 0, w: 32, h: 32 };
|
||||
const p = penetrationVector(a, b);
|
||||
expect(p).not.toBeNull();
|
||||
if (p !== null) {
|
||||
const moved: AABB = { ...a, x: a.x + p.x, y: a.y + p.y };
|
||||
expect(aabbOverlap(moved, b)).toBe(false);
|
||||
}
|
||||
});
|
||||
|
||||
// --- safeMoveAndSlide --------------------------------------------------------
|
||||
|
||||
const player: AABB = { x: 0, y: 0, w: 2, h: 2 };
|
||||
|
||||
test("no overlap at start -> behaves exactly like moveAndSlide", () => {
|
||||
// step 10's diagonal test: x blocked at 3, y keeps going
|
||||
const walls: AABB[] = [{ x: 5, y: -10, w: 2, h: 40 }];
|
||||
const p = safeMoveAndSlide(player, vec(10, 10), walls);
|
||||
expect(p.x).toBeCloseTo(3);
|
||||
expect(p.y).toBeCloseTo(10);
|
||||
});
|
||||
|
||||
test("starting inside a wall -> position stays a number", () => {
|
||||
const inside: AABB = { x: 10, y: 10, w: 2, h: 2 };
|
||||
const wall: AABB = { x: 0, y: 0, w: 32, h: 32 };
|
||||
const p = safeMoveAndSlide(inside, vec(5, 0), [wall]);
|
||||
expect(Number.isFinite(p.x)).toBe(true);
|
||||
expect(Number.isFinite(p.y)).toBe(true);
|
||||
});
|
||||
|
||||
test("starting inside a wall -> ends free of it", () => {
|
||||
const inside: AABB = { x: 10, y: 10, w: 2, h: 2 };
|
||||
const wall: AABB = { x: 0, y: 0, w: 32, h: 32 };
|
||||
const p = safeMoveAndSlide(inside, vec(5, 0), [wall]);
|
||||
expect(aabbOverlap({ ...inside, x: p.x, y: p.y }, wall)).toBe(false);
|
||||
});
|
||||
|
||||
test("overlapping and walking AWAY -> actually gets away", () => {
|
||||
// pokes 1 into the wall's left side; pushed out to x≈8, then walks -5
|
||||
const stuck: AABB = { x: 9, y: 0, w: 2, h: 2 };
|
||||
const wall: AABB = { x: 10, y: -5, w: 4, h: 10 };
|
||||
const p = safeMoveAndSlide(stuck, vec(-5, 0), [wall]);
|
||||
expect(p.x).toBeCloseTo(3);
|
||||
expect(p.y).toBeCloseTo(0);
|
||||
});
|
||||
|
||||
test("overlapping and pushing IN -> freed, then held at the wall", () => {
|
||||
// pushed out to x≈8 first; the sweep then stops the rightward move there
|
||||
const stuck: AABB = { x: 9, y: 0, w: 2, h: 2 };
|
||||
const wall: AABB = { x: 10, y: -5, w: 4, h: 10 };
|
||||
const p = safeMoveAndSlide(stuck, vec(5, 0), [wall]);
|
||||
expect(p.x).toBeCloseTo(8);
|
||||
expect(p.y).toBeCloseTo(0);
|
||||
});
|
||||
|
||||
test("overlapping and pushing IN (rtl) -> freed, then held at the wall", () => {
|
||||
const stuck: AABB = { x: 9, y: 0, w: 2, h: 2 };
|
||||
const wall: AABB = { x: 10, y: -5, w: 4, h: 10 };
|
||||
const p = safeMoveAndSlide(stuck, vec(-5, 0), [wall]);
|
||||
expect(p.x).toBeCloseTo(3);
|
||||
expect(p.y).toBeCloseTo(0);
|
||||
});
|
||||
Reference in New Issue
Block a user