IMX6U-Game/docs/APP_AND_CORE_ARCHITECTURE.md

4.7 KiB
Raw Blame History

应用层与 Core 分层设计

本文记录当前项目的代码分层。src/Core 是可复用底层库,src/Apps 放具体应用和游戏。

目录边界

src/
  Core/                 # 底层库:渲染、数学、资源、平台适配
    Asset/              # 离线资源格式加载
    Core/               # FrameBuffer、DepthBuffer、Renderer、Timer
    Draw2D/             # Core::DrawContext
    Math/               # Vector、Matrix、MathUtil
    Platform/           # 显示、时间、音频、按键等平台接口和后端
    Rasterizer/         # 线段和三角形光栅化
    RenderData/         # Color、Image、Triangle、Tilemap 等数据结构
    Scene/              # Camera、Transform、Mesh、Model
    Shading/            # Shader 相关代码
  Apps/
    Demo/               # Core 能力演示
    Game/               # Tom 游戏

src/Core/Core 这个二级目录保留的是原底层库里的核心运行时对象。它和顶层 src/Core 名称重复,但含义不同:

  • src/Core:整个底层库。
  • src/Core/Core:底层库内部的 framebuffer、depthbuffer、timer 等核心对象。

后续如果觉得重复命名影响阅读,可以再把 src/Core/Core 单独改成 Runtime/Buffer/,但这次先只做旧底层库名称到 Core 的一致性修复。

依赖方向

允许:

Apps -> Shared -> Core -> Platform
Apps -> Core

禁止:

Core -> Apps
Core -> Shared
GameA -> GameB
GameB -> GameA
Platform -> Game

Core 层不应该知道具体游戏规则、场景流程、角色状态机、关卡数据或游戏专属资源路径。

Core 职责

Core 只提供底层能力:

  • 管理 FrameBufferDepthBuffer 和绘制上下文。
  • 提供基础绘制接口line、triangle、sprite、sprite region、tilemap、bitmap font。
  • 提供基础数学、颜色、图片、三角形、tilemap 等数据结构。
  • 封装 SDL2 / framebuffer 显示提交。
  • 提供独立时间源 Platform::ITimeSource
  • 提供音频输入、音频输出和按键输入的抽象接口。
  • 使用离线转换后的运行时资源,不在热路径解码 PNG/TTF。

Core 不做:

  • 不实现具体游戏规则。
  • 不直接读取某个游戏专属资源目录。
  • 不在核心绘制接口暴露 SDL2 类型。
  • 不在每帧热路径中执行图片、字体解码或文件 IO。

应用职责

src/Apps/* 负责具体应用流程:

  • 创建具体游戏或 Demo 的主循环。
  • 加载应用自己的资源。
  • 调用 Core::DrawContext 绘制画面。
  • 根据平台输入更新游戏状态。

当前主程序位于:

src/Apps/Game/Main.cpp

它默认启动 Tom 游戏视觉入口。

DrawContext

Core::DrawContext 是当前统一绘制入口,位于:

src/Core/Draw2D/DrawContext.h
src/Core/Draw2D/DrawContext.cpp

它封装:

  • Core::FrameBuffer
  • Core::DepthBuffer
  • Rasterizer::Rasterizer
  • Rasterizer::TriangleRasterizer

对外提供:

Core::DrawContext ctx(width, height);
ctx.clear(RenderData::Color(18, 18, 24, 255));
ctx.draw_sprite(x, y, image);
ctx.draw_text(font, x, y, color, "text");
ctx.present(display);

显示后端

平台层采用“抽象接口 + 多套后端实现”的模式。

显示层通过 Platform::IDisplay 抽象:

Platform::IDisplay
  SDLDisplay   # PC / SDL2 调试后端
  FBDisplay    # Linux /dev/fb0 后端

音频输入通过 Platform::IAudioInput 抽象:

Platform::IAudioInput
  SdlAudioInput    # PC / SDL2 麦克风后端
  AlsaAudioInput   # Linux ALSA 录音后端

音频输出通过 Platform::IAudioOutput 抽象:

Platform::IAudioOutput
  SdlAudioOutput   # PC / SDL2 扬声器后端
  AlsaAudioOutput  # Linux ALSA 播放后端

按键输入通过 Platform::IButtonInput 抽象:

Platform::IButtonInput
  SdlKeyboardButtonInput # PC / SDL2 键盘后端,默认空格键
  EvdevButtonInput # Linux evdev 按键后端

游戏代码只能依赖这些 I* 接口。ALSA、evdev、SDL2、/dev/fb0 等平台细节只能出现在 src/Core/Platform 或明确的平台适配代码中。 如果只需要当前构建平台的默认后端,可以使用 Platform::DefaultAudioInputPlatform::DefaultAudioOutputPlatform::DefaultButtonInput

CMake 通过 USE_FRAMEBUFFER 选择实现:

-DUSE_FRAMEBUFFER=OFF  # 默认,使用 SDLDisplay
-DUSE_FRAMEBUFFER=ON   # 使用 FBDisplay

后续建议

  1. 保持 Core 不依赖 Apps
  2. 新增游戏逻辑放在 src/Apps/Game 或新的 src/Apps/*
  3. 新增底层绘制、数学、资源格式、平台显示能力放在 src/Core
  4. 如果继续清理命名,优先处理 src/Core/Core 这个重复目录名。