【问题标题】:Javascript platformer collision detectionJavascript 平台游戏碰撞检测
【发布时间】:2018-01-28 21:26:55
【问题描述】:

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

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

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

【问题讨论】:

    标签: javascript html


    【解决方案1】:

    彻底反思。使用碰撞检测的想法是预测路径,这适用于 2d 和 3d 并且我建议更多的完整模拟,然后如果路径被阻塞,您必须找到,最重要的是经常错过的撞击点。 因此,在 2d 中使用框时变得微不足道。 计算具有 X Y 分量的轨迹矢量。 然后测试每个盒子是否碰撞,如果很多使用实例检测球,只需距离检查colldet是否接近,并达到一个碰撞点。 然后冲击向量应用作字符的下一个位置。这允许在反弹和反弹的边缘上滑动。 希望我有所帮助。否则请说明任何错误,您的代码会检查出来。

    【讨论】:

    • 我已经在一个数组中获得了玩家的速度,所以我可以将它用作向量,是吗?感谢您的详细回答,我会看看我是否可以完成这项工作
    【解决方案2】:

    也许你想尝试改变这个:

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

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

    顺便说一句,虽然我相信这些解决方案是正确的,但按照建议重新编写函数并没有什么坏处。

    【讨论】:

    • 这确实修复了被向下移动的问题。我留下的问题正在上移……我想我只需要重做整个功能
    • 我已经编辑了“ifs”,并添加了一个检查,以便在玩家向上移动时底部碰撞不会做任何事情。这似乎足以解决问题,这样我就可以自己解决剩下的问题了 :) 谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-20
    • 2016-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多