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

发布日期 :2022-05-08 23:03
内部版本号:v0.00.00.10


变更概要

类别 内容
删除文件 Tanxl_GameEvent.hTanxl_GameEvent.cppTanxl_InitBase.h
文件合并 GameEvent 模块整体并入 GameState 模块
输入集成 InsertEventBase 正式接入主循环,支持 WASD + 方向键
组件系统 GameObjectBase 新增组件添加功能,含同名去重检查
渲染调整 玩家方块与地图方块分离,网格尺寸固定化
头文件清理 Tanxl_OpenGL_Draw.h 移除冗余的外部库包含

一、GameEvent 模块并入 GameState

背景

Build-7 中 GameEventGameEventBase 定义在独立的 Tanxl_GameEvent.h/.cpp 文件中。Build-8 将这两个类的定义和实现分别合并到 Tanxl_GameState.hTanxl_GameState.cpp

合并后的 GameState.h 结构

cpp 复制代码
//_VERSION_0_2_
// LAST_UPDATE 2022-05-08 22:40

// 以下内容原属于 Tanxl_GameEvent.h
class GameEvent { ... };
class GameEventBase { ... };

// 原有内容
class StateUnit { ... };
class GameStateBase { ... };

GameState.cpp 新增内容

cpp 复制代码
// ============ GameEvent 实现(原在 Tanxl_GameEvent.cpp)============

GameEvent::GameEvent(std::string Name) : EventName(Name) {}
std::string GameEvent::GetEventName() { return this->EventName; }

void GameEventBase::RegistEvent(GameEvent* Event) { ... }
GameEvent* GameEventBase::GetGameEvent(std::string EventName) { ... }
GameEventBase& GameEventBase::GetEventBase() { ... }

// 构造/析构/拷贝控制函数实现...
// ================================================================

// 原有的 StateUnit / GameStateBase 实现保持不变

影响范围

项目 Build-7 Build-8
Tanxl_GameEvent.h 存在 已删除
Tanxl_GameEvent.cpp 存在 已删除
Tanxl_GameState.h 仅含 StateUnit/GameStateBase 含 GameEvent + StateUnit + GameStateBase
Tanxl_GameState.cpp 仅含 StateUnit/GameStateBase 实现 含全部三个类实现

二、输入系统接入主循环

这是 Build-8 最实质性的功能改动------InsertEventBase 从独立模块正式成为渲染循环的一部分。

Tanxl_OpenGL_Draw.h 变更

2.1 头文件精简
cpp 复制代码
// Build-7 --- 包含了这些:
#include <GL\glew.h>        // ← 移除
#include <GLFW\glfw3.h>      // ↓ 全部移除
#include <iostream>
#include <string>
#include <math.h>

// Build-8 --- 仅保留引擎内部头文件和必要系统头文件
#include "Tanxl_DataBase.h"
#include "Tanxl_GameState.h"
#include "Tanxl_InsertAction.h"
#include <math.h>
#include "Utils.h"

被移除的五个头文件(GLEW、GLFW、IOSTREAM、STRING、MATH_H)实际上已被上述引擎头文件间接包含或不再需要。

2.2 全局输入对象
cpp 复制代码
InsertEventBase* IEB = &InsertEventBase::GetInsertBase();

在全局作用域创建 InsertEventBase 单例指针,供 init()mainLoop() 共同使用。

2.3 init() 注册 8 个按键

这一部分的代码来源于我近期在嵌入式方面的学习。按键的初始化采用了类似STM32库函数GPIO初始化的方式。

cpp 复制代码
void init(GLFWwindow* window, GameStateBase* State) {
    // 上: UP + W
    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 + A (MoveLen 为负值)
    Key_Unit MOVE_LEFT;
    MOVE_LEFT.GLFW_KEY = GLFW_KEY_LEFT;  MOVE_LEFT.MoveLen = -0.01f;  MOVE_LEFT.MoveToX = true;
    IEB->RegistEvent(MOVE_LEFT);
    MOVE_LEFT.GLFW_KEY = GLFW_KEY_A;
    IEB->RegistEvent(MOVE_LEFT);

    // 右: RIGHT + D
    Key_Unit MOVE_RIGHT;
    MOVE_RIGHT.GLFW_KEY = GLFW_KEY_RIGHT;  MOVE_RIGHT.MoveLen = 0.01f;  MOVE_RIGHT.MoveToX = true;
    IEB->RegistEvent(MOVE_RIGHT);
    MOVE_RIGHT.GLFW_KEY = GLFW_KEY_D;
    IEB->RegistEvent(MOVE_RIGHT);

    // 下: DOWN + S (MoveLen 为负值)
    Key_Unit MOVE_DOWN;
    MOVE_DOWN.GLFW_KEY = GLFW_KEY_DOWN;  MOVE_DOWN.MoveLen = -0.01f;  MOVE_DOWN.MoveToY = true;
    IEB->RegistEvent(MOVE_DOWN);
    MOVE_DOWN.GLFW_KEY = GLFW_KEY_S;
    IEB->RegistEvent(MOVE_DOWN);

    // ... 其余初始化代码不变
}

按键映射表:

方向 主按键 备用键 步长
W Y +0.01
S Y -0.01
A X -0.01
D X +0.01
2.4 mainLoop() 简化
cpp 复制代码
// Build-7 的主循环(约50行手动按键处理代码)
while (!glfwWindowShouldClose(window)) {
    // ... 设置 uniform ...
    if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) {
        std::cout << "LEFT_PUSHED! ..." << endl;
        movex -= movespeed;
        // ... 重复4次方向键 + Z/X/C 键 ...
    }
    display(...);
}

