Python 现代开发学习笔记

(八)矩形碰撞与离屏移除

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 没被检查。

完整游戏先收集已经离开的障碍,用它们的数量计分,再通过新列表留下仍在区域里的对象。碰撞检查放在离屏与计分之前,快速穿过玩家的障碍不能先被当作成功躲过。

遍历中删除使下一项左移而被跳过,新列表筛选则让每项都被检查一次

笔记正文与全部题解 · Ctrl / ⌘ K