285. 手动帧缓冲显示辅助函数

使用 pygame Surface 绘图添加手动帧缓冲显示辅助函数。

285 / 356 · tests/chapter_05_rendering_pipeline/test_285_manual_framebuffer_display_helpers.py

待创建文件

tools/show_framebuffer.py

为什么需要这一步

模拟器核心现在能够产生纯粹的 Framebuffer 数据。在构建完整前端之前,我们希望有一个小的手动工具,能够用 pygame 绘制 Framebuffer 以便进行可视化的冒烟检查。

重要的边界

这个文件放在 tools/ 目录下,因为 pygame 属于前端/手动显示的范畴。

模拟器核心模块不得导入 pygame

emulator/rendering/framebuffer.py
emulator/rendering/nametable_renderer.py
emulator/rendering/ppu_background_renderer.py
emulator/console.py

什么是 pygame Surface?Surface 是由 pygame 管理的可绘制像素缓冲区。由 pygame.display.set_mode(...) 创建的窗口本身也是一个 Surface。

最小示例

surface.fill((255, 0, 0), pygame.Rect(0, 0, 10, 10))

这会用红色填充一个 10x10 的矩形。

draw_framebuffer 的工作方式:

Framebuffer pixel (x, y)
    -> RGB color
    -> pygame Rect(x * scale, y * scale, scale, scale)
    -> surface.fill(color, rect)

建议的实现示例

import pygame

from emulator.rendering.framebuffer import Framebuffer


def make_checkerboard_framebuffer(width: int = 64, height: int = 64) -> Framebuffer:
    framebuffer = Framebuffer(width=width, height=height)

    for y in range(height):
        for x in range(width):
            block_x = x // 8
            block_y = y // 8

            if (block_x + block_y) % 2 == 0:
                framebuffer.set_pixel(x, y, (255, 255, 255))
            else:
                framebuffer.set_pixel(x, y, (40, 40, 40))

    return framebuffer


def draw_framebuffer(
    surface: pygame.Surface,
    framebuffer: Framebuffer,
    scale: int,
) -> None:
    for y in range(framebuffer.height):
        for x in range(framebuffer.width):
            color = framebuffer.get_pixel(x, y)

            rect = pygame.Rect(
                x * scale,
                y * scale,
                scale,
                scale,
            )

            surface.fill(color, rect)

测试策略

这个测试不会打开真正的 pygame 窗口。它使用离屏的 pygame Surface 来验证绘图辅助函数。窗口/主循环部分是单独的一步。

范围之外

  • pygame 主循环
  • pygame.display.set_mode
  • 事件处理
  • 显示 ROM 输出
  • 手柄输入
  • 精灵

运行本课

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