time for a snapshot
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user