Canvas Platform 游戏 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,height 位置。

class Player {
    constructor(x,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.height);
        this.color = "rgba(255,0)";
    }

    draw() {
        ctx.beginPath();
        ctx.save();
        ctx.fillStyle = this.color;
        ctx.strokeStyle = "red";
        ctx.stroke();
        ctx.fillRect(this.x,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.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.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.height);
        Block.blocks.push(this);
    }

    draw() {
        ctx.beginPath();
        ctx.save();
        ctx.fillStyle = "red";
        ctx.fillRect(this.x,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;
};

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)