Pygame - 防止Sprite重叠

时间:2013-10-18 18:01:56

标签: python pygame sprite

我会简单而简单。在侧滚动游戏中,我有一个用户控制的精灵,以及一个充当地形的精灵。环境精灵类,理论上可以是地板,天花板或墙壁,取决于它的位置以及玩家与之碰撞的方向,需要做一件事:击退玩家。

如果玩家与环境精灵的顶部发生碰撞,则玩家将停留在顶部边框上。如果玩家跳跃并与环境精灵的底部相撞,他们会停止向上移动并开始下降。逻辑对吗?

我无法理解。我的第一个解决方案有希望说明我的问题(不是实际代码,只是问题区域):

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意味着玩家的两个或更多边实际上一次与环境精灵碰撞。简而言之,这是我所遇到的每个解决方案所面临的问题。

我潜伏在每个线程,教程,视频,博客,指南,常见问题和帮助网站,我可以合理地,甚至在谷歌上无理地找到,我不知道。当然这是以前有人提出过的问题 - 我知道,我已经看过了。我正在寻找建议,可能是一个链接,只是帮助我克服我只能假设的一个我无法找到的简单解决方案。

如何重新计算相对于任何和所有方向的碰撞精灵的位置?

奖励:我也实施了重力 - 或者至少是一个接近恒定的向下力量。万一重要。

1 个答案:

答案 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