NES TDD

270. Структура данных фреймбуфера

Создать чистую структуру данных фреймбуфера для конвейера рендеринга.

Урок 270 из 356 · tests/chapter_05_rendering_pipeline/test_270_framebuffer_data_shape.py

Файлы для создания

emulator/rendering/
emulator/rendering/framebuffer.py

Зачем нужен этот шаг

Фаза 7 начинается с определения структуры данных, которую ядро эмулятора будет выдавать для визуального вывода. Это должны быть чистые данные Python, а не данные, специфичные для pygame.

Что такое фреймбуфер? Фреймбуфер — это блок пиксельных данных, представляющий одно законченное изображение/кадр.

Минимальный пример

A 256x240 NES framebuffer contains:

    256 * 240 = 61440 pixels

Каждый пиксель представлен кортежем RGB

    (red, green, blue)

Пример

    BLACK = (0, 0, 0)
    WHITE = (255, 255, 255)

Распространённое заблуждение

Фреймбуфер — это не окно pygame. Фреймбуфер — это данные ядра эмулятора. Pygame позже может его отображать, но pygame не должен требоваться для создания или тестирования фреймбуфера.

Пример предлагаемой реализации

from dataclasses import dataclass, field

RGBColor = tuple[int, int, int]

NES_SCREEN_WIDTH = 256
NES_SCREEN_HEIGHT = 240
BLACK: RGBColor = (0, 0, 0)


@dataclass
class Framebuffer:
    width: int = NES_SCREEN_WIDTH
    height: int = NES_SCREEN_HEIGHT
    pixels: list[RGBColor] = field(default_factory=list)

    def __post_init__(self) -> None:
        if not self.pixels:
            self.pixels = [BLACK] * (self.width * self.height)

        if len(self.pixels) != self.width * self.height:
            raise ValueError("Framebuffer pixel count must be equal width * height")

Важный инвариант

После создания

len(framebuffer.pixels) == framebuffer.width * framebuffer.height

Выходит за рамки

  • методы get_pixel/set_pixel, тестируемые на следующем шаге
  • проверка координат
  • проверка компонентов RGB
  • преобразование индексов палитры NES в RGB
  • рендеринг данных CHR/nametable
  • отображение pygame/фронтенда

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

uv run pytest tests/chapter_05_rendering_pipeline/test_270_framebuffer_data_shape.py -v