Javascript 平台游戏碰撞检测



所以这个问题之前可能被问过几次,但我似乎找不到使碰撞检测正常工作的方法。

我正在尝试制作一个HTML画布/Javascript平台游戏。如果你想看看它的作用,它在代码笔上:https://codepen.io/Arthurvanhoorebeke/pen/zpaZYM

我正在做的是检查我的播放器的角落在哪些瓷砖/"盒子"中。这意味着我对播放器上方和下方的块进行了正常检测,但横向检测非常糟糕。

我知道底部碰撞检查是搞砸横向检测的原因,但我似乎无法修复它。 这就是我现在得到的:

function tileCheck(world){
var player_topy = Math.ceil(player1.pos[1] / world.squareHeight) || 0;
var player_bottomy = Math.ceil((player1.pos[1]+player1.height)/world.squareHeight) || 0;
var player_leftx = Math.floor(player1.pos[0]/world.squareWidth) || 0;
var player_rightx = Math.floor((player1.pos[0]+player1.width)/world.squareWidth) || 0;
var topRightBlock = getSquare(world1,player_rightx,player_topy-1); 
var topLeftBlock = getSquare(world1,player_leftx,player_topy-1);
var bottomRightBlock = getSquare(world1,player_rightx,player_bottomy-1);
var bottomLeftBlock = getSquare(world1,player_leftx,player_bottomy-1);
//checks if blocks are solid
var topRightSol = world.legend[topRightBlock].solid;
var topLeftSol = world.legend[topLeftBlock].solid;
var bottomRightSol = world.legend[bottomRightBlock].solid;
var bottomLeftSol = world.legend[bottomLeftBlock].solid;
//This kinda messes up my 'sideways collision detection'.
if((bottomRightSol && !topRightSol) || (bottomLeftSol && !topLeftSol)){
player1.pos[1] -= (player1.pos[1]+player1.height) - (player_bottomy-1)*world.squareHeight;
player1.vel[1] = 0;
player1.grounded = true;
}
else{
player1.grounded = false;
}
if((topLeftSol && !bottomLeftSol) || (topRightSol && !bottomRightSol)){
player1.pos[1] += player_topy*world.squareHeight - player1.pos[1];
player1.vel[1] = 0;
}
//This doesn't work properly.
if(topLeftSol && bottomLeftSol){
player1.vel[0] = 0;
player1.wallLeft = true;
player1.pos[0] += (player_leftx+1)*world.squareWidth - player1.pos[0];
}
else{player1.wallLeft = false}
if(topRightSol && bottomRightSol){
player1.vel[0] = 0;
player1.wallRight = true;
player1.pos[0] -= (player1.pos[0]+player1.width) - (player_rightx)*world.squareWidth;
}
else{player1.wallRight = false}
}

我知道当只有玩家块的一个角碰到其他东西时,横向检测是行不通的。问题是,当玩家击中一个方块时,它的垂直位置会被底部碰撞检查器改变(至少我认为这是问题所在)。

如果您想查看确切的问题,请尝试打开代码笔链接并跳来跳去......

是否有解决此问题的方法,或者我需要重新考虑我的整个功能?

完全重新思考。通过碰撞检测,这个想法是预测路径,这适用于 2d 以及 3d 和 im,建议更多的是完整的模拟,然后如果路径被阻塞,你必须找到,最重要的是经常错过,撞击点。 因此,在 2D 中使用盒子时,它变得微不足道。 计算具有 X Y 分量的轨迹矢量。 然后测试每个箱子的碰撞,如果很多使用实例化探测球体,只需在距离之间检查是否靠近碰撞,并达到一个撞击点。 然后,应将冲击矢量用作角色的下一个位置。这允许滑过反弹和反弹的边缘。 希望我有帮助。否则,请指定任何错误,您的代码将签出。

也许您想尝试更改此设置:

if((bottomRightSol || !topRightSol) || (bottomLeftSol && !topLeftSol)){

对此:

if((bottomRightSol || bottomLeftSol) && (!topRightSol && !topLeftSol)){

这里的区别在于,如果我正确理解了你的代码,你现在要检查以确保你至少在一个角落与地面发生碰撞,然后确保你没有与角落里的任何东西发生碰撞。我认为这应该可以防止玩家在半空中被移动。


编辑以下注释:

//This kinda messes up my 'sideways collision detection'.
if((bottomRightSol && !topRightSol) || (bottomLeftSol && !topLeftSol)){
player1.pos[1] -= (player1.pos[1]+player1.height) - (player_bottomy-1)*world.squareHeight;
player1.vel[1] = 0;
player1.grounded = true;
}
else{
player1.grounded = false;
}
if((topLeftSol && !bottomLeftSol) || (topRightSol && !bottomRightSol)){
player1.pos[1] += player_topy*world.squareHeight - player1.pos[1];
player1.vel[1] = 0;
}

我已经建议修复的最重要的if语句。下面的第二个我会更改为以下内容:

if((topLeftSol || topRightSol) && (!bottomLeftSol && !bottomRightSol)){

这基本上与上述更改相同,但现在检查上限。希望这有帮助。

顺便说一句,虽然我相信这些解决方案是正确的,但无论如何,正如建议的那样重写函数并没有什么坏处。

最新更新