// Build-8 的主循环
while (!glfwWindowShouldClose(window)) {
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);   // 新增:每帧清屏
    glClear(GL_COLOR_BUFFER_BIT);             // 新增

    PosX = glGetUniformLocation(renderingProgram, "MoveX");
    glProgramUniform1f(renderingProgram, PosX, movex);
    PosY = glGetUniformLocation(renderingProgram, "MoveY");
    glProgramUniform1f(renderingProgram, PosY, movey);

    IEB->GetInsert(window, &movex, &movey);  // 替代所有手动按键检测

    display(window, glfwGetTime());
    glfwSwapBuffers(window);
    glfwPollEvents();
}

变化量 :优化后的代码量大幅减少:主循环代码从约60行精简至约16行核心逻辑,同时移除了冗余的SpeedFlag变量,并优化了方向键及Z/X/C键的手动判断逻辑。


三、游戏对象组件系统完善

Tanxl_GameObject.h 变更

3.1 ComponmentBase 类
cpp 复制代码
// Build-7 --- 仅一个纯虚函数占位
class ComponmentBase
{
	virtual void SpecialAbility() = 0;
};

// Build-8 --- 增加了实际内容 但是还未正式应用
class ComponmentBase
{
public:
	ComponmentBase(std::string Name) :ComponmentName(Name) {}
	std::string GetName() { return this->ComponmentName; }
	virtual void Special() = 0;           // 重命名:SpecialAbility → Special
private:
	std::string ComponmentName;           // 新增:组件名称字段
};
3.2 GameObjectBase 类
cpp 复制代码
// Build-7 --- 空类体
class GameObjectBase
{
private:
	std::vector<ComponmentBase*> CMB;
};

// Build-8 --- 提供公共接口
class GameObjectBase
{
	bool AppendComponment(ComponmentBase* CM);  // 新增方法声明
private:
	std::vector<ComponmentBase*> CMB;
};

// 方法实现(内联在头文件中)
bool GameObjectBase::AppendComponment(ComponmentBase* CM)
{
	for (int i = 0; i < CMB.size(); i++)
		if (CMB.at(i)->GetName() == CM->GetName())
			return false;          // 同名组件拒绝添加
	CMB.push_back(CM);
	return true;
}

四、着色器改动:玩家方块分离

StatevertShader.glsl 核心变化

项目 Build-7 Build-8
网格尺寸 动态计算 (2.0f / SHeight) 固定值 0.2f
循环起点 i = 0 i = 1
VertexID 0~5 在循环内统一处理 循环外单独处理(玩家方块)
玩家方块 有,受 MoveX/MoveY 控制
第二顶点颜色 黄色 (1,1,0,1) 绿色 (0,1,0,1)
cpp 复制代码
// Build-8 关键结构
float Height = 0.2f;       // 固定尺寸
float Width  = 0.2f;

for(int i = 1; i < SHeight * SWidth; i++)  // 从1开始,跳过前6个顶点
{
    // 地图方块的网格排列逻辑(与 Build-7 相同)
}

// 玩家方块 ------ 独立于网格,可自由移动
if (gl_VertexID == 0) 
{ gl_Position = vec4(Width/2 + MoveX, -Height/2 + MoveY, 0.1, 1.0); vs_color = vec4(1.0, 0.8, 0.0, 1.0);}
else if (gl_VertexID == 1) 
{ gl_Position = vec4(-Width/2 + MoveX, -Height/2 + MoveY, 0.1, 1.0); vs_color = vec4(1.0, 1.0, 0.0, 1.0);}
// ... 2~5 同理

玩家方块的 z 坐标设为 0.1(地图方块为 0.0),确保绘制在最上层。


五、其他变更

文件 变更内容
main.cpp SetState(10, 10)SetState(1, 1)
Tanxl_InitBase.h 整个文件删除
TANXL_ENGINE.vcxproj 移除已删除文件的编译项引用


Wild_Chicken_Programing /// 2022-05-08 23:03

相关推荐
都在酒里1 小时前
Linux字符设备驱动开发(十):综合实例——I2C传感器 + LED智能控制与进阶指南
linux·运维·服务器·驱动开发·交互
●VON8 小时前
鸿蒙Flutter实战:分类管理页BottomSheet CRUD
数据库·flutter·华为·harmonyos·鸿蒙
Cosolar8 小时前
Chroma向量库面试学习指南
数据库·人工智能·面试·职场和发展·数据库架构
wanhengidc8 小时前
服务器租用有何优点
运维·服务器·安全·web安全
坤昱9 小时前
cfs调度类深入解刨——最新内核细节分析2
linux·服务器·cfs·cfs调度·eevdf调度·eevdf·kernel 7.1
艾莉丝努力练剑9 小时前
【Linux:文件】Ext系列文件系统进阶
linux·运维·服务器·c++·文件系统·文件io·ext
海市公约9 小时前
Linux核心基础命令与权限管理实战指南
linux·运维·服务器·vim·权限管理·系统监控·命令行
企服AI产品测评局9 小时前
Agent适配信创环境实测:企业级自动化如何实现国产操作系统与数据库全兼容?
运维·数据库·人工智能·ai·chatgpt·自动化
cfm_291410 小时前
Redis数据安全性解析
数据库·redis·缓存
DIY源码阁10 小时前
JavaSwing学生成绩管理系统 - MySQL版
java·数据库·mysql·eclipse