This commit is contained in:
Schluffe
2026-07-31 00:01:09 +02:00
parent 3885c6dbb6
commit bb071074d2
+48 -14
View File
@@ -89,6 +89,7 @@ ctx.imageSmoothingEnabled = false;
// player is an AABB (top-left corner + size) // player is an AABB (top-left corner + size)
const player = { x: 40, y: 40, w: 12, h: 12 }; const player = { x: 40, y: 40, w: 12, h: 12 };
window.player = player;
// walls: a border plus a few interior blocks to slide against // walls: a border plus a few interior blocks to slide against
const T = 8; // border thickness const T = 8; // border thickness
@@ -101,7 +102,7 @@ const walls = [
{ x: 0, y: H - T, w: W, h: T }, // bottom { x: 0, y: H - T, w: W, h: T }, // bottom
{ x: 0, y: 0, w: T, h: H }, // left { x: 0, y: 0, w: T, h: H }, // left
{ x: W - T, y: 0, w: T, h: H }, // right { x: W - T, y: 0, w: T, h: H }, // right
{ x: 150, y: 30, w: 16, h: 90 }, // a pillar { x: 144, y: 30, w: 12, h: 82 }, // a pillar
{ x: 96, y: 96, w: 60, h: 16 }, // a bar { x: 96, y: 96, w: 60, h: 16 }, // a bar
ledge, ledge,
]; ];
@@ -160,23 +161,56 @@ function penetrationVector(a, b) {
return null; return null;
} }
/** function resolveOverlaps(box, walls) {
* moveAndSlide, but immune to the overlap trap: first push `box` out of any const res = {
* wall it is already inside (plus an EPSILON of slack, same idea as the x: box.x,
* backoff in the loop), THEN run the normal sweep loop from the safe spot. y: box.y,
* settled: true,
* Everything you need is penetrationVector above and given.ts. };
*/
function safeMoveAndSlide(box, v, walls) { const count = walls.length;
for (const wall of walls) { let index = 0;
const pv = penetrationVector(box, wall); let tries = 0;
while (index < count) {
const pv = penetrationVector(box, walls[index++]);
if (pv) { if (pv) {
box.x += pv.x > 0 ? pv.x + EPSILON : pv.x - EPSILON; if (pv.x !== 0) {
box.y += pv.y > 0 ? pv.y + EPSILON : pv.y - EPSILON; 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 moveAndSlide(box, v, walls); return res;
}
function safeMoveAndSlide(box, v, walls) {
const res = resolveOverlaps(box, walls);
if (res.settled) {
return moveAndSlide(box, v, walls);
}
return {
x: box.x,
y: box.y,
};
} }
let then = performance.now(); let then = performance.now();