6.6 KiB
Vendored
6.6 KiB
Vendored
AI Skill:dl 引擎开发指南
本文档面向开发者与 AI,记录 dl 引擎的整体架构、代码风格、通用易错点与常规使用方法,便于快速上手并保持一致。
一、整体架构
1. 项目定位
dl(drawing library)是基于 C++23 的开发框架/游戏引擎,命名空间统一为 dl,集成了大量 C/C++ 开源库。
2. 目录结构
| 目录 | 职责 |
|---|---|
base/ |
基础类型与容器(Array、String、Color、Vector 等) |
io/ |
输入输出(日志、文件、网络、JSON/XML/XLSX、数据库) |
math/ |
数学与物理(Mesh、Guid、Physics) |
memory/ |
内存管理(Buffer、加密、流、对象复用) |
misc/ |
杂项(Mod、JsonConfig、Tilemap、AStar) |
render/ |
渲染(Graphics、Factory、Action、Animation、粒子) |
script/ |
脚本(Lua、AngelScript) |
system/ |
系统(Engine、System 窗口、音频、线程、硬件信息) |
tool/ |
工具(DebugInfo、Archiver 等) |
ui/ |
UI 系统(Manager、Scene) |
vk/ |
Vulkan 渲染底层 |
3. 头文件组织
- 总头文件为
dl.h,也可按模块单独包含(dl_type.h、dl_io.h、dl_render.h、dl_ui.h、dl_range.h)。 - 模块聚合头位于
dl/根目录,具体类头位于各子目录。
4. 程序入口
- 平台入口已统一封装在
dl_main.h:根据平台自动生成main/WinMain/android_main,用户只需实现int Main()。 - 入口内部会调用
dl_main_init(初始化崩溃采集、解析命令行参数)与dl_main_release。
5. 全局对象约定
- 各子系统通过
extern全局指针暴露,命名统一g_前缀:g_system、g_factory、g_gfx、g_input、g_log、g_audio、g_lua、g_as、g_net、g_http、g_ui、g_physics、g_time、g_thread等。 - 用指针而非全局对象,是为了控制生命周期、不占用全局空间。
- 这些对象的生命周期由
Engine::Init/Engine::Release统一管理,Release之后不可再访问。
二、代码风格
1. 命名规范
- 全局函数:小写 + 下划线,如
calc_n。 - 非通用型全局函数:仅首字母小写,如
createQuad。 dl命名空间内的全局函数:大写开头,如Math::SetSeed。- 宏:无命名空间,必须
DL_开头防止冲突。 - 类/类型:首字母大写;缩写只首字母大写(如
UI);除dl外的其他命名空间也首字母大写。 - 成员变量:下划线前缀,如
_mulSpr。
2. 常用语义区分
init:不需要外部资源的初始化;load:需要使用外部资源的初始化。Add:添加一个已有对象,而非创建。func:回调函数;fn:局部 lambda。Refresh:刷新(不保存数据);Set:设置。Update:时间片逻辑;Render:绘制;Run:前二者合一(一般不使用)。Reset:重置;Delete:删除(不可逆);Clear:清除;Release:释放。Clone:新建元素复制;Copy:把属性复制到已有元素。GetBuffer:返回字节流;GetData:返回实际类型指针。- 多个元素不加复数,用
mul修饰(如_mulSpr,可为数组或链表)。
3. 命名约定补充
- 加减乘除:
add/sub/mul/div。 - 冒号
:用作特殊对象的隐含命名,如默认精灵/默认演员名为":"。 - 资源名中
/不能作文件名,用.替换。
4. 基础类型与编码
- 优先使用
int、unsigned、float;字节流用std::byte(配合Buffer类)。 - 字符串统一 UTF-8(
std::string),需要拆分字符时再转 UTF-32(用 iconv)。 - 文件优先
fstream;接口统一 UTF-8。 - 优先使用枚举类(
enum class)。
5. 类成员顺序
嵌套类 → 构造函数 → 操作符重载 → 主要函数 → Set 函数 → Get 函数 → 功能性函数 → 析构函数 → 私有成员 → 私有函数。
6. 对象创建与释放
- 特殊对象通过
g_factory创建,用户层一般情况不出现new。
三、通用易错点
1. 生命周期顺序
Engine::Release() 会释放(delete)所有 g_ 全局对象。任何对全局对象的操作(如 g_system->Pause())必须在 Release() 之前,否则出现悬空指针。
2. 越界判断语义(易搞反)
IsOutRange越界返回 true。CheckRange越界返回 false。
两者语义相反,注意区分。
3. init 与 load 的区别
init 不依赖外部资源,load 依赖外部资源。命名用错会导致对资源加载时机的误解。
4. 全局对象是裸指针
g_system 等是裸指针而非引用,使用前需确认已初始化;Release 后立即失效。
5. 资源路径与命名
- 资源名中的
/需用.替换(/不能作文件名)。 Factory::SetPath只能在System::Start之前调用一次。
四、常规使用方法
1. 最小入口
#include <dl.h>
int Main()
{
// 可选:配置引擎,如 dl::Engine::GetParamRef()._useAudio = false;
dl::Engine::Init();
// ...
dl::Engine::Release();
return 0;
}
2. 进入游戏循环
#include <dl.h>
void OnInit() { /* 初始化资源 */ }
void OnRun() { /* 每帧逻辑 */ }
int Main()
{
dl::Engine::Init();
dl::g_system->SetFuncInit(OnInit);
dl::g_system->SetFuncRun(OnRun);
dl::g_system->Start(); // 创建窗口并进入游戏循环
dl::Engine::Release();
return 0;
}
3. 常用全局对象
| 对象 | 用途 |
|---|---|
g_system |
窗口、游戏循环、暂停、剪贴板、截屏 |
g_factory |
资源工厂(精灵/模型/字体等的加载与创建) |
g_gfx |
绘图 |
g_input |
输入(鼠标/键盘) |
g_log |
日志 |
g_audio / g_midi |
音频 / MIDI |
g_lua / g_as |
Lua / AngelScript 脚本 |
g_net / g_http |
网络 / HTTP |
g_physics |
物理 |
g_time |
时间 |
4. 基础类型速查
Point=Array<int,2>,Size=Array<unsigned,2>,Position=Array<float,2>,Color=Array<float,4>(rgba)。Rect=Point4,RectF=Position4。Float = float,FloatTime = float。- 字面量后缀:
_f(Float)、_ft(FloatTime)、_zu(size_t)。
5. 单元测试
- 使用 googletest,测试入口为
project/dl_unit_test/test_main.cpp。 dl_unit_test目标开启USE_RENDER,会链接渲染相关依赖。- 测试完成后可调用
g_system->Pause()暂停观察结果(注意需在Engine::Release()之前)。