【V0.1B15】从零开始的2D游戏引擎开发之路

TEnGinE Version-0.1 Build-15 更新日志

发布日期: 2022-05-28 02:11

内部版本号: Version-0.1 Build-15

更新类型: 结构优化与头文件分离


变更概要

类别 内容
架构重构 绘制模块实现从头文件分离至独立源文件 Tanxl_OpenGL_Draw.cpp
架构重构 渲染模块全局函数封装进 class OR 静态方法
核心功能 DataBase 模块 IC_VectorId_Vector::exac 改为指针类型,降低连续存储压力
功能新增 主函数提供存储模块测试例程
代码优化 绘制模块移除 Height/Width 两个重复成员变量,复用 PosA/PosB
代码优化 绘制模块 IEB 成员移入 mainLoop() 局部变量
代码优化 核心功能文件统一改用 #pragma once 限定只编译一次

一、绘制模块(架构重构)

Tanxl_OpenGL_Draw.h 中所有内联实现迁移至新增的 Tanxl_OpenGL_Draw.cpp,头文件仅保留类声明。同时移除两个语义重复的成员变量,并移除 IEB 成员。

1.1 头文件与源文件分离

头文件从 155 行精简至 64 行,仅保留类声明与构造函数声明。

Tanxl_OpenGL_Draw.h - 类声明:

cpp 复制代码
// Build-14
class OpenGL_Draw
{
public:
    OpenGL_Draw() :HeightInt(0), Height(0), PosA(0), PosB(0), PosX(0), PosY(0), StateInfor(), WidthInt(0),
        Width(0), movex(0), movey(0), renderingProgram(0), vao() {}
    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];
    bool Clear_Function = false;
    float movex;
    float movey;
    GLuint renderingProgram;
    GLuint vao[numVAOs];                      // ← 依赖全局常量
    int HeightInt;
    int WidthInt;
    InsertEventBase* IEB{ &InsertEventBase::GetInsertBase() }; // ← 类成员
};

// Build-15
class OpenGL_Draw
{
public:
    OpenGL_Draw();
    void init(GLFWwindow* window, GameStateBase* State);
    void display(GLFWwindow* window, double currentTime);
    void mainLoop(GameStateBase* State);   // ← 注释:绘制主循环 在此之后的一切操作都会被忽略
private:
    GLuint PosA, PosB;
    GLuint PosX, PosY;
    GLint StateInfor[101];
    bool Clear_Function = false;
    float movex;
    float movey;
    GLuint renderingProgram;
    GLuint vao[1];                          // ← 修改:直接写 1
    int HeightInt;
    int WidthInt;
    // Height/Width/IEB 均移除
};
1.2 同意义变量复用

init()SHeight/SWidth 的 uniform 句柄原先存入 Height/Width 成员,Build-15 复用 PosA/PosB(这两个成员在 display() 中用于其他 uniform,生命周期不重叠)。

Tanxl_OpenGL_Draw.cpp - init():

cpp 复制代码
// Build-14
Height = glGetUniformLocation(renderingProgram, "SHeight");
glProgramUniform1f(renderingProgram, Height, static_cast<float>(HeightInt));
Width = glGetUniformLocation(renderingProgram, "SWidth");
glProgramUniform1f(renderingProgram, Width, static_cast<float>(WidthInt));

// Build-15
PosA = glGetUniformLocation(renderingProgram, "SHeight");   // ← 复用 PosA
glProgramUniform1f(renderingProgram, PosA, static_cast<float>(HeightInt));
PosB = glGetUniformLocation(renderingProgram, "SWidth");    // ← 复用 PosB
glProgramUniform1f(renderingProgram, PosB, static_cast<float>(WidthInt));
1.3 IEB 移入局部变量

InsertEventBase* IEB 从类成员移入 mainLoop() 函数体内局部声明,降低类实例的耦合度。

Tanxl_OpenGL_Draw.cpp - mainLoop():

