首页 > 解决方案 > Canvas 平台游戏 JS - 碰撞

问题描述

因此,我尝试创建一个平台游戏,但是 5 天来我遇到了碰撞问题,如果我的重力太大(角色从高处坠落),即使有条件存在我的对象卡在障碍物(地面)内并且当我向左或向右时,我可以通过障碍,尝试解决这个问题,但它不起作用。

因此,我创建了 BoundingBox 类,它类似于每个障碍物和玩家的阴影(第二个透明对象),它检查玩家阴影是否与障碍物阴影发生碰撞。

    class BoundingBox {
    constructor(x, y, width, height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.x2 = this.x + this.width;
        this.y2 = this.y + this.height;
    }

    draw() {
        ctx.beginPath();
        ctx.save();
        ctx.globalAlpha = 0;
        ctx.fillRect(this.x, this.y, this.width, this.height);
        ctx.restore();
    }

    update(x, y) {
        this.x = x;
        this.y = y;
        this.x2 = x + this.width;
        this.y2 = y + this.height;
    }

    checkCollision(ob) {
        return this.x2 > ob.x && this.x < ob.x2 && this.y2 >= ob.y && this.y < ob.y2;
    }
}

Character类和Obstacle类包含这些BoundingBox实例类(bbx),它继承了这些类的x,y,width,height位置。

class Player {
    constructor(x, y, width, height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.speedX = 1;
        this.speedY = 1;
        this.leftArrowPressed = false;
        this.rightArrowPressed = false;
        this.bbx = new BoundingBox(this.x, this.y, this.width, this.height);
        this.color = "rgba(255,0,0)";
    }

    draw() {
        ctx.beginPath();
        ctx.save();
        ctx.fillStyle = this.color;
        ctx.strokeStyle = "red";
        ctx.stroke();
        ctx.fillRect(this.x, this.y, this.width, this.height);
        ctx.restore();
        this.bbx.draw();
    }

    update() {
        this.handleController();
        this.gravity();
        this.draw();
        this.bbx.update(this.x, this.y);

        if (blockCollision(this.bbx, this.x, this.y + this.speedY)) {
            while (!blockCollision(this.bbx, this.x, this.y + Math.sign(this.speedY))) this.y -= Math.sign(this.speedY);
            this.speedY = 0;
        }

        if (blockCollision(this.bbx, this.x + this.speedX, this.y)) {
            while (!blockCollision(this.bbx, this.x, this.y + Math.sign(this.speedX))) this.y -= Math.sign(this.speedX);
            this.speedX = 0;
        }
    }

    gravity() {
        this.y += this.speedY;
        this.speedY += 0.09; //it's too high and my player can stuck inside an obstacle
    }

    controll() {
        addEventListener("keydown", e => {
            if (e.code === "Space") {
                this.speedY = -5;
            } else if (e.code === "ArrowRight") {
                this.speedX = -5;
                this.rightArrowPressed = true;
            } else if (e.code === "ArrowLeft") {
                this.speedX = 5;
                this.leftArrowPressed = true;
            }
        });

        addEventListener("keyup", e => {
            if (e.code === "ArrowRight") {
                this.rightArrowPressed = false;
            } else if (e.code === "ArrowLeft") {
                this.leftArrowPressed = false;
            }
        });
    }

    handleController() {
        this.controll();
        if (this.leftArrowPressed) {
            this.x -= this.speedX;
        } else if (this.rightArrowPressed) {
            this.x -= this.speedX;
        }
    }
}

class Block {
    constructor(x, y) {
        this.x = x;
        this.y = y;
        this.width = 32;
        this.height = 32;
        this.bbx = new BoundingBox(this.x, this.y, this.width, this.height);
        Block.blocks.push(this);
    }

    draw() {
        ctx.beginPath();
        ctx.save();
        ctx.fillStyle = "red";
        ctx.fillRect(this.x, this.y, this.width, this.height);
        this.bbx.draw();
        ctx.restore();
    }

    static blocks = [];
}

有一个函数,它使每个障碍物循环并检查条件:

// check if any block collisions with character
const blockCollision = (bbx, x, y) => {
    const lastX = bbx.x;
    const lastY = bbx.y;

    const collision = Block.blocks.some(block => {
        if (block.bbx.checkCollision(bbx)) return true;
    });
    return collision;
};

标签: javascriptcanvascollisiongravity

解决方案


推荐阅读