我会简单而简单。在侧滚动游戏中,我有一个用户控制的精灵,以及一个充当地形的精灵。环境精灵类,理论上可以是地板,天花板或墙壁,取决于它的位置以及玩家与之碰撞的方向,需要做一件事:击退玩家。
如果玩家与环境精灵的顶部发生碰撞,则玩家将停留在顶部边框上。如果玩家跳跃并与环境精灵的底部相撞,他们会停止向上移动并开始下降。逻辑对吗?
我无法理解。我的第一个解决方案有希望说明我的问题(不是实际代码,只是问题区域):
if player.rect.bottom > environment.rect.top:
player.rect.bottom = environment.rect.top - 1
if player.rect.top < environment.rect.bottom:
player.rect.top = environment.rect.bottom + 1
if player.rect.right > environment.rect.left:
etc.
etc.
etc.
这种情况在某些时候效果很好,但是在角落变得非常狡猾,因为每次重叠超过1px意味着玩家的两个或更多边实际上一次与环境精灵碰撞。简而言之,这是我所遇到的每个解决方案所面临的问题。
我潜伏在每个线程,教程,视频,博客,指南,常见问题和帮助网站,我可以合理地,甚至在谷歌上无理地找到,我不知道。当然这是以前有人提出过的问题 - 我知道,我已经看过了。我正在寻找建议,可能是一个链接,只是帮助我克服我只能假设的一个我无法找到的简单解决方案。
如何重新计算相对于任何和所有方向的碰撞精灵的位置?
奖励:我也实施了重力 - 或者至少是一个接近恒定的向下力量。万一重要。
答案 0 :(得分:2)
你的解决方案非常接近。既然你正在使用Pygame的rects来处理碰撞,那么我会为你提供最适合他们的方法。
假设一个精灵会与另一个精灵重叠多少是不太安全的。在这种情况下,你的碰撞分辨率假定你的精灵之间有一个像素(可能更好地称为“单位”)重叠,而事实上它听起来你得到的不止这些。我猜你的玩家精灵一次不会移动一个单位。
你需要做的是确定你的球员与一个障碍物相交的单位的确切数量,并将他移回那么多:
if player.rect.bottom > environment.rect.top:
# Determine how many units the player's rect has gone below the ground.
overlap = player.rect.bottom - environment.rect.top
# Adjust the players sprite by that many units. The player then rests
# exactly on top of the ground.
player.rect.bottom -= overlap
# Move the sprite now so that following if statements are calculated based upon up-to-date information.
if player.rect.top < environment.rect.bottom:
overlap = environment.rect.bottom - player.rect.top
player.rect.top += overlap
# Move the sprite now so that following if statements are calculated based upon up-to-date information.
# And so on for left and right.
这种方法甚至可以在凸角和凹角处起作用。只要你只需要担心两个轴,独立解决每个轴就可以得到你所需要的东西(只要确保你的玩家无法进入他不适合的区域)。考虑这个简短的示例,其中播放器P
与环境E
在一个角落交叉:
Before collision resolution:
--------
| P --|------ --- <-- 100 y
| | | | <-- 4px
-----|-- E | --- <-- 104 y
| |
---------
^
2px
^ ^
90 x 92 x
Collision resolution:
player.rect.bottom > environment.rect.top is True
overlap = 104 - 100 = 4
player.rect.bottom = 104 - 4 = 100
player.rect.right > environment.rect.left is True
overlap = 92 - 90 = 2
player.rect.right = 92 - 2 = 90
After collision resolution:
--------
| P |
| |
---------------- <-- 100 y
| |
| E |
| |
---------
^
90 x