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

TEnGinE Version-0.1 Build-11 更新日志

发布日期: 2022-05-15 22:43

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

更新类型: 模块重构与功能扩展


变更概要

类别 内容
架构重构 Utils类拆解,Shader渲染函数独立为Tanxl_OpenGL_Render模块
功能新增 GameObjectBase新增FinishComponment()一键执行所有组件功能
功能新增 新增LocationBase类提供2D坐标基础组件
数据结构增强 StateUnit新增构造函数、移动目标标记及GetMoveT()访问器
代码修复 CompileState()中Reader变量作用域修正,修复字符串拼接丢失Bug
接口精简 UniqueID模块Uniqt数组移入类私有成员,减少全局命名空间污染

一、渲染模块重构(架构整理)

本次更新将 Utils 工具类拆解,移除类的包裹,使 Shader 工具函数以独立全局函数的形式存在,同时消除 using namespace std 语句,所有标准库类型改为显式 std:: 前缀。

1.1 移除 Utils 类(Utils.h / Utils.cpp)

Utils 原为一个纯静态方法类,包含 readShaderFile()prepareShader()createShaderProgram() 等 Shader 编译工具函数。该类仅为函数容器,无状态管理需求,静态类的设计增加了不必要的调用层级。

cpp 复制代码
// Build-10 (Utils.h)
class Utils
{
private:
    static std::string readShaderFile(const char *filePath);
    static GLuint prepareShader(int shaderTYPE, const char *shaderPath);
    // ... 其余静态方法
public:
    static GLuint createShaderProgram(const char *vp, const char *fp);
};
cpp 复制代码
// Build-10 调用方式 (Tanxl_OpenGL_Draw.h)
renderingProgram = Utils::createShaderProgram("vertShader.glsl", "fragShader.glsl");

Utils.cpp 中实现使用了 using namespace std;,所有 std:: 前缀被省略。

1.2 新增 Tanxl_OpenGL_Render.h(独立函数模块)

Utils 中的全部 Shader 工具函数提取为独立全局函数,存放于新文件 Tanxl_OpenGL_Render.h

cpp 复制代码
// Build-11 (Tanxl_OpenGL_Render.h)
std::string readShaderFile(const char* filePath);
void printShaderLog(GLuint shader);
void printProgramLog(int prog);
GLuint prepareShader(int shaderTYPE, const char* shaderPath);
int finalizeShaderProgram(GLuint sprogram);
bool checkOpenGLError();
GLuint createShaderProgram(const char* vp, const char* fp);
cpp 复制代码
// Build-11 调用方式 (Tanxl_OpenGL_Draw.h)
renderingProgram = createShaderProgram("vertShader.glsl", "fragShader.glsl"); // ← 修改:移除 Utils:: 前缀

所有函数实现中 using namespace std; 已移除,改为显式 std:: 前缀:

函数 Build-10 (Utils.cpp) Build-11 (Tanxl_OpenGL_Render.h)
readShaderFile string content; ifstream fileStream(...) std::string content; std::ifstream fileStream(...)
checkOpenGLError cout << "glError: " << glErr << endl; std::cout << "glError: " << glErr << std::endl;
全局命名空间 using namespace std; 已移除

二、GameObject 组件系统(功能扩展)

2.1 新增 FinishComponment()(Tanxl_GameObject.h)

GameObjectBase 新增一键执行所有组件的函数,遍历组件列表依次调用每个组件的 Special() 虚函数。

cpp 复制代码
// Build-11 新增
void GameObjectBase::FinishComponment()
{
    for (int i = 0; i < CMB.size(); i++)
        CMB.at(i)->Special();
}
项目 Build-10 Build-11
GameObjectBase 公开方法 AppendComponment, RemoveComponment AppendComponment, RemoveComponment, FinishComponment

该函数实现了组件模式的"一键执行"语义,遍历 CMB 容器中的每个 ComponmentBase*,调用多态的 Special() 方法。


三、LocationBase --- 2D 坐标基础组件(新模块)

新增 Tanxl_LocationBase.h,提供一个轻量级 2D 位置组件。

cpp 复制代码
// Build-11 新增文件 Tanxl_LocationBase.h
class LocationBase
{
public:
    void Set_LocationBase(float LocX, float LocY);
private:
    float Location_x;
    float Location_y;
};

