import { type AABB, add, EPSILON, type Hit, scale, slide, sweptAABB, type Vec, } from "./given.ts"; /** * Move `box` by the full-frame displacement `v`, sliding along any `walls` it * hits, up to 4 iterations. Returns the final corner position. * * See the README for the algorithm. You already have everything you need in * given.ts: sweptAABB, slide, add, scale, EPSILON. */ export function moveAndSlide(box: AABB, v: Vec, walls: AABB[]): Vec { let pos: Vec = { x: box.x, y: box.y }; let vel: Vec = { x: v.x, y: v.y }; let timeLeft = 1; let i = 0; while (i++ < 4 && timeLeft > 0) { const move = scale(vel, timeLeft); let nearest: Hit = { normal: { x: 0, y: 0 }, time: 2, }; for (const wall of walls) { const hit = sweptAABB( { x: pos.x, y: pos.y, w: box.w, h: box.h, }, move, wall, ); if (hit !== null) { nearest = hit.time < nearest.time ? hit : nearest; } } if (nearest.time === 2) { pos = add(pos, move); break; } else { pos = add(pos, scale(move, Math.max(0, nearest.time - EPSILON))); vel = slide(vel, nearest.normal); timeLeft = timeLeft * (1 - nearest.time); } } return pos; }