Javascript平台碰撞检测

时间:2018-01-23 10:59:23

标签: javascript html

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

我正在尝试制作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链接并跳转一下......

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

2 个答案:

答案 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)){

这与上面的改变基本相同,但现在检查天花板。希望这会有所帮助。

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