void LocationBase::Set_LocationBase(float LocX, float LocY)
{
    Location_x = LocX;
    Location_y = LocY;
}
项目 Build-10 Build-11
Tanxl_LocationBase.h 不存在 新增(18行)
类名 - LocationBase
接口 - Set_LocationBase(float, float)

该模块源于嵌入式的学习心得,为后续物理/碰撞系统提供统一的位置表达。


四、GameState 模块(数据增强与 Bug 修复)

4.1 StateUnit 新增构造函数与移动目标标记

StateUnit 类新增带参构造函数,并引入 Is_Move_Target 布尔成员标识该单元格是否可作为移动目标。

cpp 复制代码
// Build-10 (Tanxl_GameState.h)
class StateUnit
{
public:
    void SetEvent(std::string GameEventName);
private:
    GameEvent* GameEvents;
};
cpp 复制代码
// Build-11 (Tanxl_GameState.h)
class StateUnit
{
public:
    StateUnit(GameEvent* GE = NULL, bool MoveTarget = true); // ← 新增:默认构造函数
    void SetEvent(std::string GameEventName);
    bool GetMoveT();                                         // ← 新增:获取移动目标标记
private:
    GameEvent* GameEvents;
    bool Is_Move_Target;                                     // ← 新增:移动目标标记
};
cpp 复制代码
// Build-11 构造函数实现 (Tanxl_GameState.cpp)
StateUnit::StateUnit(GameEvent* GE, bool MoveTarget)
    :Is_Move_Target(MoveTarget), GameEvents(GE) {}

bool StateUnit::GetMoveT()
{
    return this->Is_Move_Target;
}
项目 Build-10 Build-11
StateUnit 构造函数 无(使用编译器默认生成) StateUnit(GameEvent*, bool)
移动目标标记 Is_Move_Target(默认 true)
查询接口 GetMoveT()
4.2 CompileState() --- Reader 作用域 Bug 修复

CompileState() 中存在一个隐蔽 Bug:Reader 字符串变量在 for 循环体内声明,每次迭代被重新初始化为空串,导致 += 拼接操作无效,累计的字符在下次循环中被清空。

cpp 复制代码
// Build-10 --- Bug 版本
void GameStateBase::CompileState(std::string Infor)
{
    for (int i = 0, SetCount = 0; i < Infor.size(); i++)
    {
        std::string Reader{};            // ← Bug: 每次循环清零
        if (Infor.at(i) != ',')
            Reader += Infor.at(i);       // 拼接无效
        else
        {
            this->GameState.at(SetCount++)->SetEvent(Reader);
            Reader = "";
        }
    }
}
cpp 复制代码
// Build-11 --- 修复版本
void GameStateBase::CompileState(std::string Infor)
{
    std::string Reader{};                // ← 修复: 声明移至循环外部
    for (int i = 0, SetCount = 0; i < Infor.size(); i++)
    {
        if (Infor.at(i) != ',')
            Reader += Infor.at(i);       // 拼接正常生效
        else
        {
            this->GameState.at(SetCount++)->SetEvent(Reader);
            Reader = "";
        }
    }
}
项目 Build-10 Build-11
Reader 声明位置 for 循环体内 for 循环体前
字符串拼接是否正确 否(每轮清零)
Bug 影响 逗号分隔解析完全失败 正常解析

五、UniqueID 模块(接口精简)

Uniqt[62] 字符数组从全局命名空间移入 UniqueIdBase 类的私有成员区域,减少全局符号暴露。

cpp 复制代码
// Build-10 --- Uniqt 为全局数组
std::string Uniqt[62] = {
    {"1"}, {"2"}, /* ... */ {"Z"}
};

class UniqueIdBase { /* ... */ };
cpp 复制代码
// Build-11 --- Uniqt 移入类私有成员
class UniqueIdBase
{
public:
    // ... Generate() 保持不变
private:
    std::string Uniqt[62] = {          // ← 修改:移至私有成员
    {"1"}, {"2"}, /* ... */ {"Z"} };

    UniqueIdBase(){}
    // ...
};
项目 Build-10 Build-11
Uniqt 作用域 全局 UniqueIdBase::private
全局符号数 +1 0

六、Console_List 警告修复(Tanxl_Console_List.cpp)

Display() 函数中页面上限计算添加 static_cast<int>() 显式转换,消除有符号/无符号比较警告。

