NES TDD

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,
        )

Вне рамок этого шага

  • попадание спрайта 0
  • переполнение спрайтов
  • политика приоритета/композитинга фона
  • спрайты 8x16
  • оценка спрайтов по строкам развёртки
  • pygame

Запустить этот урок

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