cpp 复制代码
// Build-14 --- IEB 为类成员
// 类声明中:InsertEventBase* IEB{ &InsertEventBase::GetInsertBase() };
// mainLoop 中直接使用:IEB->GetInsert(window, &movex, &movey);

// Build-15 --- IEB 为局部变量
void OpenGL_Draw::mainLoop(GameStateBase* State)
{
    // ...
    InsertEventBase* IEB{ &InsertEventBase::GetInsertBase() }; // ← 局部声明
    init(window, State);
    // ...
    IEB->GetInsert(window, &movex, &movey);
}
项目 Build-14 Build-15
实现位置 头文件内联 独立 .cpp 文件
Height/Width 成员 存在 移除,复用 PosA/PosB
IEB 成员 类成员 mainLoop() 局部变量
vao 声明 vao[numVAOs] vao[1]
numVAOs 全局常量 存在 移除
createShaderProgram 调用 全局函数 OR::createShaderProgram

二、渲染模块(架构重构)

Tanxl_OpenGL_Render.h 中所有全局函数封装进 class OR,以静态方法形式提供。函数签名与实现逻辑不变,仅作用域改变。

Tanxl_OpenGL_Render.h - 函数封装:

cpp 复制代码
// Build-14 --- 全局函数 + 前向声明
std::string readShaderFile(const char* filePath);
void printShaderLog(GLuint shader);
GLuint createShaderProgram(const char* vp, const char* fp);
// ... 实现直接跟在声明后

// Build-15 --- 封装进 class OR
class OR
{
public:
    static std::string readShaderFile(const char* filePath) { /* 实现 */ }
    static void printShaderLog(GLuint shader) { /* 实现 */ }
    static GLuint createShaderProgram(const char* vp, const char* fp) { /* 实现 */ }
    // ...
};

调用方相应修改:

cpp 复制代码
// Build-14 (Tanxl_OpenGL_Draw.h init 内)
renderingProgram = createShaderProgram("vertShader.glsl", "fragShader.glsl");

// Build-15 (Tanxl_OpenGL_Draw.cpp init 内)
renderingProgram = OR::createShaderProgram("vertShader.glsl", "fragShader.glsl");

Update-Log 中描述为"考虑重复包含问题暂时回滚Render模块"------将原先散落在全局作用域的函数重新收入类作用域,避免多重包含时的链接冲突。


三、DataBase 模块(核心改进)

IC_VectorId_Vector::exac 从值类型改为指针类型,降低 vector 扩容时连续存储的压力。

3.1 成员类型变更

Tanxl_DataBase.h - 结构体与类成员:

cpp 复制代码
// Build-14
struct Id_Vector
{
    std::vector<Data_Vector*> exac;           // ← 值类型
    explicit Id_Vector(...) : exac(NULL) {}
};

class TANXL_DataBase
{
    std::vector<Id_Vector*> IC_Vector;        // ← 值类型
};

// Build-15
struct Id_Vector
{
    std::vector<Data_Vector*>* exac;          // ← 指针类型
    explicit Id_Vector(...) : exac(new std::vector<Data_Vector*>) {}  // ← 构造时 new
};

class TANXL_DataBase
{
    std::vector<Id_Vector*>* IC_Vector;      // ← 指针类型
};
3.2 构造函数初始化

Tanxl_DataBase.cpp - 构造函数:

cpp 复制代码
// Build-14
TANXL_DataBase::TANXL_DataBase(bool Zero_Legal) :
    Is_Instance_Data(false), Is_Chain_Empty(true), Is_Zero_Legal(Zero_Legal),
    IC_Vector(NULL), Current_Location(0) {}

// Build-15
TANXL_DataBase::TANXL_DataBase(bool Zero_Legal) :
    Is_Instance_Data(false), Is_Chain_Empty(true), Is_Zero_Legal(Zero_Legal),
    IC_Vector(new std::vector<Id_Vector*>), Current_Location(0) {}  // ← 修改:new
