在 Pygame 中,有一个侧滚动的游戏,其中有一个精灵由用户控制,另一个精灵作为地形。环境精灵类从理论上讲可以是地板、天花板或墙壁,具体取决于它的位置以及玩家与它的碰撞方向,需要做一件事: 击退玩家。
如果玩家与环境精灵的顶部碰撞,则玩家停留在顶部边界。如果玩家跳跃并与环境精灵的底部碰撞,则他们停止向上移动并开始下降。逻辑正确吗? 目前无法解决这个问题。第一个解决方案希望说明问题(不是实际代码,只是问题所在):
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.
有时这样做很好,但角落在某处变得非常危险,因为每次超过 1 像素的重叠意味着玩家的两边或多边实际上同时与环境精灵发生碰撞。简单来说,这是尝试过的每个解决方案都面临的问题。
已经浏览了谷歌上合理甚至不合理地找到的每个线程、教程、视频、博客、指南、常见问题解答和帮助站点,但不知道答案。当然有人解决过这个问题,曾经见过。正在寻找建议,可能是一个链接,只要能帮助找到一个简单的解决方案,就足够了。
如何根据任何方向重新计算碰撞精灵的位置?
奖励: 也实现了重力,或者至少是近乎恒定的向下力。以防这个问题重要。
2、解决方案
解决方法非常接近。由于使用的是 Pygame 的矩形来处理碰撞,因此将提供最适合它们的方法。
假设一个精灵将重叠另一个精灵多少是不安全的。在这种情况下,碰撞解决假设精灵之间有一个像素(可能更好地称为“单位”)重叠,但听起来好像获得的不仅仅是这些。猜测玩家精灵不会一次移动一个单位。
那么需要做的是确定玩家与障碍物相交的确切单位数,并按此数目将其移回:
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 在一个角处相交:
碰撞解决之前:
--------
| P --|------ --- <-- 100 y
| | | | <-- 4px
-----|-- E | --- <-- 104 y
| |
---------
^
2px
^ ^
90 x 92 x
碰撞解决:
player.rect.bottom > environment.rect.top 为 True
overlap = 104 - 100 = 4
player.rect.bottom = 104 - 4 = 100
player.rect.right > environment.rect.left 为 True
overlap = 92 - 90 = 2
player.rect.right = 92 - 2 = 90
碰撞解决之后:
--------
| P |
| |
---------------- <-- 100 y
| |
| E |
| |
---------
^
90 x