2026-02-15 10:11:09 +08:00
|
|
|
|
# Extra2D 模块系统
|
|
|
|
|
|
|
|
|
|
|
|
## 概述
|
|
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
Extra2D 采用模块化架构设计,核心功能通过**模块系统**和**服务系统**管理:
|
2026-02-15 10:11:09 +08:00
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
- **模块 (Module)**: 平台级初始化,管理硬件资源(窗口、渲染、输入)
|
|
|
|
|
|
- **服务 (Service)**: 运行时功能,通过服务定位器管理(场景、计时器、事件、相机)
|
2026-02-15 10:11:09 +08:00
|
|
|
|
|
|
|
|
|
|
## 架构图
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ Application │
|
2026-02-17 23:57:50 +08:00
|
|
|
|
│ (协调模块和服务,通过服务定位器获取依赖) │
|
2026-02-15 10:11:09 +08:00
|
|
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
|
|
|
│
|
2026-02-15 12:36:36 +08:00
|
|
|
|
┌───────────────┴───────────────┐
|
|
|
|
|
|
▼ ▼
|
|
|
|
|
|
┌─────────────────────────────┐ ┌─────────────────────────────┐
|
2026-02-17 23:57:50 +08:00
|
|
|
|
│ 模块系统 │ │ 服务系统 │
|
|
|
|
|
|
│ (Module - 硬件资源) │ │ (Service - 运行时功能) │
|
|
|
|
|
|
├─────────────────────────────┤ ├─────────────────────────────┤
|
|
|
|
|
|
│ ┌─────────┐ ┌─────────┐ │ │ ┌─────────┐ ┌─────────┐ │
|
|
|
|
|
|
│ │ Window │ │ Render │ │ │ │ Logger │ │ Scene │ │
|
|
|
|
|
|
│ │ Module │ │ Module │ │ │ │ Service │ │ Service │ │
|
|
|
|
|
|
│ │ P0 │ │ P10 │ │ │ │ │ │ │ │
|
|
|
|
|
|
│ └─────────┘ └─────────┘ │ │ └─────────┘ └─────────┘ │
|
|
|
|
|
|
│ ┌─────────┐ │ │ ┌─────────┐ ┌─────────┐ │
|
|
|
|
|
|
│ │ Input │ │ │ │ Timer │ │ Event │ │
|
|
|
|
|
|
│ │ Module │ │ │ │ Service │ │ Service │ │
|
|
|
|
|
|
│ │ P20 │ │ │ │ │ │ │ │
|
|
|
|
|
|
│ └─────────┘ │ │ └─────────┘ └─────────┘ │
|
|
|
|
|
|
│ │ │ ┌─────────┐ │
|
|
|
|
|
|
│ │ │ │ Camera │ │
|
|
|
|
|
|
│ │ │ │ Service │ │
|
|
|
|
|
|
│ │ │ │ │ │
|
|
|
|
|
|
│ │ │ └─────────┘ │
|
2026-02-15 12:36:36 +08:00
|
|
|
|
└─────────────────────────────┘ └─────────────────────────────┘
|
2026-02-15 10:11:09 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-15 12:36:36 +08:00
|
|
|
|
## 模块 vs 服务
|
|
|
|
|
|
|
|
|
|
|
|
| 特性 | 模块 (Module) | 服务 (Service) |
|
|
|
|
|
|
|-----|--------------|---------------|
|
|
|
|
|
|
| 用途 | 平台级初始化 | 运行时功能 |
|
|
|
|
|
|
| 生命周期 | Application 管理 | ServiceLocator 管理 |
|
2026-02-17 23:57:50 +08:00
|
|
|
|
| 依赖方式 | 通过 `deps()` 方法声明 | 通过 `ServiceLocator` 获取 |
|
2026-02-15 12:36:36 +08:00
|
|
|
|
| 可替换性 | 编译时确定 | 运行时可替换 |
|
2026-02-15 13:32:42 +08:00
|
|
|
|
| 示例 | Window, Render, Input | Scene, Timer, Event, Camera |
|
2026-02-15 12:36:36 +08:00
|
|
|
|
|
|
|
|
|
|
## 模块系统
|
2026-02-15 10:11:09 +08:00
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
### 模块基类
|
2026-02-15 10:11:09 +08:00
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
所有模块继承自 `Module` 基类:
|
2026-02-15 10:11:09 +08:00
|
|
|
|
|
|
|
|
|
|
```cpp
|
2026-02-17 23:57:50 +08:00
|
|
|
|
class Module {
|
2026-02-15 10:11:09 +08:00
|
|
|
|
public:
|
2026-02-17 23:57:50 +08:00
|
|
|
|
virtual ~Module() = default;
|
|
|
|
|
|
virtual bool init() = 0; // 初始化
|
|
|
|
|
|
virtual void shutdown() = 0; // 关闭
|
|
|
|
|
|
virtual bool ok() const = 0; // 检查状态
|
|
|
|
|
|
virtual const char* name() const = 0; // 模块名称
|
|
|
|
|
|
virtual int priority() const { return 100; } // 优先级(越小越优先)
|
|
|
|
|
|
virtual std::vector<std::type_index> deps() const { return {}; } // 依赖
|
|
|
|
|
|
void setApp(Application* app) { app_ = app; }
|
|
|
|
|
|
Application* app() const { return app_; }
|
|
|
|
|
|
protected:
|
|
|
|
|
|
Application* app_ = nullptr;
|
2026-02-15 10:11:09 +08:00
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
### 内置模块
|
2026-02-15 10:11:09 +08:00
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
| 模块 | 优先级 | 依赖 | 职责 |
|
|
|
|
|
|
|-----|-------|------|------|
|
|
|
|
|
|
| WindowModule | 0 | 无 | 窗口创建和管理 |
|
|
|
|
|
|
| RenderModule | 10 | WindowModule | 渲染后端初始化 |
|
|
|
|
|
|
| InputModule | 20 | WindowModule | 输入设备管理 |
|
2026-02-15 10:11:09 +08:00
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
### 模块配置
|
2026-02-15 10:11:09 +08:00
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
每个模块有自己的配置结构:
|
2026-02-15 10:11:09 +08:00
|
|
|
|
|
|
|
|
|
|
```cpp
|
2026-02-17 23:57:50 +08:00
|
|
|
|
// Window 模块配置
|
|
|
|
|
|
struct WindowCfg {
|
|
|
|
|
|
std::string title = "Extra2D";
|
|
|
|
|
|
int w = 1280;
|
|
|
|
|
|
int h = 720;
|
|
|
|
|
|
WindowMode mode = WindowMode::Windowed;
|
|
|
|
|
|
bool vsync = true;
|
|
|
|
|
|
int priority = 0;
|
|
|
|
|
|
std::string backend = "sdl2"; // "sdl2" 或 "glfw"
|
2026-02-15 12:36:36 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
// Render 模块配置
|
|
|
|
|
|
struct RenderCfg {
|
|
|
|
|
|
BackendType backend = BackendType::OpenGL;
|
|
|
|
|
|
int targetFPS = 60;
|
|
|
|
|
|
bool vsync = true;
|
|
|
|
|
|
int multisamples = 0;
|
|
|
|
|
|
int priority = 10;
|
2026-02-15 10:11:09 +08:00
|
|
|
|
};
|
2026-02-15 13:32:42 +08:00
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
// Input 模块配置
|
|
|
|
|
|
struct InputCfg {
|
|
|
|
|
|
float deadzone = 0.15f;
|
|
|
|
|
|
float mouseSensitivity = 1.0f;
|
|
|
|
|
|
bool enableVibration = true;
|
|
|
|
|
|
int maxGamepads = 4;
|
|
|
|
|
|
int priority = 20;
|
2026-02-15 10:11:09 +08:00
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
### 使用模块
|
2026-02-15 10:11:09 +08:00
|
|
|
|
|
|
|
|
|
|
```cpp
|
2026-02-17 23:57:50 +08:00
|
|
|
|
Application app;
|
2026-02-15 13:32:42 +08:00
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
// 配置 Window 模块
|
2026-02-17 00:34:14 +08:00
|
|
|
|
app.use<WindowModule>([](auto& cfg) {
|
2026-02-17 23:57:50 +08:00
|
|
|
|
cfg.title = "My Game";
|
|
|
|
|
|
cfg.w = 1920;
|
|
|
|
|
|
cfg.h = 1080;
|
|
|
|
|
|
cfg.backend = "glfw"; // 使用 GLFW 后端
|
2026-02-17 00:34:14 +08:00
|
|
|
|
});
|
2026-02-15 10:11:09 +08:00
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
// 配置 Render 模块
|
|
|
|
|
|
app.use<RenderModule>([](auto& cfg) {
|
|
|
|
|
|
cfg.backend = BackendType::OpenGL;
|
|
|
|
|
|
cfg.vsync = true;
|
|
|
|
|
|
cfg.targetFPS = 60;
|
|
|
|
|
|
});
|
2026-02-15 10:11:09 +08:00
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
// 配置 Input 模块
|
2026-02-17 00:34:14 +08:00
|
|
|
|
app.use<InputModule>([](auto& cfg) {
|
2026-02-17 23:57:50 +08:00
|
|
|
|
cfg.deadzone = 0.2f;
|
2026-02-17 00:34:14 +08:00
|
|
|
|
cfg.enableVibration = true;
|
|
|
|
|
|
});
|
2026-02-15 13:32:42 +08:00
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
app.run();
|
2026-02-15 10:11:09 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
### 构建时选择后端
|
2026-02-15 10:11:09 +08:00
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
```bash
|
|
|
|
|
|
# 选择窗口后端
|
|
|
|
|
|
xmake f --window_backend=sdl2 -y # 使用 SDL2(默认)
|
|
|
|
|
|
xmake f --window_backend=glfw -y # 使用 GLFW
|
2026-02-15 10:11:09 +08:00
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
# 选择渲染后端
|
|
|
|
|
|
xmake f --render_backend=opengl -y # 使用 OpenGL(默认)
|
|
|
|
|
|
xmake f --render_backend=vulkan -y # 使用 Vulkan
|
2026-02-15 10:11:09 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-15 13:32:42 +08:00
|
|
|
|
## 服务系统
|
2026-02-15 10:11:09 +08:00
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
### 服务接口基类
|
2026-02-15 10:11:09 +08:00
|
|
|
|
|
2026-02-15 12:36:36 +08:00
|
|
|
|
```cpp
|
2026-02-15 13:32:42 +08:00
|
|
|
|
class IService {
|
|
|
|
|
|
public:
|
|
|
|
|
|
virtual ~IService() = default;
|
|
|
|
|
|
virtual ServiceInfo getServiceInfo() const = 0;
|
|
|
|
|
|
virtual bool initialize() = 0;
|
|
|
|
|
|
virtual void shutdown() = 0;
|
2026-02-17 23:57:50 +08:00
|
|
|
|
virtual void update(float deltaTime) {}
|
|
|
|
|
|
virtual bool isInitialized() const = 0;
|
2026-02-15 12:36:36 +08:00
|
|
|
|
};
|
2026-02-15 13:32:42 +08:00
|
|
|
|
```
|
2026-02-15 10:11:09 +08:00
|
|
|
|
|
2026-02-15 13:32:42 +08:00
|
|
|
|
### 内置服务
|
|
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
| 服务 | 用途 | 自动注册宏 |
|
|
|
|
|
|
|-----|------|-----------|
|
|
|
|
|
|
| LoggerService | 日志记录 | `E2D_AUTO_REGISTER_SERVICE(ILogger, ConsoleLogger)` |
|
|
|
|
|
|
| SceneService | 场景管理 | `E2D_AUTO_REGISTER_SERVICE(ISceneService, SceneService)` |
|
|
|
|
|
|
| TimerService | 计时器 | `E2D_AUTO_REGISTER_SERVICE(ITimerService, TimerService)` |
|
|
|
|
|
|
| EventService | 事件分发 | `E2D_AUTO_REGISTER_SERVICE(IEventService, EventService)` |
|
|
|
|
|
|
| CameraService | 相机系统 | `E2D_AUTO_REGISTER_SERVICE(ICameraService, CameraService)` |
|
2026-02-15 13:32:42 +08:00
|
|
|
|
|
|
|
|
|
|
### 使用服务
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// 获取服务
|
2026-02-17 23:57:50 +08:00
|
|
|
|
auto logger = app.logger();
|
|
|
|
|
|
auto sceneService = app.scenes();
|
|
|
|
|
|
auto timerService = app.timers();
|
|
|
|
|
|
auto eventService = app.events();
|
|
|
|
|
|
auto cameraService = app.camera();
|
|
|
|
|
|
|
|
|
|
|
|
// 使用日志服务
|
|
|
|
|
|
logger->info("Application started");
|
|
|
|
|
|
logger->setLevel(LogLevel::Debug);
|
|
|
|
|
|
E2D_LOG_INFO("Player position: {}, {}", x, y);
|
|
|
|
|
|
E2D_LOG_ERROR("Failed to load texture: {}", filepath);
|
2026-02-15 13:32:42 +08:00
|
|
|
|
|
|
|
|
|
|
// 使用场景服务
|
|
|
|
|
|
sceneService->pushScene(myScene);
|
|
|
|
|
|
|
|
|
|
|
|
// 使用计时器服务
|
|
|
|
|
|
timerService->addTimer(1.0f, []() {
|
|
|
|
|
|
E2D_LOG_INFO("Timer fired!");
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 使用事件服务
|
|
|
|
|
|
eventService->addListener(EventType::KeyPressed, [](Event& e) {
|
|
|
|
|
|
auto& keyEvent = std::get<KeyEvent>(e.data);
|
|
|
|
|
|
E2D_LOG_INFO("Key pressed: {}", keyEvent.keyCode);
|
|
|
|
|
|
});
|
2026-02-17 23:57:50 +08:00
|
|
|
|
|
|
|
|
|
|
// 使用相机服务
|
|
|
|
|
|
cameraService->setPosition(100, 100);
|
|
|
|
|
|
cameraService->setZoom(2.0f);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 渲染后端
|
|
|
|
|
|
|
|
|
|
|
|
### 支持的后端
|
|
|
|
|
|
|
|
|
|
|
|
| 后端 | 状态 | 平台支持 |
|
|
|
|
|
|
|-----|------|---------|
|
|
|
|
|
|
| OpenGL | 完整实现 | Windows, Linux, macOS, Switch |
|
|
|
|
|
|
| Vulkan | 计划中 | Windows, Linux, macOS, Switch |
|
|
|
|
|
|
|
|
|
|
|
|
### 渲染后端接口
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
2026-02-20 15:04:21 +08:00
|
|
|
|
class Renderer {
|
2026-02-17 23:57:50 +08:00
|
|
|
|
public:
|
2026-02-20 15:04:21 +08:00
|
|
|
|
virtual ~Renderer() = default;
|
2026-02-17 23:57:50 +08:00
|
|
|
|
|
|
|
|
|
|
// 生命周期
|
|
|
|
|
|
virtual bool init(IWindow* window) = 0;
|
|
|
|
|
|
virtual void shutdown() = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 帧管理
|
|
|
|
|
|
virtual void beginFrame(const Color &clearColor) = 0;
|
|
|
|
|
|
virtual void endFrame() = 0;
|
|
|
|
|
|
virtual void setViewport(int x, int y, int width, int height) = 0;
|
|
|
|
|
|
virtual void setVSync(bool enabled) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 状态设置
|
|
|
|
|
|
virtual void setBlendMode(BlendMode mode) = 0;
|
|
|
|
|
|
virtual void setViewProjection(const glm::mat4 &matrix) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 变换矩阵栈
|
|
|
|
|
|
virtual void pushTransform(const glm::mat4 &transform) = 0;
|
|
|
|
|
|
virtual void popTransform() = 0;
|
|
|
|
|
|
virtual glm::mat4 getCurrentTransform() const = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 纹理
|
|
|
|
|
|
virtual Ptr<Texture> createTexture(int width, int height, const uint8_t *pixels, int channels) = 0;
|
|
|
|
|
|
virtual Ptr<Texture> loadTexture(const std::string &filepath) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 精灵批处理
|
|
|
|
|
|
virtual void beginSpriteBatch() = 0;
|
|
|
|
|
|
virtual void drawSprite(const Texture &texture, const Rect &destRect, const Rect &srcRect,
|
|
|
|
|
|
const Color &tint, float rotation, const Vec2 &anchor) = 0;
|
|
|
|
|
|
virtual void endSpriteBatch() = 0;
|
|
|
|
|
|
virtual void flush() = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 形状渲染
|
|
|
|
|
|
virtual void drawLine(const Vec2 &start, const Vec2 &end, const Color &color, float width = 1.0f) = 0;
|
|
|
|
|
|
virtual void drawRect(const Rect &rect, const Color &color, float width = 1.0f) = 0;
|
|
|
|
|
|
virtual void fillRect(const Rect &rect, const Color &color) = 0;
|
|
|
|
|
|
virtual void drawCircle(const Vec2 ¢er, float radius, const Color &color,
|
|
|
|
|
|
int segments = 32, float width = 1.0f) = 0;
|
|
|
|
|
|
virtual void fillCircle(const Vec2 ¢er, float radius, const Color &color, int segments = 32) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 文字渲染
|
|
|
|
|
|
virtual Ptr<FontAtlas> createFontAtlas(const std::string &filepath, int fontSize, bool useSDF = false) = 0;
|
|
|
|
|
|
virtual void drawText(const FontAtlas &font, const std::string &text, const Vec2 &position, const Color &color) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 工厂方法
|
2026-02-20 15:04:21 +08:00
|
|
|
|
static UniquePtr<Renderer> create(BackendType type);
|
2026-02-17 23:57:50 +08:00
|
|
|
|
};
|
2026-02-15 13:32:42 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
## 资源抽象层
|
|
|
|
|
|
|
|
|
|
|
|
渲染后端通过资源抽象层实现跨平台兼容:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ 前端 (Frontend) │
|
|
|
|
|
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
|
|
|
|
|
|
│ │ Renderer │ │ SpriteBatch │ │ 其他 │ │
|
|
|
|
|
|
│ └──────┬──────┘ └──────┬──────┘ └─────────────────────┘ │
|
|
|
|
|
|
└─────────┼────────────────┼──────────────────────────────────┘
|
|
|
|
|
|
│ │
|
|
|
|
|
|
▼ ▼
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ 资源抽象层 (resources/) │
|
|
|
|
|
|
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
|
|
|
|
|
│ │ Buffer │ │ Pipeline │ │ Framebuf │ │ Shader │ │
|
|
|
|
|
|
│ │ (缓冲区) │ │ (管线) │ │(帧缓冲) │ │ (着色器) │ │
|
|
|
|
|
|
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
|
|
|
|
|
│ ┌──────────┐ ┌──────────┐ │
|
|
|
|
|
|
│ │ Texture │ │ FontAtlas│ │
|
|
|
|
|
|
│ │ (纹理) │ │(字体图集)│ │
|
|
|
|
|
|
│ └──────────┘ └──────────┘ │
|
|
|
|
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ 后端实现 (backends/) │
|
|
|
|
|
|
│ ┌─────────────────┐ ┌─────────────────┐ │
|
|
|
|
|
|
│ │ OpenGL │ │ Vulkan │ │
|
|
|
|
|
|
│ │ GLBuffer │ │ VKBuffer │ │
|
|
|
|
|
|
│ │ GLPipeline │ │ VKPipeline │ │
|
|
|
|
|
|
│ │ GLFramebuffer │ │ VKFramebuffer │ │
|
|
|
|
|
|
│ │ GLShader │ │ VKShader │ │
|
|
|
|
|
|
│ │ GLTexture │ │ VKTexture │ │
|
|
|
|
|
|
│ └─────────────────┘ └─────────────────┘ │
|
|
|
|
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
|
|
|
```
|
2026-02-15 13:32:42 +08:00
|
|
|
|
|
|
|
|
|
|
## 输入事件系统
|
|
|
|
|
|
|
|
|
|
|
|
### 事件类型
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
enum class EventType {
|
|
|
|
|
|
// 键盘
|
|
|
|
|
|
KeyPressed,
|
|
|
|
|
|
KeyReleased,
|
|
|
|
|
|
KeyRepeat,
|
|
|
|
|
|
|
|
|
|
|
|
// 鼠标
|
|
|
|
|
|
MouseButtonPressed,
|
|
|
|
|
|
MouseButtonReleased,
|
|
|
|
|
|
MouseMoved,
|
|
|
|
|
|
MouseScrolled,
|
|
|
|
|
|
|
|
|
|
|
|
// 手柄
|
|
|
|
|
|
GamepadConnected,
|
|
|
|
|
|
GamepadDisconnected,
|
|
|
|
|
|
GamepadButtonPressed,
|
|
|
|
|
|
GamepadButtonReleased,
|
|
|
|
|
|
|
|
|
|
|
|
// 触摸
|
|
|
|
|
|
TouchBegan,
|
|
|
|
|
|
TouchMoved,
|
|
|
|
|
|
TouchEnded,
|
|
|
|
|
|
|
|
|
|
|
|
// 窗口
|
|
|
|
|
|
WindowResize,
|
|
|
|
|
|
WindowClose,
|
2026-02-15 12:36:36 +08:00
|
|
|
|
};
|
2026-02-15 10:11:09 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-15 13:32:42 +08:00
|
|
|
|
### 事件监听
|
2026-02-15 10:11:09 +08:00
|
|
|
|
|
|
|
|
|
|
```cpp
|
2026-02-17 23:57:50 +08:00
|
|
|
|
auto eventService = app.events();
|
2026-02-15 13:32:42 +08:00
|
|
|
|
|
|
|
|
|
|
// 监听键盘事件
|
|
|
|
|
|
eventService->addListener(EventType::KeyPressed, [](Event& e) {
|
|
|
|
|
|
auto& key = std::get<KeyEvent>(e.data);
|
|
|
|
|
|
E2D_LOG_INFO("Key: {}, mods: {}", key.keyCode, key.mods);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 监听鼠标事件
|
|
|
|
|
|
eventService->addListener(EventType::MouseButtonPressed, [](Event& e) {
|
|
|
|
|
|
auto& mouse = std::get<MouseButtonEvent>(e.data);
|
|
|
|
|
|
E2D_LOG_INFO("Mouse button: {} at ({}, {})",
|
|
|
|
|
|
mouse.button, mouse.position.x, mouse.position.y);
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-15 13:39:18 +08:00
|
|
|
|
## 场景图系统
|
|
|
|
|
|
|
|
|
|
|
|
### Node 基类
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
class Node : public std::enable_shared_from_this<Node> {
|
|
|
|
|
|
public:
|
|
|
|
|
|
// 层级管理
|
|
|
|
|
|
void addChild(Ptr<Node> child);
|
|
|
|
|
|
void removeChild(Ptr<Node> child);
|
|
|
|
|
|
void detach();
|
|
|
|
|
|
void clearChildren();
|
|
|
|
|
|
|
|
|
|
|
|
Ptr<Node> getParent() const;
|
|
|
|
|
|
const std::vector<Ptr<Node>>& getChildren() const;
|
|
|
|
|
|
|
|
|
|
|
|
// 变换属性
|
|
|
|
|
|
void setPos(const Vec2& pos);
|
|
|
|
|
|
void setRotation(float degrees);
|
|
|
|
|
|
void setScale(const Vec2& scale);
|
|
|
|
|
|
void setAnchor(const Vec2& anchor);
|
|
|
|
|
|
void setOpacity(float opacity);
|
|
|
|
|
|
void setVisible(bool visible);
|
|
|
|
|
|
void setZOrder(int zOrder);
|
|
|
|
|
|
|
|
|
|
|
|
// 世界变换
|
|
|
|
|
|
Vec2 toWorld(const Vec2& localPos) const;
|
|
|
|
|
|
Vec2 toLocal(const Vec2& worldPos) const;
|
|
|
|
|
|
glm::mat4 getLocalTransform() const;
|
|
|
|
|
|
glm::mat4 getWorldTransform() const;
|
|
|
|
|
|
|
|
|
|
|
|
// 生命周期回调
|
|
|
|
|
|
virtual void onEnter();
|
|
|
|
|
|
virtual void onExit();
|
|
|
|
|
|
virtual void onUpdate(float dt);
|
2026-02-20 15:04:21 +08:00
|
|
|
|
virtual void onRender(Renderer& renderer);
|
2026-02-15 13:39:18 +08:00
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
### 使用场景
|
2026-02-15 13:39:18 +08:00
|
|
|
|
|
|
|
|
|
|
```cpp
|
2026-02-17 23:57:50 +08:00
|
|
|
|
auto scene = Scene::create();
|
2026-02-15 13:39:18 +08:00
|
|
|
|
|
|
|
|
|
|
// 创建形状节点
|
|
|
|
|
|
auto rect = ShapeNode::createFilledRect(Rect(0, 0, 100, 100), Color(1.0f, 0.4f, 0.4f, 1.0f));
|
|
|
|
|
|
auto circle = ShapeNode::createFilledCircle(Vec2(0, 0), 50, Color(0.4f, 0.4f, 1.0f, 1.0f));
|
|
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
// 添加到场景
|
|
|
|
|
|
scene->addChild(rect);
|
|
|
|
|
|
scene->addChild(circle);
|
2026-02-15 13:39:18 +08:00
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
// 运行场景
|
|
|
|
|
|
app.scenes()->runWithScene(scene);
|
2026-02-15 13:39:18 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 视口适配系统
|
|
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
### 视口适配模式
|
2026-02-15 13:39:18 +08:00
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
enum class ViewportMode {
|
|
|
|
|
|
AspectRatio, // 保持宽高比,可能有黑边
|
|
|
|
|
|
Stretch, // 拉伸填满整个窗口
|
|
|
|
|
|
Center, // 居中显示,不缩放
|
|
|
|
|
|
Custom // 自定义缩放和偏移
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
### 配置视口
|
2026-02-15 13:39:18 +08:00
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
auto cameraService = app.camera();
|
|
|
|
|
|
if (cameraService) {
|
|
|
|
|
|
ViewportConfig vpConfig;
|
2026-02-17 23:57:50 +08:00
|
|
|
|
vpConfig.logicWidth = 1280.0f;
|
|
|
|
|
|
vpConfig.logicHeight = 720.0f;
|
|
|
|
|
|
vpConfig.mode = ViewportMode::AspectRatio;
|
|
|
|
|
|
vpConfig.letterboxColor = Color(0.0f, 0.0f, 0.0f, 1.0f);
|
2026-02-15 13:39:18 +08:00
|
|
|
|
|
|
|
|
|
|
cameraService->setViewportConfig(vpConfig);
|
|
|
|
|
|
cameraService->updateViewport(windowWidth, windowHeight);
|
|
|
|
|
|
cameraService->applyViewportAdapter();
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
## 平台支持
|
2026-02-15 13:39:18 +08:00
|
|
|
|
|
2026-02-17 23:57:50 +08:00
|
|
|
|
| 平台 | 窗口后端 | 图形 API |
|
|
|
|
|
|
|-----|---------|---------|
|
|
|
|
|
|
| Windows | SDL2 / GLFW | OpenGL / Vulkan |
|
|
|
|
|
|
| Linux | SDL2 / GLFW | OpenGL / Vulkan |
|
|
|
|
|
|
| macOS | SDL2 / GLFW | OpenGL / Vulkan |
|
|
|
|
|
|
| Nintendo Switch | SDL2 / GLFW | OpenGL / Vulkan |
|
2026-02-15 13:39:18 +08:00
|
|
|
|
|
2026-02-15 10:11:09 +08:00
|
|
|
|
## 示例
|
|
|
|
|
|
|
|
|
|
|
|
完整示例请参考:
|
2026-02-17 23:57:50 +08:00
|
|
|
|
- [examples/basic/main.cpp](../../examples/basic/main.cpp) - 基础示例
|
|
|
|
|
|
- [examples/demo_shapes/main.cpp](../../examples/demo_shapes/main.cpp) - 形状绘制
|
|
|
|
|
|
- [examples/demo_sprite/main.cpp](../../examples/demo_sprite/main.cpp) - 精灵渲染
|
|
|
|
|
|
- [examples/demo_text/main.cpp](../../examples/demo_text/main.cpp) - 文字渲染
|
|
|
|
|
|
- [examples/demo_framebuffer/main.cpp](../../examples/demo_framebuffer/main.cpp) - 帧缓冲
|