3.3 访问方式适配

所有原先通过 . 访问的成员改为 ->

cpp 复制代码
// Build-14
IC_Vector.push_back(&New_Id);
IC_Vector.at(0)->exac.push_back(&New_Data);
PIC->exac.push_back(&New_Data);

// Build-15
IC_Vector->push_back(&New_Id);
IC_Vector->at(0)->exac->push_back(&New_Data);
PIC->exac->push_back(&New_Data);

涉及 SortDataBase()Append_Chain()Get_LocalData()Clear_Chain()Print_Data()Remove_Chain()Id_Chain_Locate()Data_Chain_Locate()Replace_Chain() 共 9 个函数。

项目 Build-14 Build-15
IC_Vector 类型 std::vector<Id_Vector*> std::vector<Id_Vector*>*
Id_Vector::exac 类型 std::vector<Data_Vector*> std::vector<Data_Vector*>*
访问语法 . ->
构造时初始化 NULL new std::vector<...>
版本号 _VERSION_1_5_ _VERSION_1_6_

四、主函数(功能新增)

main.cpp 新增 DataBase 测试例程,启用先前注释的 #include "Tanxl_DataBase.h"

main.cpp - DataBase 测试例程:

cpp 复制代码
// Build-14
#include "Tanxl_OpenGL_Draw.h"
#include "Tanxl_UniqueID.h"
//#include "Tanxl_DataBase.h"        // ← 注释状态
int main()
{
    GameStateBase* GSB{ &GameStateBase::GetStateBase(10, 10) };
    // ... 按键注册 ...
}

// Build-15
#include "Tanxl_OpenGL_Draw.h"
#include "Tanxl_UniqueID.h"
#include "Tanxl_DataBase.h"           // ← 启用
int main()
{
    //Data Function Test
    TANXL_DataBase NData;
    int n = 0x11111, i = 5;
    while (i--)
    {
        std::cout << "Updating : " << n << std::endl;
        NData.Set_Instance(n++, "Updating" + std::to_string(n));
        std::cout << NData;
        NData.AppendItem(false);     // ← 写入内存链表
    }
    NData.Print_Data();               // ← 输出链表内容
    // ... 后续游戏逻辑不变 ...
}

该例程向 NData 写入 5 条递增 ID 的数据项,演示 Set_Instance()operator<<AppendItem(false)Print_Data() 的完整链表写入流程。


五、头文件保护统一(代码优化)

8 个核心文件统一改用 #pragma once 替换 #ifndef/#define/#endif 包裹宏。

文件 原 include guard
Tanxl_GameState.h #ifndef VECTOR 区域后的文件级 guard
Tanxl_GameState.cpp #include "Tanxl_GameState.h"
Tanxl_InsertAction.h #ifndef VECTOR 区域后的文件级 guard
Tanxl_InsertAction.cpp #include "Tanxl_InsertAction.h"
Tanxl_Console_List.h #ifndef IOSTREAM 区域后的文件级 guard
Tanxl_Console_List.cpp #include "TANXL_CONSOLE_LIST.h"
Tanxl_OpenGL_Draw.h #ifndef TANXL_DATABASE_H 外层包裹
Tanxl_OpenGL_Render.h #ifndef GL_GLEW_H 外层包裹

Tanxl_Console_List.cpp#include 同时修正了文件名大小写:"TANXL_CONSOLE_LIST.h""Tanxl_Console_List.h"


影响范围总览

