(八)矩形碰撞与离屏移除
1. 接触与正面积重叠
# 项目文件:demos/rect_collision.py
# 右边与左边恰好相等只表示接触;向左移动1像素后才出现正面积重叠。
import pygame
player = pygame.Rect(100, 110, 48, 24)
obstacle = pygame.Rect(148, 110, 30, 24)
print("共边", player.colliderect(obstacle))
obstacle.move_ip(-1, 0)
print("重叠1像素", player.colliderect(obstacle))
print("右边点", player.collidepoint((148, 120)))第一次得到 共边 False,左移 1 像素后得到 重叠1像素 True。玩家矩形覆盖 x 为 100 至 147 的整数像素,right 为 148;障碍从 x=148 开始时只是共边。示例最后的点 x=148 也没有落入玩家内部。
碰撞框表达的是矩形区域,后面图像中的透明角和具体形状还可以用像素掩码细分。先看清几何判断,再决定碰撞形状。
2. 移除对象时保留下一项检查
障碍离开画面后需要移除。下面先展示遍历中删除会发生的跳项:
# 项目文件:demos/remove_filter.py
# 错误示例:遍历时删除导致下一项左移并被跳过;筛选新列表一次保留需要的项。
records = [{"id": 1, "y": 700}, {"id": 2, "y": 720}, {"id": 3, "y": 20}]
bad = records.copy()
for item in bad:
if item["y"] >= 600:
bad.remove(item)
good = [item for item in records if item["y"] < 600]
print("错误剩余", [item["id"] for item in bad])
print("筛选剩余", [item["id"] for item in good])错误结果剩下编号 [2, 3],筛选结果只剩 [3]。删掉第一项后,原来的第二项移到前一个位置,而遍历继续去下一个位置,所以编号 2 没被检查。
完整游戏先收集已经离开的障碍,用它们的数量计分,再通过新列表留下仍在区域里的对象。碰撞检查放在离屏与计分之前,快速穿过玩家的障碍不能先被当作成功躲过。