在游戏中无法获得可靠的碰撞检测/响应

所以,我现在有一个更新的玩家位置的矩形,是精灵的大小。 我使用Tiled作为我的瓷砖编辑器,并且有一个名为“collision”的对象层,我在加载地图时将其循环,并将每个对象作为Rectangle存储在列表中。 然后在我的更新中,我检查玩家是否与任何矩形(通过循环列表)碰撞与Rectangle.Intersects(矩形)。 如果检测到碰撞,我用这个函数处理它:

private static void HandleCollision() { if (_currentLevel.IsCollisionTile()) { float deltaLeft = Math.Abs((Player.Instance.Position.X + Player.Instance.PlayerCollider.Width) - (_currentLevel.collidingRectangle.X)); float deltaRight = Math.Abs((Player.Instance.Position.X) + (_currentLevel.collidingRectangle.X + _currentLevel.collidingRectangle.Width)); float deltaUp = Math.Abs((Player.Instance.Position.Y + Player.Instance.PlayerCollider.Height) - (_currentLevel.collidingRectangle.Y)); float deltaDown = Math.Abs((Player.Instance.Position.Y) - (_currentLevel.collidingRectangle.Y + _currentLevel.collidingRectangle.Height)); if (deltaLeft < deltaRight && deltaLeft < deltaUp && deltaLeft < deltaDown) { Player.Instance.Position.X -= deltaLeft; } else if (deltaRight < deltaLeft && deltaRight < deltaUp && deltaRight < deltaDown) { Player.Instance.Position.X += deltaRight; } else if (deltaUp < deltaLeft && deltaUp < deltaRight && deltaUp < deltaDown) { Player.Instance.Position.Y -= deltaUp; } else if (deltaDown < deltaLeft && deltaDown < deltaRight && deltaDown < deltaUp) { Player.Instance.Position.Y += deltaDown; } } } 

我知道这是丑陋的,但这不是问题,问题是,当它发现一个碰撞时,玩家“spa”“,只是在它碰撞的矩形中跳出和跳出。 我也尝试过其他两种方法,比如只使用绝对值设置玩家位置,并进行类似的计算。 虽然同样的问题发生。 而且它也允许玩家只从一侧穿过平台,玩家有时会被传送到另一边,所以这非常糟糕。

我不知道该怎么处理它,我已经做了很多search和search,以及在这里search,但是我发现的一切都是关于实际的碰撞检测,我通过Rectangle.Intersects()方法。 我已经在这里呆了3-4天,然后决定在这里发帖。

当然,它会反弹。 你正在这样做:

  • 使用Monogame API调用检测矩形交集(这只会告诉您发生交集)
  • 使玩家回到瓦片矩形前/后

这种方法的问题在于无论发生碰撞的地方,玩家将被推向相同的宽度/高度。 随着玩家的x / y最常见的实施方式每帧更新一定量的像素/更新,取决于运动的速度和起始位置,当玩家在瓦片内5个像素时,可以检测到碰撞,3个像素在瓦片内部,瓦片内部14个像素,或者根本不被检测到,例如,玩家在x = 5,瓦片在x = 22,瓦片和玩家盒子是16×16,并且你设置速度为每帧40个像素,导致玩家通过瓦片而没有检测到碰撞,因为玩家在5个一帧,在45个下一个帧。

[animationgif这里]

快速修复

计算玩家矩形的穿透向量到矩形的矩形中。 通过将玩家向后移动穿透vector而不是游戏区宽度,玩家将被拒绝并且离开游戏区域。

这种方法有基于瓦片的地图的问题,你需要以某种方式解决,但你现在有一个起点。 尝试适应您的需求。

这是你想要的: https : //vimeo.com/64923588

只要我们在轴alignment边界框(AABB)的土地上,渗透vector的公式很简单:

 TX = Player.x - Tile.x; TY = Player.y - Tile.y; 

但是你只能按照绝对值更大的方向推动玩家。

阅读更多有关AABB的渗透vector: http : //hamaluik.com/posts/simple-aabb-collision-using-minkowski-difference/

可能的解决scheme:“玩家卡在瓷砖之间”或者“玩家从整个瓷砖线推出”:

  • 只有在玩家下方没有平台的情况下才能使用重力(无论如何,谁还需要真实的物理?)。
  • 做到这一点: 使用AABB的碰撞检测问题

“如果移动速度太快,玩家仍然会错过平铺”的可能解决scheme:

  • 不要让玩家移动更多的像素,每帧,比瓷砖宽度(只有当你有一个恒定的瓷砖宽度)。
  • 使用更复杂的AABB碰撞/穿透检测来解释移动AABB: http ://www.gamasutra.com/view/feature/131790/simple_intersection_tests_for_games.php?page =3