ehm
This commit is contained in:
@@ -133,6 +133,51 @@ function drawBox(b, fill, stroke) {
|
||||
ctx.strokeRect(b.x + 0.5, b.y + 0.5, b.w - 1, b.h - 1);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* How to push `a` OUT of `b`, by the smallest possible single-axis move.
|
||||
*
|
||||
* Returns the push as a vector to ADD to a's position, or null if the boxes
|
||||
* don't strictly overlap (merely touching edges is not overlapping).
|
||||
*
|
||||
* There are four ways out (left, right, up, down) — measure all four
|
||||
* distances and return the shortest one. See the README.
|
||||
*/
|
||||
function penetrationVector(a, b) {
|
||||
const outLeft = a.x + a.w - b.x;
|
||||
const outRight = b.x + b.w - a.x;
|
||||
const outUp = a.y + a.h - b.y;
|
||||
const outDown = b.y + b.h - a.y;
|
||||
|
||||
const minX = Math.min(outLeft, outRight);
|
||||
const minY = Math.min(outUp, outDown);
|
||||
|
||||
if (minX > 0 && minY > 0) {
|
||||
return minX > minY
|
||||
? { x: 0, y: outDown > outUp ? -minY : minY }
|
||||
: { x: outLeft > outRight ? minX : -minX, y: 0 };
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* moveAndSlide, but immune to the overlap trap: first push `box` out of any
|
||||
* wall it is already inside (plus an EPSILON of slack, same idea as the
|
||||
* backoff in the loop), THEN run the normal sweep loop from the safe spot.
|
||||
*
|
||||
* Everything you need is penetrationVector above and given.ts.
|
||||
*/
|
||||
function safeMoveAndSlide(box, v, walls) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return moveAndSlide(box, v, walls);
|
||||
}
|
||||
|
||||
let then = performance.now();
|
||||
function frame(now) {
|
||||
@@ -156,7 +201,7 @@ function frame(now) {
|
||||
|
||||
// full-frame displacement is velocity * delta — exactly what moveAndSlide expects
|
||||
const displacement = scale(velocity, delta);
|
||||
const next = moveAndSlide(player, displacement, walls);
|
||||
const next = safeMoveAndSlide(player, displacement, walls);
|
||||
player.x = next.x;
|
||||
player.y = next.y;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user