diff --git a/workshop/steps/12-overlap/overlap.ts b/workshop/steps/12-overlap/overlap.ts index fc0cc82..adc1a17 100644 --- a/workshop/steps/12-overlap/overlap.ts +++ b/workshop/steps/12-overlap/overlap.ts @@ -38,8 +38,12 @@ export function safeMoveAndSlide(box: AABB, v: Vec, walls: AABB[]): Vec { for (const wall of walls) { const pv = penetrationVector(box, wall); if (pv) { - box.x += pv.x > 0 ? pv.x + EPSILON : pv.x - EPSILON; - box.y += pv.y > 0 ? pv.y + EPSILON : pv.y - EPSILON; + if (pv.x !== 0) { + box.x += pv.x > 0 ? pv.x + EPSILON : pv.x - EPSILON; + } + if (pv.y !== 0) { + box.y += pv.y > 0 ? pv.y + EPSILON : pv.y - EPSILON; + } } } diff --git a/workshop/steps/13-crush/crush.ts b/workshop/steps/13-crush/crush.ts index dd3b4cf..be5064a 100644 --- a/workshop/steps/13-crush/crush.ts +++ b/workshop/steps/13-crush/crush.ts @@ -1,5 +1,6 @@ import { type AABB, + EPSILON, moveAndSlide, penetrationVector, type Vec, @@ -24,7 +25,43 @@ export type Resolution = { x: number; y: number; settled: boolean }; * Returns where the box ended up and whether it truly got free. */ export function resolveOverlaps(box: AABB, walls: AABB[]): Resolution { - throw new Error("not implemented"); + const res: Resolution = { + x: box.x, + y: box.y, + settled: true, + }; + + const count = walls.length; + let index = 0; + let tries = 0; + + while (index < count) { + const pv = penetrationVector(box, walls[index++]); + + if (pv) { + if (pv.x !== 0) { + box.x += pv.x > 0 ? pv.x + EPSILON : pv.x - EPSILON; + } + if (pv.y !== 0) { + box.y += pv.y > 0 ? pv.y + EPSILON : pv.y - EPSILON; + } + + res.x = box.x; + res.y = box.y; + res.settled = false; + + index = 0; + tries += 1; + } else { + res.settled = true; + } + + if (tries > 7) { + break; + } + } + + return res; } /** @@ -37,5 +74,13 @@ export function resolveOverlaps(box: AABB, walls: AABB[]): Resolution { * and waits for the gap to open. */ export function safeMoveAndSlide(box: AABB, v: Vec, walls: AABB[]): Vec { - throw new Error("not implemented"); + const res = resolveOverlaps(box, walls); + if (res.settled) { + return moveAndSlide(box, v, walls); + } + + return { + x: box.x, + y: box.y, + }; }