1

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

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

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

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

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

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

奖励:我也实施了重力 - 或者至少是一个几乎恒定的向下力。以防万一。

4

1 回答 1

2

您的解决方案非常接近。由于您使用 Pygame 的 rects 来处理碰撞,我将为您提供最适合它们的方法。

假设一个 sprite 将与另一个 sprite 重叠多少是不太安全的。在这种情况下,您的碰撞分辨率假定您的精灵之间有一个像素(可能更好地称为“单位”)重叠,而实际上听起来您得到的不止这些。我猜你的玩家精灵一次不会移动一个单位。

然后你需要做的是确定你的玩家与障碍物相交的确切单位数量,并将他移回这么多:

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
于 2013-10-19T03:26:06.087 回答