docs: 添加快速入门指南并更新文档索引

添加详细的快速入门指南文档,涵盖从安装到创建第一个游戏的完整流程
更新 README.md 中的文档索引部分以包含新指南链接
This commit is contained in:
ChestnutYueyue 2026-02-15 20:15:59 +08:00
parent f8a7fab2e7
commit d06c8735bd
2 changed files with 611 additions and 0 deletions

View File

@ -371,6 +371,7 @@ xmake run demo_hello_module
## 文档
- [快速入门指南](./docs/quick_start.md) - 从安装到创建第一个游戏
- [模块系统文档](./docs/module_system.md) - 模块系统、服务系统、场景图、视口适配
---

610
docs/quick_start.md Normal file
View File

@ -0,0 +1,610 @@
# Extra2D 快速入门指南
本指南将帮助您快速上手 Extra2D 游戏引擎,从安装到创建您的第一个游戏。
---
## 目录
1. [环境准备](#环境准备)
2. [创建项目](#创建项目)
3. [基础概念](#基础概念)
4. [创建场景](#创建场景)
5. [添加节点](#添加节点)
6. [处理输入](#处理输入)
7. [自定义模块](#自定义模块)
8. [完整示例](#完整示例)
---
## 环境准备
### 安装 xmake
**Windows (PowerShell):**
```powershell
Invoke-Expression (Invoke-WebRequest 'https://xmake.io/psget.text' -UseBasicParsing).Content
```
**macOS:**
```bash
brew install xmake
```
**Linux:**
```bash
sudo add-apt-repository ppa:xmake-io/xmake
sudo apt update
sudo apt install xmake
```
### 克隆项目
```bash
git clone https://github.com/ChestnutYueyue/extra2d.git
cd extra2d
```
### 构建项目
```bash
# 配置项目
xmake f -p mingw -a x86_64 -m release -y
# 构建
xmake build
# 运行示例
xmake run demo_basic
```
---
## 创建项目
### 最小示例
创建一个 `main.cpp` 文件:
```cpp
#include <extra2d/extra2d.h>
using namespace extra2d;
int main() {
// 1. 配置应用
AppConfig config;
config.appName = "My First Game";
config.appVersion = "1.0.0";
// 2. 获取应用实例
Application& app = Application::get();
// 3. 初始化
if (!app.init(config)) {
return -1;
}
// 4. 创建场景
auto scene = Scene::create();
scene->setBackgroundColor(Color(0.1f, 0.1f, 0.2f, 1.0f));
// 5. 进入场景
app.enterScene(scene);
// 6. 运行游戏循环
app.run();
// 7. 清理
app.shutdown();
return 0;
}
```
---
## 基础概念
### 模块系统
Extra2D 使用模块化架构,通过 `Application::use()` 注册模块:
```cpp
// 内置模块会自动注册,您也可以自定义
MyModule myModule;
app.use(myModule);
```
**内置模块优先级:**
| 模块 | 优先级 | 说明 |
|------|--------|------|
| Logger | -1 | 日志系统 |
| Config | 0 | 配置管理 |
| Platform | 10 | 平台检测 |
| Window | 20 | 窗口管理 |
| Input | 30 | 输入系统 |
| Render | 40 | 渲染系统 |
### 服务系统
服务提供运行时功能,通过 `Application` 的便捷方法访问:
```cpp
auto sceneService = app.scenes(); // 场景管理
auto timerService = app.timers(); // 计时器
auto eventService = app.events(); // 事件分发
auto cameraService = app.camera(); // 相机系统
```
### 场景图
场景图是一个树形结构,由 `Scene``Node` 组成:
```
Scene (根节点)
├── Node (父节点)
│ ├── Node (子节点)
│ └── ShapeNode (形状节点)
└── Sprite (精灵)
```
---
## 创建场景
### 基本场景
```cpp
class MyScene : public Scene {
public:
static Ptr<MyScene> create() {
return makeShared<MyScene>();
}
void onEnter() override {
Scene::onEnter();
// 设置背景颜色
setBackgroundColor(Color(0.1f, 0.1f, 0.2f, 1.0f));
// 在这里添加节点和设置游戏逻辑
}
void onUpdate(float dt) override {
Scene::onUpdate(dt);
// 每帧更新逻辑
}
};
```
### 使用场景
```cpp
auto scene = MyScene::create();
app.enterScene(scene);
```
---
## 添加节点
### 创建形状节点
```cpp
// 矩形
auto rect = ShapeNode::createFilledRect(
Rect(0, 0, 100, 100), // 位置和大小
Color(1.0f, 0.4f, 0.4f, 1.0f) // 颜色
);
scene->addChild(rect);
// 圆形
auto circle = ShapeNode::createFilledCircle(
Vec2(50, 50), // 圆心
30, // 半径
Color(0.4f, 0.4f, 1.0f, 1.0f) // 颜色
);
scene->addChild(circle);
// 三角形
auto triangle = ShapeNode::createFilledTriangle(
Vec2(50, 0), // 顶点1
Vec2(0, 100), // 顶点2
Vec2(100, 100), // 顶点3
Color(0.4f, 1.0f, 0.4f, 1.0f) // 颜色
);
scene->addChild(triangle);
// 线段
auto line = ShapeNode::createLine(
Vec2(0, 0), // 起点
Vec2(100, 100), // 终点
Color(1.0f, 1.0f, 1.0f, 1.0f), // 颜色
2.0f // 线宽
);
scene->addChild(line);
```
### 节点变换
```cpp
// 位置
node->setPos(100, 200);
Vec2 pos = node->getPosition();
// 旋转(角度)
node->setRotation(45);
float rotation = node->getRotation();
// 缩放
node->setScale(2.0f); // 统一缩放
node->setScale(2.0f, 1.5f); // 分别设置 X/Y
Vec2 scale = node->getScale();
// 锚点(变换中心)
node->setAnchor(0.5f, 0.5f); // 中心(默认)
// 透明度
node->setOpacity(0.5f); // 0.0 - 1.0
// 可见性
node->setVisible(false);
// Z 序(渲染顺序)
node->setZOrder(10);
```
### 节点层级
```cpp
// 添加子节点
parent->addChild(child);
// 移除子节点
parent->removeChild(child);
// 从父节点分离
child->detach();
// 查找子节点
Ptr<Node> found = parent->findChild("nodeName");
Ptr<Node> foundByTag = parent->findChildByTag(1);
// 清除所有子节点
parent->clearChildren();
```
### 变换继承
子节点会继承父节点的变换:
```cpp
auto parent = makeShared<Node>();
parent->setPos(400, 300);
parent->setRotation(30); // 旋转 30 度
auto child = ShapeNode::createFilledRect(
Rect(-25, -25, 50, 50),
Color(1.0f, 0.0f, 0.0f, 1.0f)
);
child->setPos(100, 0); // 相对于父节点
parent->addChild(child);
scene->addChild(parent);
// child 会随 parent 一起旋转
// child 的世界位置约为 (486.6, 350)
```
---
## 处理输入
### 在场景中处理事件
```cpp
class MyScene : public Scene {
public:
void onEnter() override {
Scene::onEnter();
// 键盘事件
addListener(EventType::KeyPressed, [](Event& e) {
auto& key = std::get<KeyEvent>(e.data);
if (key.keyCode == static_cast<int>(Key::Escape)) {
e.handled = true;
Application::get().quit();
}
if (key.keyCode == static_cast<int>(Key::Space)) {
E2D_LOG_INFO("Space pressed!");
}
});
// 鼠标事件
addListener(EventType::MouseButtonPressed, [](Event& e) {
auto& mouse = std::get<MouseButtonEvent>(e.data);
E2D_LOG_INFO("Click at ({}, {})", mouse.position.x, mouse.position.y);
});
// 手柄事件
addListener(EventType::GamepadButtonPressed, [](Event& e) {
auto& gamepad = std::get<GamepadButtonEvent>(e.data);
E2D_LOG_INFO("Gamepad button: {}", gamepad.button);
});
}
};
```
### 实时输入查询
```cpp
void onUpdate(float dt) override {
Scene::onUpdate(dt);
auto& input = Application::get().input();
// 键盘
if (input.down(Key::W)) {
// W 键被按住
}
if (input.pressed(Key::Space)) {
// 空格键刚按下
}
if (input.released(Key::Space)) {
// 空格键刚释放
}
// 鼠标
Vec2 mousePos = input.mouse();
if (input.down(Mouse::Left)) {
// 左键被按住
}
// 手柄
if (input.gamepad()) {
Vec2 leftStick = input.leftStick();
Vec2 rightStick = input.rightStick();
if (input.down(Gamepad::A)) {
// A 键被按住
}
// 振动
input.vibrate(0.5f, 0.5f);
}
}
```
---
## 自定义模块
### 创建模块
```cpp
#include <extra2d/core/module.h>
class GameModule : public extra2d::Module {
public:
const char* getName() const override { return "GameModule"; }
int getPriority() const override { return 1000; }
void setupModule() override {
// 初始化游戏资源
E2D_LOG_INFO("Game module initialized");
}
void destroyModule() override {
// 清理资源
E2D_LOG_INFO("Game module destroyed");
}
void onUpdate(extra2d::UpdateContext& ctx) override {
// 更新游戏逻辑
float dt = ctx.getDeltaTime();
// ...
ctx.next(); // 继续下一个模块
}
};
```
### 注册模块
```cpp
int main() {
Application& app = Application::get();
GameModule gameModule;
app.use(gameModule);
app.init();
app.run();
return 0;
}
```
---
## 完整示例
下面是一个完整的游戏示例,展示如何创建一个简单的交互式场景:
```cpp
#include <extra2d/extra2d.h>
using namespace extra2d;
// 自定义场景
class GameScene : public Scene {
public:
static Ptr<GameScene> create() {
return makeShared<GameScene>();
}
void onEnter() override {
Scene::onEnter();
// 设置背景
setBackgroundColor(Color(0.1f, 0.1f, 0.15f, 1.0f));
// 创建玩家
player_ = ShapeNode::createFilledRect(
Rect(-25, -25, 50, 50),
Color(1.0f, 0.4f, 0.4f, 1.0f)
);
player_->setPos(getWidth() / 2, getHeight() / 2);
addChild(player_);
// 键盘控制
addListener(EventType::KeyPressed, [this](Event& e) {
auto& key = std::get<KeyEvent>(e.data);
if (key.keyCode == static_cast<int>(Key::Escape)) {
e.handled = true;
Application::get().quit();
}
});
E2D_LOG_INFO("Game scene entered");
}
void onUpdate(float dt) override {
Scene::onUpdate(dt);
// 移动玩家
auto& input = Application::get().input();
float speed = 200.0f * dt;
Vec2 pos = player_->getPosition();
if (input.down(Key::W) || input.down(Key::Up)) pos.y -= speed;
if (input.down(Key::S) || input.down(Key::Down)) pos.y += speed;
if (input.down(Key::A) || input.down(Key::Left)) pos.x -= speed;
if (input.down(Key::D) || input.down(Key::Right)) pos.x += speed;
// 边界检测
pos.x = std::clamp(pos.x, 25.0f, getWidth() - 25.0f);
pos.y = std::clamp(pos.y, 25.0f, getHeight() - 25.0f);
player_->setPos(pos);
// 旋转
rotation_ += 90.0f * dt;
player_->setRotation(rotation_);
}
private:
Ptr<ShapeNode> player_;
float rotation_ = 0.0f;
};
int main() {
// 配置
AppConfig config;
config.appName = "My Game";
config.appVersion = "1.0.0";
// 初始化
Application& app = Application::get();
if (!app.init(config)) {
return -1;
}
// 创建并进入场景
auto scene = GameScene::create();
app.enterScene(scene);
// 运行
app.run();
// 清理
app.shutdown();
return 0;
}
```
---
## 下一步
- 查看 [模块系统文档](./module_system.md) 了解更多高级功能
- 查看 `examples/` 目录中的示例代码
- 阅读 [API 参考](./api_reference.md)(待完善)
---
## 常见问题
### Q: 如何设置窗口大小?
```cpp
WindowModule windowModule;
WindowConfigData windowConfig;
windowConfig.width = 1920;
windowConfig.height = 1080;
windowConfig.title = "My Game";
windowModule.setWindowConfig(windowConfig);
app.use(windowModule);
```
### Q: 如何启用垂直同步?
```cpp
RenderModule renderModule;
RenderModuleConfig renderConfig;
renderConfig.vsync = true;
renderModule.setRenderConfig(renderConfig);
app.use(renderModule);
```
### Q: 如何处理窗口大小变化?
```cpp
// 在场景中
void onEnter() override {
Scene::onEnter();
addListener(EventType::WindowResize, [this](Event& e) {
auto& resize = std::get<WindowResizeEvent>(e.data);
E2D_LOG_INFO("Window resized: {}x{}", resize.width, resize.height);
// 更新视口
setViewportSize(resize.width, resize.height);
});
}
```
### Q: 如何使用计时器?
```cpp
void onEnter() override {
Scene::onEnter();
auto timerService = Application::get().timers();
// 延迟执行
timerService->addTimer(2.0f, []() {
E2D_LOG_INFO("2 seconds passed!");
});
// 重复执行
timerService->addRepeatingTimer(1.0f, [](int count) {
E2D_LOG_INFO("Count: {}", count);
return true; // 返回 false 停止
});
}
```
---
## 获取帮助
- GitHub Issues: https://github.com/ChestnutYueyue/extra2d/issues
- 查看示例代码: `examples/` 目录