cpp 复制代码
// Build-10
for (... i < (Page+1)*(SSpace & 0x00ff); i++)

// Build-11
for (... i < (Page + 1) * static_cast<int>(SSpace & 0x00ff); i++)  // ← 修改

影响范围总览

文件 旧版行数 新版行数 变更类型
Utils.h 71 - 删除(Shader 工具函数迁移至 Tanxl_OpenGL_Render.h)
Utils.cpp 99 - 删除(实现迁移)
Tanxl_OpenGL_Render.h - 166 新增(独立 Shader 渲染函数模块)
Tanxl_LocationBase.h - 18 新增(2D 坐标基础组件)
Tanxl_OpenGL_Draw.h 160 160 修改(include 替换:Utils.h → Tanxl_OpenGL_Render.h + 调用前缀移除)
Tanxl_GameState.h 76 83 修改(StateUnit 新增构造函数、Is_Move_Target、GetMoveT())
Tanxl_GameState.cpp 170 178 修改(StateUnit 构造函数实现 + GetMoveT() + CompileState bug 修复)
Tanxl_GameObject.h 64 72 修改(GameObjectBase 新增 FinishComponment())
Tanxl_UniqueID.h 44 43 修改(Uniqt 移入类私有成员)
Tanxl_Console_List.cpp 165 165 修改(static_cast 警告修复,1行变更)
TANXL_ENGINE.vcxproj 197 197 修改(移除 Utils.h/cpp,新增 LocationBase + OpenGL_Render)

净代码量变化: +184 行(Tanxl_OpenGL_Render.h + LocationBase.h),-170 行(Utils.h + Utils.cpp 移除),+22 行(GameState/GameObject 增强),净增 +36 行。


技术要点总结

渲染模块架构演进
复制代码
Build-10 渲染调用链:
  Tanxl_OpenGL_Draw.h ──include──► Utils.h ──include──► Utils.cpp
       │                              │
       └── Utils::createShaderProgram()  (静态类方法调用)

Build-11 渲染调用链:
  Tanxl_OpenGL_Draw.h ──include──► Tanxl_OpenGL_Render.h (独立函数)
       │
       └── createShaderProgram()  (全局函数直接调用,无类前缀)
核心 API 说明
API/配置项 所属模块 说明
FinishComponment() GameObjectBase 遍历执行所有组件的 Special() 虚函数
StateUnit(GameEvent*, bool) StateUnit 带参构造函数,指定绑定事件与移动目标标记
GetMoveT() StateUnit 返回 Is_Move_Target 布尔值
Set_LocationBase(float, float) LocationBase 设置 2D 坐标
createShaderProgram(vp, fp) Tanxl_OpenGL_Render 全局函数,编译链接顶点/片元着色器
CompileState Bug 根因分析

CompileState()Reader 变量声明于 for 循环体内,std::string Reader{}; 在每个迭代周期重新构造为空字符串,导致 Reader += Infor.at(i); 的拼接操作被后续迭代的清空操作抵消。在遇到 ',' 分隔符时,SetEvent(Reader) 传入的是当前迭代周期内单个字符,而此前累积的字符已丧失。修复方案:将 Reader 声明提升至循环前,使其生命周期跨越整个解析过程。

Wild_Chicken_Programing /// 2022-05-15 22:43

相关推荐
玖玥拾1 小时前
Cocos学习笔记:武器系统与数据驱动UI联动
游戏引擎·cocos2d
10岁的博客2 小时前
IOI 2018 高速公路收费(Highway)题解:二分与树的巧妙结合
开发语言·c++
不知名的老吴2 小时前
C++运算符重载的常见注意点
开发语言·c++
弹简特2 小时前
【Java项目-轻聊】07-实现主页面模块
java·开发语言
Thecozzy2 小时前
写文档教 AI 用代码
开发语言·python
Hanniel2 小时前
装饰器 (中): 进阶篇,解锁框架级玩法
开发语言·python
于先生吖2 小时前
前后端分离人事招聘项目,校招宣讲预约+社招双向撮合功能架构设计教程
java·开发语言·uni-app
川冰ICE3 小时前
JavaScript进阶④|Symbol与元编程,对象的隐藏身份
开发语言·javascript·ecmascript
码界索隆3 小时前
Python转Java系列:作者有话说
java·开发语言·python