【V0.1B13】从零开始的2D游戏引擎开发之路 TEnGinE Version-0.1 Build-13 更新日志发布日期2022-05-17 22:28内部版本号Version-0.1 Build-13更新类型模块重构与功能完善变更概要类别内容架构重构绘制模块全局变量封装至OpenGL_Draw类消除全局状态污染核心功能绘制模块额外绘制一个方块补全 10×10 地图铺满屏幕的第 100 格功能新增输入模块新增可操纵方块的移动边界限制功能代码修复输入模块修复GetInsertBase()单例每次调用均new新对象的问题功能新增游戏物品类新增预设生命值组件Unit_Life接口调整按键注册与参数初始化代码从init()内部迁移至main()函数颜色微调顶点着色器地图方块与玩家方块颜色数值调整一、绘制模块架构重构Tanxl_OpenGL_Draw.h本版本完成了一次较大范围的架构整理原先以全局变量形式散落在文件作用域的所有绘制状态统一封装进OpenGL_Draw类外部不再可见这些变量。同时init()、display()、mainLoop()均成为该类的成员函数。1.1 全局变量封装至类// Build-12 — 全局变量散落在文件作用域 GLuint PosA, PosB; GLuint PosX, PosY; GLuint Height, Width; GLint StateInfor[100]{ 1,1,...,1 }; bool Clear_Function false; float movex; float movey; GLuint renderingProgram; GLuint vao[numVAOs]; int HeightInt; int WidthInt; InsertEventBase* IEB{ InsertEventBase::GetInsertBase() }; void init(GLFWwindow* window, GameStateBase* State) { ... } void display(GLFWwindow* window, double currentTime) { ... } int mainLoop(GameStateBase* State) { ... } // Build-13 — 全部移入 OpenGL_Draw 类的 private 区段 class OpenGL_Draw { public: void init(GLFWwindow* window, GameStateBase* State) { ... } void display(GLFWwindow* window, double currentTime) { ... } int mainLoop(GameStateBase* State) { ... } private: GLuint PosA, PosB; GLuint PosX, PosY; GLuint Height, Width; GLint StateInfor[101]; // ← 容量从 100 扩至 101 bool Clear_Function false; float movex; float movey; GLuint renderingProgram; GLuint vao[numVAOs]; int HeightInt; int WidthInt; InsertEventBase* IEB{ InsertEventBase::GetInsertBase() }; };项目Build-12Build-13绘制状态存储文件作用域全局变量OpenGL_Draw类private成员init/display/mainLoop独立全局函数类成员函数StateInfor容量GLint StateInfor[100]GLint StateInfor[101]StateInfor初始化定长花括号列表硬编码值srand rand() % 2 - 1随机初始化1.2 额外绘制第 101 个方块地图为 10×10 100 格顶点着色器的循环范围为i 1..SHeight*SWidth这意味着gl_VertexID从 6 到 600而gl_VertexID 0..5固定留给玩家方块。Build-12 中glDrawArrays总顶点数为HeightInt * WidthInt * 6600导致第 100 个地图格实际不会被渲染。Build-13 将绘制数量加 6// Build-12 glDrawArrays(GL_TRIANGLES, 0, HeightInt * WidthInt * 6); // Build-13 glDrawArrays(GL_TRIANGLES, 0, HeightInt * WidthInt * 6 6); // ← 新增补全第 100 格相应地着色器循环上限也从i SHeight * SWidth修改为i SHeight * SWidth 1// Build-12 for(int i 1; i SHeight * SWidth; i) // Build-13 for(int i 1; i SHeight * SWidth 1; i) // ← 新增循环包含第 100 格同时init()内部StatePos与StateInfor的初始化循环上限也同步扩展// Build-12 GLuint StatePos[100]{}; for (int i 0; i HeightInt * WidthInt; i) // Build-13 GLuint StatePos[101]{}; // ← 扩容 for (int i 0; i HeightInt * WidthInt 1; i) // ← 覆盖第 101 个 uniform1.3 按键注册代码迁移Build-12 的init()函数内部包含四组按键注册逻辑UP/DOWN/LEFT/RIGHT各双绑 WASD。Build-13 将这些代码从init()中完全移除统一迁移至main.cpp的main()函数// Build-12 — init() 内部已移除 Key_Unit MOVE_UP; MOVE_UP.GLFW_KEY GLFW_KEY_UP; MOVE_UP.MoveLen 0.01f; MOVE_UP.MoveToY true; IEB-RegistEvent(MOVE_UP); MOVE_UP.GLFW_KEY GLFW_KEY_W; IEB-RegistEvent(MOVE_UP); // ... LEFT / RIGHT / DOWN 同理 // Build-13 — main() 内部新位置 InsertEventBase* IEB{ InsertEventBase::GetInsertBase() }; Key_Unit MOVE_UP; MOVE_UP.GLFW_KEY GLFW_KEY_UP; MOVE_UP.MoveLen 0.01f; MOVE_UP.MoveToY true; IEB-RegistEvent(MOVE_UP); // ... IEB-Set_MaxFloat(0.9f); // ← 新增设置移动边界 OpenGL_Draw OD; OD.mainLoop(GSB); // ← 新增通过类实例调用二、输入模块功能新增 Bug 修复InsertEventBase新增移动边界限制功能并修复了单例实现的严重错误。2.1 单例 Bug 修复// Build-12 — GetInsertBase() 每次调用均 new 新对象单例完全失效 InsertEventBase InsertEventBase::GetInsertBase() { InsertEventBase* IEB new InsertEventBase; // ← Bug无 static每次返回新实例 return *IEB; } // Build-13 — 加入 static保证全局唯一 InsertEventBase InsertEventBase::GetInsertBase() { static InsertEventBase* IEB new InsertEventBase; // ← 修复static 保证单例 return *IEB; }该 Bug 导致在Tanxl_OpenGL_Draw.h中通过IEB-RegistEvent()注册的按键事件与GetInsert()调用时获取的对象并非同一个实例——事件列表永远为空按键完全失效。2.2 移动边界限制功能头文件新增接口// Build-13 — Tanxl_InsertAction.h 新增 void Set_MaxFloat(float Max_float); // ← 新增设置坐标边界 // private 区段新增 void AutoCheck(float* MoveX, float* MoveY); // ← 新增内部越界检查 float _Max_float; // ← 新增边界值成员实现逻辑void InsertEventBase::Set_MaxFloat(float Max_float) { this-_Max_float Max_float; } void InsertEventBase::AutoCheck(float* MoveX, float* MoveY) { if (*MoveX _Max_float) *MoveX _Max_float; else if (*MoveX -_Max_float) *MoveX -_Max_float; if (*MoveY _Max_float) *MoveY _Max_float; else if (*MoveY -_Max_float) *MoveY -_Max_float; }AutoCheck()在GetInsert()的按键响应分支中调用// Build-12 *MoveX KeyEventS.at(i).MoveLen; // ... std::cout BUTTON PUSHED x_ *MoveX y_ *MoveY std::endl; // Build-13 *MoveX KeyEventS.at(i).MoveLen; // ... AutoCheck(MoveX, MoveY); // ← 新增每次移动后自动夹紧坐标 std::cout BUTTON PUSHED x_ *MoveX y_ *MoveY std::endl;构造函数与拷贝构造函数同步初始化_Max_float// Build-12 InsertEventBase::InsertEventBase() :KeyEventS(NULL) {} InsertEventBase::InsertEventBase(const InsertEventBase) {} // Build-13 InsertEventBase::InsertEventBase() :KeyEventS(NULL), _Max_float(1.0f) {} // ← 新增初始化 InsertEventBase::InsertEventBase(const InsertEventBase) :KeyEventS(NULL), _Max_float(1.0f) {} // ← 修复边界值由main()中IEB-Set_MaxFloat(0.9f)设定公式为1 - (1 / 地图边长)10×10 地图对应0.9f确保玩家方块中心恰好到达最边缘格子时停止。三、游戏物品类功能新增Tanxl_GameObject.h新增预设生命值组件Unit_Life作为ComponmentBase的一个具体实现示例。// Build-13 — 新增 Unit_Life 组件Componment Sample class Unit_Life : public ComponmentBase { public: Unit_Life(int Life_Count) :ComponmentBase(Unit_Life), _Life_Count(Life_Count) {} void Special() { // 预留可在此实现生命值相关的帧逻辑 } void RestoreHealth() { _Life_Count; // ← 新增回复1点生命值 } void TakeDamage() { _Life_Count--; // ← 新增扣除1点生命值 } private: int _Life_Count; };GameObjectBase本身AppendComponment、RemoveComponment、FinishComponment未作任何修改仅文件头部注释版本号从_VERSION_0_2_升至_VERSION_0_3_。四、顶点着色器颜色微调vertShader.glsl对地图方块和玩家方块的颜色数值进行了调整蓝色分量从0.0微调至0.1同时玩家方块颜色方案由暖黄系改为紫白系。// Build-12 — 地图方块 ID0暖黄 vs_color vec4(1.0, 0.8, 0.0, 1.0); // 顶点 0 vs_color vec4(1.0, 1.0, 0.0, 1.0); // 顶点 1~5 // Build-13 — 地图方块 ID0暖黄蓝色分量 0.1 vs_color vec4(1.0, 0.8, 0.1, 1.0); // ← 修改 vs_color vec4(1.0, 1.0, 0.1, 1.0); // ← 修改 // Build-12 — 地图方块 ID≠0青色 vs_color vec4(0.0, 0.8, 1.0, 1.0); vs_color vec4(0.0, 1.0, 1.0, 1.0); // Build-13 — 地图方块 ID≠0青色红色分量 0.0→0.1 vs_color vec4(0.1, 0.8, 1.0, 1.0); // ← 修改 vs_color vec4(0.1, 1.0, 1.0, 1.0); // ← 修改 // Build-12 — 玩家方块暖黄系 gl_VertexID0: vs_color vec4(1.0, 0.8, 0.0, 1.0); gl_VertexID1~5: vs_color vec4(1.0, 1.0, 0.0, 1.0); // Build-13 — 玩家方块紫白系 gl_VertexID0: vs_color vec4(0.9, 0.8, 1.0, 1.0); // ← 修改淡紫色 gl_VertexID1~5: vs_color vec4(0.9, 1.0, 1.0, 1.0); // ← 修改淡青白色着色器文件头部注释新增一行// 颜色微调且删除了 Build-12 中的注释行// float Height 0.2f;单一方块移动测试用的被注释代码。项目Build-12Build-13地图方块 ID0 颜色(1.0, 0.8, 0.0)(1.0, 1.0, 0.0)(1.0, 0.8, 0.1)(1.0, 1.0, 0.1)地图方块 ID≠0 颜色(0.0, 0.8, 1.0)(0.0, 1.0, 1.0)(0.1, 0.8, 1.0)(0.1, 1.0, 1.0)玩家方块颜色暖黄系(1.0, 0.8/1.0, 0.0)紫白系(0.9, 0.8/1.0, 1.0)调试注释行含// float Height 0.2f;已移除影响范围总览文件旧版行数新版行数变更类型Tanxl_OpenGL_Draw.h176145修改类封装全局变量 移除按键注册代码 随机初始化main.cpp850修改新增 IEB 获取 四方向按键注册 Set_MaxFloat 类实例调用Tanxl_InsertAction.h5358修改新增Set_MaxFloatAutoCheck_Max_floatTanxl_InsertAction.cpp5069修改新增单例 static 修复 Set_MaxFloatAutoCheck实现Tanxl_GameObject.h7290修改新增Unit_Life组件类vertShader.glsl124122修改颜色数值微调 移除调试注释 循环上限 1Update-Log.txt6874修改新增 Build-13 条目净代码量变化96 行main.cpp 新增按键注册 42InsertAction 功能 24GameObject 18vertShader 循环调整 1-29 行OpenGL_Draw 移除按键注册代码 1注释清理 -2技术要点总结绘制模块封装架构Build-12 (全局变量): Build-13 (类封装): ┌─────────────────────────┐ ┌─────────────────────────┐ │ 文件作用域全局变量 │ → │ class OpenGL_Draw │ │ GLuint PosA, PosB... │ │ public: │ │ GLint StateInfor[100] │ │ init(), display() │ │ bool Clear_Function │ │ mainLoop() │ │ float movex, movey │ │ private: │ │ │ │ GLuint PosA, PosB... │ │ void init(...) │ │ GLint StateInfor[101] │ │ void display(...) │ │ float movex, movey │ │ int mainLoop(...) │ │ ... │ └─────────────────────────┘ └─────────────────────────┘移动边界公式玩家方块坐标范围为[-Max, Max]Max 1 - (1 / 地图边长)10×10 地图Max 1 - 1/10 0.9f方块宽度为2.0 / 10 0.2中心到达±0.9时方块边缘恰好与地图边缘对齐核心 API 说明API/配置项所属模块说明InsertEventBase::Set_MaxFloat(float)InsertAction设置可操纵方块的坐标边界绝对值InsertEventBase::GetInsertBase()InsertAction单例获取Build-13 修复为真正的单例OpenGL_Draw::mainLoop(GameStateBase*)OpenGL_Draw进入主循环Build-13 改为通过类实例调用Unit_Life(int)GameObject预设生命值组件构造参数为初始生命值Unit_Life::RestoreHealth()GameObject生命值 1Unit_Life::TakeDamage()GameObject生命值 -1Wild_Chicken_Programing/// 2022-05-17 22:28