【问题标题】:Collision detection between rectangles (no overlap) - libgdx矩形之间的碰撞检测(无重叠) - libgdx
【发布时间】:2015-06-23 16:46:28
【问题描述】:

我已经在这方面工作了 2-3 周,但我仍然无法进行适当的碰撞检测。我用矩形创建了一个迷宫。我希望我的对象(在矩形中)在我的对象与任何墙壁碰撞时停止并且能够在任何地方移动(或从墙壁上滑下)。我的墙壁(矩形)有如下负坐标:

shapeRenderer.rect(0.9f, 12, 1.15f, 0, Color.RED, Color.RED, Color.RED, Color.RED); //NORTH
shapeRenderer.rect(1, 12, 0, -1.05f, Color.RED, Color.RED, Color.RED, Color.RED); // WEST
shapeRenderer.rect(2, 12, 0, -1.05f, Color.RED, Color.RED, Color.RED, Color.RED); // EAST
shapeRenderer.rect(0.9f, 11, 1.15f, 0, Color.RED, Color.RED, Color.RED, Color.RED); // SOUTH

我目前正在使用我在 SO 中找到的重叠方法。这是我的 CollisionManager 类中的方法:

private boolean overlaps (Rectangle collision, Rectangle wall) {
    return Math.min(collision.x, collision.x + collision.width) 
        < Math.max(wall.x, wall.x + wall.width) 
    && Math.max(collision.x, collision.x + collision.width) 
        > Math.min(wall.x, wall.x + wall.width) 
    && Math.min(collision.y, collision.y + collision.height) 
        < Math.max(wall.y, wall.y + wall.height) 
    && Math.max(collision.y, collision.y + collision.height) 
        > Math.min(wall.y, wall.y + wall.height);
}

我有一个函数可以保存对象所做的所有位置移动。因此,当发生碰撞时,对象会恢复到上一次移动之前的上一次移动(因为最后一次移动是发生碰撞时)(如下示例):

private void overlapsTop(Entity object, Rectangle wall){

    Rectangle r = new Rectangle();
    if(spritePositions.size() != 0){
        r = spritePositions.get(spritePositions.size()-1);
    }
    object.update(r.x, r.y, r.width, r.height);
    object.getObject().setBounds(r.x, r.y, r.width, r.height);
    spritePositions.clear();
}

附加信息:我正在像这样移动我的对象:

public void moveRight(){
    position.x += 1f;
    update();
}

public void update(){

      boundingRectangle.set(position.x, position.y, object.getWidth(), object.getHeight());
}

我卡住的地方是我的重叠功能(我在 SO 中找到的那个)。它适用于大多数情况;但是,例如,如果对象在右侧的墙壁附近移动并触摸它,则该函数将返回 true 并执行所有操作。但是假设我沿着墙壁滑动并直接向下移动并且没有墙壁,对象会停在一点,因为它检测到对象底部和墙壁顶部之间的碰撞(当没有墙壁时)和物体右侧与墙左侧发生碰撞。

我正在尝试为此寻找另一种解决方案。我只希望我的对象停在任何墙壁上并且能够移动(或滑下墙壁)而不会怀疑附近没有墙壁的地方可能会发生碰撞。我觉得我非常接近解决方案,但我需要一些额外的帮助。

更新

我更新了 moveRight 函数和 update 函数。 @Adrian Shum 和 @Matthew Mark Miller 我现在用整数制作了所有内容(意思是我使用 1f 而不是 0.01f)。

因此,我用来移动对象的以下代码是这样的:

if(Gdx.input.isKeyPressed(Keys.RIGHT)){

                 if(collisionManager.canSpriteNotMoveRight(object)){
                     object.stopGoingRight();
                 }else{
                     object.moveRight();
                 }
             }

在我的碰撞管理器类中,函数 stopGoingRight 如下:

public void stopGoingRight(){
    position.x -= 1f;
    update();
}

到目前为止,一切都很好。当物体与墙壁碰撞时,物体会停下并弹回。那挺好的。但是我还有另一个问题(很烦人),我会尽力描述最好的。例如,如果我一直将物体移到墙上,物体会从墙上反弹很多次;如果我停止按向上键,物体有时会卡在墙上。因此发生的情况是当我按下向下键时,它会向上而不是向下(或者如果我按下左键,对象将向右而不是向左移动),因为重叠功能被执行(因为对象和墙相交)。

我有办法解决这个问题吗?似乎 Libgdx 并不完全适合处理这种碰撞检测,但我现在正在深入构建我的游戏。

【问题讨论】:

  • 你控制的矩形可以旋转吗?或者你只是在旋转它的标题?
  • 是的,你可以控制它的旋转。基本上,当您向下、向上、向右或向左移动时,对象会相应地旋转。
  • 只是一个可能有帮助的想法:正如其他人所提到的,这可能是由浮点数的精度问题引起的。如果您知道您的迷宫/运动等将要处理的最小值为 0.01,然后尝试在您的 overlaps 中进行 epsilon 调整(可能使用 0.005),这样就不用写 a &lt; b,而是写a &lt; b-EPSILON
  • 或者,将所有内容设为整数。
  • @CODE。如果负坐标是唯一的问题,那么您可以在检查交叉点之前对垂直或水平或两个方向的两个矩形应用平移,然后在相反方向使用平移。 :)

标签: java libgdx collision-detection collision maze


【解决方案1】:

您的碰撞算法似乎冗长但正确(冗长,因为 x 的最小值,x+ 宽度始终只是 x,因为宽度必须 >= 0,而最大值则相反)。

您是否考虑过它是浮点精度问题的可能性?例如,如果您将 1 添加到 fp 数,然后从结果中删除 1,则不能保证返回原始值。您可能会或多或少,因为中间结果可能无法表示为浮点数。

我最喜欢的例子:.1f + .2f > .3f

【讨论】:

    【解决方案2】:

    感谢以下链接,我终于找到了一个好的解决方案:On overlap, player gets stuck libgdx Rectangle

    基本上我必须创建一个“假”移动来查看对象是否会与墙壁发生碰撞。如果发生碰撞,我只是停止对象而不执行新的移动。

    感谢大家的帮助:)!!非常感谢!

    【讨论】:

      猜你喜欢
      • 2017-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-26
      • 2014-02-07
      • 1970-01-01
      相关资源
      最近更新 更多