文件 旧版行数 新版行数 变更类型
Tanxl_OpenGL_Draw.h 155 64 修改(实现移出 + 移除 Height/Width/IEB 成员)
Tanxl_OpenGL_Draw.cpp - 97 新增(init/display/mainLoop 实现)
Tanxl_OpenGL_Render.h 166 162 修改(全局函数封装进 class OR)
Tanxl_DataBase.h 153 153 修改(IC_Vector/exac 改为指针类型)
Tanxl_DataBase.cpp 616 620 修改(适配指针访问 + 构造函数 new 初始化)
main.cpp 50 63 修改(新增 DataBase 测试例程)
Tanxl_GameState.h 85 87 修改(#pragma once)
Tanxl_GameState.cpp 214 216 修改(#pragma once + #include)
Tanxl_InsertAction.h 58 60 修改(#pragma once)
Tanxl_InsertAction.cpp 69 71 修改(#pragma once + #include)
Tanxl_Console_List.h 81 83 修改(#pragma once)
Tanxl_Console_List.cpp 165 168 修改(#pragma once + #include 大小写修正)
Update-Log.txt 80 86 修改(新增 Build-15 条目)
TANXL_ENGINE.vcxproj 197 198 修改(新增 Tanxl_OpenGL_Draw.cpp)

净代码量变化: +207行(OpenGL_Draw.cpp 新增 97行,DataBase 适配 +4行,main.cpp +13行,#pragma once +18行,Update-Log +6行,vcxproj +1行,Render 封装调整 -4行),-91行(OpenGL_Draw.h 实现移出)


技术要点总结

绘制模块的变量复用

init() 阶段需要 SHeight/SWidth 的 uniform 句柄,display() 阶段需要 SinCurrentTime/CosCurrentTime 的句柄。这两组句柄生命周期不重叠,Build-15 复用 PosA/PosB 两组成员存储,移除了原先独立的 Height/Width 成员。代价是每次进入 display()PosA/PosB 会被覆盖,需要重新查询------但 glGetUniformLocation 本就在 display() 中每帧调用,无额外开销。

DataBase 指针化的存储压力优化

原先 std::vector<Id_Vector*> 在扩容时会复制所有 Id_Vector* 指针(指针本身),而 Id_Vector 内嵌的 std::vector<Data_Vector*> exac 成员会随其父对象一起被复制------vector 复制涉及堆分配和元素迁移。改为指针类型后,IC_Vector 扩容仅复制一个指针,Id_Vector 对象本身不受影响。Id_Vector::exac 同理。

核心 API 说明
API/配置项 所属模块 说明
OR::createShaderProgram() OpenGL_Render 着色器程序创建(改为静态方法)
OR::readShaderFile() OpenGL_Render 着色器文件读取(改为静态方法)
OpenGL_Draw::OpenGL_Draw() OpenGL_Draw 构造函数(声明与实现分离)
TANXL_DataBase(bool) DataBase 构造时 new 初始化 IC_Vector
Id_Vector(int, int, ...) DataBase 构造时 new 初始化 exac

Wild_Chicken_Programing /// 2022-05-28 02:11

相关推荐
zhchyun20081 天前
# 【Unity UI 进阶】仿 Element UI 打造企业级 Unity UI 组件库(06)
ui·unity·游戏引擎
Behaviour2 天前
Unity游戏HybridCLR 热更新接入实战
游戏·unity·游戏引擎
王维志2 天前
UiSplineRenderer
unity·游戏引擎
k4m7v2pz2 天前
Godot 4 仿 agar.io:相机缩放被 max_zoom 卡死,窗口越大球越小的根因与修复
游戏引擎·godot·相机·缩放·clamp·camera2d
k4m7v2pz3 天前
Godot 4 窗口拉伸黑边与变形:stretch 配置全解析
数码相机·游戏引擎·godot·2d游戏·黑边·stretch·画面比例
Behaviour4 天前
Unity 手游网络同步技术
网络·unity·c#·游戏引擎
niuniudengdeng4 天前
Unity手游APK去广告实战:华为渠道包反编译、广告拦截与“网络不佳“弹窗修复全记录
unity·游戏引擎
k4m7v2pz4 天前
Godot 4 嵌入式试玩窗口尺寸与适配策略详解
编辑器·游戏引擎·godot·游戏开发·嵌入式运行
Behaviour4 天前
Unity UI循环列表UIScrollViewContent实现
ui·unity·c#·游戏引擎