in libs/game/physics.ts [144:236]
public moveSprite(s: Sprite, tm: tiles.TileMap, dx: number, dy: number) {
if (dx === 0 && dy === 0) {
s._lastX = s.x;
s._lastY = s.y;
return;
}
if (tm && !(s.flags & sprites.Flag.Ghost)) {
s._hitboxes.forEach(box => {
const t0 = box.top >> 4;
const r0 = box.right >> 4;
const b0 = box.bottom >> 4;
const l0 = box.left >> 4;
if (dx > 0) {
let topCollide = tm.isObstacle(r0 + 1, t0);
if (topCollide || tm.isObstacle(r0 + 1, b0)) {
const nextRight = box.right + dx;
const maxRight = ((r0 + 1) << 4) - GAP
if (nextRight > maxRight) {
dx -= (nextRight - maxRight);
s.registerObstacle(CollisionDirection.Right, tm.getObstacle(r0 + 1, topCollide ? t0 : b0))
}
}
}
else if (dx < 0) {
const topCollide = tm.isObstacle(l0 - 1, t0);
if (topCollide || tm.isObstacle(l0 - 1, b0)) {
const nextLeft = box.left + dx;
const minLeft = (l0 << 4) + GAP;
if (nextLeft < minLeft) {
dx -= (nextLeft - minLeft);
s.registerObstacle(CollisionDirection.Left, tm.getObstacle(l0 - 1, topCollide ? t0 : b0))
}
}
}
if (dy > 0) {
const rightCollide = tm.isObstacle(r0, b0 + 1);
if (rightCollide || tm.isObstacle(l0, b0 + 1)) {
const nextBottom = box.bottom + dy;
const maxBottom = ((b0 + 1) << 4) - GAP;
if (nextBottom > maxBottom) {
dy -= (nextBottom - maxBottom);
s.registerObstacle(CollisionDirection.Bottom, tm.getObstacle(rightCollide ? r0 : l0, b0 + 1))
}
}
}
else if (dy < 0) {
const rightCollide = tm.isObstacle(r0, t0 - 1);
if (tm.isObstacle(r0, t0 - 1) || tm.isObstacle(l0, t0 - 1)) {
const nextTop = box.top + dy;
const minTop = (t0 << 4) + GAP;
if (nextTop < minTop) {
dy -= (nextTop - minTop);
s.registerObstacle(CollisionDirection.Top, tm.getObstacle(rightCollide ? r0 : l0, t0 - 1))
}
}
}
// Now check each corner and bump out if necessary. This step is needed for
// the case where a hitbox goes diagonally into the corner of a tile.
const t1 = (box.top + dy) >> 4;
const r1 = (box.right + dx) >> 4;
const b1 = (box.bottom + dy) >> 4;
const l1 = (box.left + dx) >> 4;
if (tm.isObstacle(r1, t1)) {
// bump left
dx -= (box.right + dx - ((r1 << 4) - GAP))
s.registerObstacle(CollisionDirection.Right, tm.getObstacle(r1, t1));
}
else if (tm.isObstacle(l1, t1)) {
// bump right
dx -= (box.left + dx - (((l1 + 1) << 4) + GAP));
s.registerObstacle(CollisionDirection.Left, tm.getObstacle(l1, t1));
}
else {
const rightCollide = tm.isObstacle(r1, b1);
if (rightCollide || tm.isObstacle(l1, b1)) {
// bump up because that is usually better for platformers
dy -= (box.bottom + dy - ((b1 << 4) - GAP));
s.registerObstacle(CollisionDirection.Bottom, tm.getObstacle(rightCollide ? r1 : l1, b1));
}
}
});
}
s.x += dx;
s.y += dy;
s._lastX = s.x;
s._lastY = s.y;
}