所以这个问题之前可能已被问过几次,但我似乎找不到让碰撞检测工作正常的方法。
我正在尝试制作HTML canvas / Javascript平台游戏。如果你想知道它的作用,它就在codepen上: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}
}
我知道当玩家区块的一个角落碰到别的东西时,横向检测不起作用。问题是,当玩家遇到一个区块时,它的垂直位置会被底部碰撞检查器改变(至少我认为这是问题所在。)。
如果您想查看确切的问题,请尝试打开codepen链接并跳转一下......
是否有解决方法或我是否需要重新考虑我的整个功能?
答案 0 :(得分:2)
重新思考。使用碰撞检测的想法是预测路径,这适用于2d以及3d,我建议更多的完整模拟,然后如果路径被阻止,你必须找到,最重要的是经常错过,影响点。 因此在2d中使用盒子时变得微不足道。 计算具有X Y分量的轨迹矢量。 然后测试每个盒子是否碰撞,如果许多使用实例检测球体,只需检查是否接近碰撞,并达到撞击点。 然后应将影响向量用作角色的下一个位置。这允许在边缘上滑动弹跳和反弹。 希望我帮忙。否则请指出任何错误,您的代码会检查出来。
答案 1 :(得分:1)
也许你想尝试改变这个:
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)){
这与上面的改变基本相同,但现在检查天花板。希望这会有所帮助。
顺便说一句,虽然我认为这些解决方案是正确的,但正如所建议的那样,无论如何重写函数都没有坏处。