javascript - 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;
};
解决方案
推荐阅读
- java - Maven 没有创建具有正确路径的类
- php - 使用 Doctrine 加载一个 sqlite 扩展
- python - 以特定值拆分列表
- kubernetes - Kubernetes 监控和自我修复
- node.js - 使用 npm audit 手动修复漏洞
- matlab - Using GetMouse/GetClick to get location of a click in psychtoolbox
- angular - 使用 flatMap 将第一次调用的响应合并到第二次调用中会出现错误 [不支持的媒体类型状态 415] --
- git - Git 显示最近 X 小时内修改(但尚未提交)的文件列表
- oracle - 在 oracle 中使用嵌套表打印元素
- javascript - map 函数中的 if/else 语句?