306. 渲染所有 OAM 精灵

把全部 64 个 OAM 精灵渲染进帧缓冲数据。

306 / 356 · tests/chapter_09_sprite_rendering/test_306_render_all_oam_sprites.py

需要更新的文件

emulator/rendering/sprite_renderer.py

为什么需要这一步

我们现在已经可以渲染一个 SpriteEntry。由于 OAMDMA 会向 PPU.oam 填入 64 个精灵条目,下一步就是遍历所有 OAM 条目,把每个精灵渲染进目标帧缓冲。

重要的精灵优先级规则

当精灵重叠时,OAM 索引较小者优先级更高

sprite 0 is in front of sprite 1
sprite 1 is in front of sprite 2
...

由于这个渲染器会修改帧缓冲,应按 OAM 逆序绘制

sprite 63 first
...
sprite 0 last

这样在像素重叠处,索引较小的精灵就会覆盖索引较大的精灵。

建议的实现示例

def render_oam_sprites_to_framebuffer(
    framebuffer: Framebuffer,
    oam: bytes | bytearray,
    pattern_table: bytes,
    sprite_palettes: SpritePalettes,
) -> None:
    if len(oam) < OAM_SIZE:
        raise ValueError("OAM must contain 256 bytes")

    for sprite_index in reversed(range(OAM_SPRITE_COUNT)):
        sprite = decode_sprite_entry(oam, sprite_index)
        render_sprite_8x8_to_framebuffer(
            framebuffer,
            sprite,
            pattern_table,
            sprite_palettes,
        )

本步骤不涉及的内容

  • sprite 0 hit
  • sprite overflow
  • 背景优先级/合成策略
  • 8x16 精灵
  • 逐扫描线的精灵评估
  • pygame

运行本课

uv run pytest tests/chapter_09_sprite_rendering/test_306_render_all_oam_sprites.py -v