public moveSprite()

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;
    }