2D 平台游戏 AABB 碰撞问题
我有以下问题AABB 碰撞解决。
我通过首先解析 X 轴,然后解析 Y 轴来解析 AABB 相交。 这样做是为了防止此错误:https://i.sstatic.net/NLg4j.png
当对象移入播放器并且必须水平推动播放器时,当前方法可以正常工作。正如您在 .gif 中看到的,水平尖峰正确地推动玩家。
然而,当垂直尖峰移动到玩家体内时,X 轴仍然首先被解析。这使得“使用钉鞋作为升降机”变得不可能。
当玩家移动到垂直尖峰中时(受重力影响,落入其中),他会在 Y 轴上被推动,因为 X 轴上一开始就没有重叠。
我尝试过的方法是此链接的第一个答案中描述的方法。 然而,尖峰和移动物体通过改变它们的位置而不是速度来移动,并且在调用它们的 Update() 方法之前我不会计算它们的下一个预测位置。 不用说这个解决方案也不起作用。 :(
我需要以上述两种情况都能按预期工作的方式解决 AABB 碰撞。
这是我当前的碰撞源代码: http://pastebin.com/MiCi3nA1
如果有人能够研究这个问题,我将非常感激,因为这个错误从一开始就存在于引擎中,而且我已经一直在努力寻找一个好的解决方案,但没有取得任何成功,这让我花了很多晚上的时间查看碰撞代码,并阻止我进入“有趣的部分”并编写游戏逻辑:(
我尝试实现与在 XNA AppHub 平台游戏演示中(通过复制粘贴大部分内容),但是“跳跃”错误出现在我的游戏中,而它不会出现在 AppHub 演示中。 [ 跳跃 bug: https://i.sstatic.net/NLg4j.png ]
跳跃我检查玩家是否处于“onGround”状态,然后将 -5 添加到 Velocity.Y。
由于玩家的 Velocity.X 高于 Velocity.Y(参见图中的第四个面板),onGround 在不应该设置为 true 的情况下被设置为 true,从而让玩家在半空中跳跃。
我相信这不会发生在 AppHub 演示中,因为玩家的 Velocity.X 永远不会高于 Velocity.Y,但我可能是错的。
我之前通过先解析 X 轴,然后解析 Y 轴来解决这个问题。但这会搞砸与尖峰的碰撞,正如我上面所说的。
I have a problem with AABB collision resolution.
I resolve AABB intersection by resolving the X axis first, then the Y axis.
This is done to prevent this bug: https://i.sstatic.net/NLg4j.png
The current method works fine when an object moves into the player and the player has to be pushed horizontally. As you can see in the .gif, the horizontal spikes push the player correctly.
When the vertical spikes move into the player, however, the X axis is still resolved first. This makes "using the spikes as a lift" impossible.
When the player moves into the vertical spikes (affected by gravity, falls into them), he's pushed on the Y axis, because there was no overlap on the X axis to begin with.
Something I tried was the method described in the first answer of this link.
However the spikes and moving objects move by having their position changed, not velocity, and I don't calculate their next predicted position until their Update() method is called.
Needless to say this solution didn't work either. :(
I need to solve AABB collision in a way that both of the cases described above work as intended.
This is my current collision source code: http://pastebin.com/MiCi3nA1
I'd be really grateful if someone could look into this, since this bug has been present in the engine all the way back from the beginning, and I've been struggling to find a good solution, without any success. This is seriously making me spend nights looking at the collision code and preventing me from getting to the "fun part" and coding the game logic :(
I tried implementing the same collision system as in the XNA AppHub platformer demo (by copy-pasting most of the stuff). However the "jumping" bug occurs in my game, while it doesn't occur in the AppHub demo.
[ jumping bug: https://i.sstatic.net/NLg4j.png ]
To jump I check if the player is "onGround", then add -5 to Velocity.Y.
Since the player's Velocity.X is higher than Velocity.Y (refer to the fourth panel in the diagram), onGround is set to true when it shouldn't be, and thus lets the player jump in mid-air.
I believe this doesn't happen in the AppHub demo because the player's Velocity.X will never be higher than Velocity.Y, but I may be mistaken.
I solved this before by resolving on the X axis first, then on the Y axis. But that screws up the collision with the spikes as I stated above.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
为什么不首先在 Y 轴上解析垂直尖峰,然后在 X 轴上解析水平尖峰?
顺便说一下,图形不错。
据我了解,您正在处理类似这样的运动和碰撞:
这意味着当您执行步骤 (2) 时,您已经忘记了对象 O 移动的方向,因此您无法判断它是试图向上还是向侧面推动玩家。
解决方案:在步骤(1)中,存储每个物体的移动方向。当你发现玩家与某个物体相交时,你可以查看该物体是否向上、向下、向左或向右移动,这将告诉你以哪种方式进行弹射。
Why not resolve on the Y-axis first for vertical spikes, and on the X-axis first for horizontal spikes?
Nice graphic, by the way.
As I understand it, you're handling movement and collision something like this:
This means that when you come to step (2), you have forgotten which way the object O was moving, so you can't tell if it is trying to push the player upwards or sideways.
Solution: in step (1), store for each object the direction it is moving. When you find the player intersecting with an object, you can look to see whether the object is moving up, down, left or right, and that will tell you which way to perform the ejection.
正如 Gareth Rees 所说,问题是检测到碰撞后,您需要更多信息(当前位置以及来自或最后位置的方向)来执行碰撞响应。
如果两个物体都在移动,事情就会变得非常复杂。相反,选择一个物体作为参考系,并从其他物体中减去它的速度。
一个直接的解决方案可能是为非参考框架对象的移动/增量创建线段。然后将这些线段与 4 条 AABB 边相交。这给出了相交时间和相交点的法线。然后您可以应用与现在相同的响应。
As Gareth Rees already said, the issue is after a collision is detected, you need more information (both current location and either direction came from or last position) to perform the collision response.
It gets quite complicated if both objects are moving. Instead, choose one object to be the frame of reference and subtract its velocity from everything else.
A straight forward solution might be to create line segments for the movement/delta of the non-frame-of-reference object. Then intersect those segments with the 4 AABB edges. This gives the time of intersection and the normal at the point of intersection. Then you can apply the same response you have now.
我发现的一种可能的解决方案是在根据玩家的速度进行解析之前对对象进行排序。
One possible solution I found is sorting the objects before resolving based on the velocity of the player.