挂机放置类游戏开发学习历程
\(\Large \mathcal{ImGUI}\)
我准备以 \(C++\) 为核心(也只用 \(C++\) )来完成这一学习流程,先要学习的是 ImGUI 这一前端库。使用 AI 生成了一份可能需要的学习流程图。
| 阶段 | 学习目标(核心) | 具体落地要求(适配挂机游戏) |
|---|---|---|
| 环境搭建 | 完成 ImGUI + 图形库(SDL2/GLFW)环境配置;理解 ImGUI 渲染核心流程 | 编译运行官方 SDL2+ImGUI 示例;能独立写出 “空 ImGUI 窗口” 的完整代码 |
| 基础组件 | 编译运行官方 SDL2+ImGUI 示例; 能独立写出 “空 ImGUI 窗口” 的完整代码 | 用 Text 显示 “金币 / 等级 / 每秒收益”;用 Button 实现 “收取金币 / 升级建筑”;用 ProgressBar 展示挂机进度 |
| UI 布局 | 掌握窗口、分组、行列布局;能固定 / 调整 UI 位置和样式 | 搭建 “挂机主面板 + 设置面板” 双窗口;整齐排版数值和按钮,适配游戏界面 |
| 逻辑联动 | 实现 UI 与游戏变量双向绑定;掌握定时器 + UI 实时刷新 | 点击按钮修改金币 / 收益数值,UI 即时更新;实现 “每秒自动加金币” 并刷新显示 |
| 进阶交互 | 掌握提示文本、禁用按钮、弹窗; 实现简单的存档 / 读档 UI | 金币不足时按钮禁用 + 红色提示;点击 “存档” 弹出确认弹窗,显示存档成功 / 失败 |
| 项目整合 | 用 CMake 管理 ImGUI 项目编译;代码模块化拆分 | 编写 CMakeLists.txt 整合 ImGUI 源码 + 游戏逻辑;将 UI 绘制、游戏逻辑拆分为独立函数 |
环境搭建:
完成 ImGUI + SDL2(OpenGL3)的环境搭建,编译运行第一个 ImGUI 窗口,理解 “窗口创建→ImGUI 上下文初始化→帧循环渲染” 的核心流程。
前置准备:
SDL2 开发库:https://www.libsdl.org/download-2.0.php
ImGUI 源码:https://github.com/ocornut/imgui
CMake:https://cmake.org/download/
步骤 1:文件目录结构搭建
imgui_idle_game/ # 项目根目录
├── CMakeLists.txt # CMake构建脚本
├── src/ # 源码目录
│ └── main.cpp # 主程序文件
└── third_party/ # 第三方库目录
├── imgui/ # ImGui源码(直接解压GitHub下载的文件)
│ ├── imgui.h
│ ├── imgui.cpp
│ ├── imgui_draw.cpp
│ ├── imgui_widgets.cpp
│ ├── imgui_tables.cpp
│ ├── imgui_sdl2.cpp # 后续复制的绑定文件
│ └── backends/ # ImGui官方后端(SDL2+OpenGL3)
└── sdl2/ # SDL2开发库(Windows需解压,Linux无需)
将下载的 ImGUI 源码解压到 third_party/imgui,保留 backends 目录(核心是 imgui_impl_sdl2.h/.cpp 和 imgui_impl_opengl3.h/.cpp);
Windows 下将 SDL2 开发库解压到 third_party/sdl2,确保包含 include(头文件)和 lib(库文件)目录;Linux 下无需手动放置,通过包管理器安装后 CMake 可自动找到。
步骤 2:编写 CMakeLists.txt
# 指定CMake最低版本
cmake_minimum_required(VERSION 3.16)
# 项目名称(挂机游戏)
project(imgui_idle_game)
# 设置C++标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 1. 查找SDL2库(Linux自动找,Windows需指定路径)
if (WIN32)
# Windows下SDL2的路径(根据自己的解压位置调整)
set(SDL2_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/third_party/sdl2/include)
set(SDL2_LIB_DIR ${CMAKE_SOURCE_DIR}/third_party/sdl2/lib/x64)
include_directories(${SDL2_INCLUDE_DIR})
link_directories(${SDL2_LIB_DIR})
else()
# Linux下自动查找SDL2
find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})
endif()
# 2. 包含ImGUI头文件目录
include_directories(${CMAKE_SOURCE_DIR}/third_party/imgui)
include_directories(${CMAKE_SOURCE_DIR}/third_party/imgui/backends)
# 3. 收集所有源码文件
set(SOURCE_FILES
src/main.cpp
# ImGui核心源码
third_party/imgui/imgui.cpp
third_party/imgui/imgui_draw.cpp
third_party/imgui/imgui_widgets.cpp
third_party/imgui/imgui_tables.cpp
# ImGui与SDL2/OpenGL3的绑定文件
third_party/imgui/backends/imgui_impl_sdl2.cpp
third_party/imgui/backends/imgui_impl_opengl3.cpp
)
# 4. 生成可执行文件
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
# 5. 链接库文件
if (WIN32)
# Windows下链接SDL2和OpenGL
target_link_libraries(${PROJECT_NAME} SDL2.lib SDL2main.lib opengl32.lib)
else()
# Linux下链接SDL2和OpenGL
target_link_libraries(${PROJECT_NAME} ${SDL2_LIBRARIES} GL)
endif()
步骤 3:编写 main.cpp
在 src/main.cpp 中写入以下代码(核心流程拆解,适配新手理解):
#include <SDL.h>
#include <gl/GL.h> // Windows
// #include <GL/gl.h> // Linux需替换此行
#include "imgui.h"
#include "imgui_impl_sdl2.h"
#include "imgui_impl_opengl3.h"
int main(int argc, char* argv[]) {
// ========== 步骤1:初始化SDL2窗口 ==========
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) {
printf("SDL初始化失败: %s\n", SDL_GetError());
return -1;
}
// 设置OpenGL版本(3.2核心版,兼容大部分设备)
const char* glsl_version = "#version 150"; // OpenGL 3.2
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
// 创建SDL窗口
SDL_Window* window = SDL_CreateWindow(
"挂机游戏ImGUI测试", // 窗口标题
SDL_WINDOWPOS_CENTERED, // 窗口位置
SDL_WINDOWPOS_CENTERED,
800, 600, // 窗口大小
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE // 启用OpenGL+可调整大小
);
SDL_GLContext gl_context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, gl_context);
SDL_GL_SetSwapInterval(1); // 开启垂直同步
// ========== 步骤2:初始化ImGUI上下文 ==========
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // 启用键盘导航
// 设置ImGUI样式(默认样式即可)
ImGui::StyleColorsDark();
// 初始化ImGUI与SDL2/OpenGL3的绑定
ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
ImGui_ImplOpenGL3_Init(glsl_version);
// ========== 步骤3:主循环(核心) ==========
bool running = true;
while (running) {
// 1. 处理SDL事件(窗口关闭、鼠标/键盘输入)
SDL_Event event;
while (SDL_PollEvent(&event)) {
ImGui_ImplSDL2_ProcessEvent(&event);
if (event.type == SDL_QUIT)
running = false;
}
// 2. 开始ImGUI帧(必须在绘制UI前调用)
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplSDL2_NewFrame(window);
ImGui::NewFrame();
// 3. 绘制ImGUI UI(核心:这里写挂机游戏的UI)
ImGui::Begin("挂机游戏主面板"); // 创建一个窗口
ImGui::Text("Hello, 挂机游戏!"); // 显示文本
ImGui::Text("当前金币:0"); // 模拟挂机游戏数值
ImGui::Button("收取金币"); // 模拟交互按钮
ImGui::End(); // 结束窗口绘制
// 4. 渲染ImGUI
ImGui::Render();
glClearColor(0.2f, 0.2f, 0.2f, 1.0f); // 背景色
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
SDL_GL_SwapWindow(window); // 交换缓冲区(显示画面)
}
// ========== 步骤4:清理资源 ==========
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
SDL_GL_DeleteContext(gl_context);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
步骤 4:编译运行
打开终端,进入项目根目录;
创建 build 目录并编译
mkdir build && cd build
cmake .. -G "MinGW Makefiles"
mingw32-make
将 SDL2 的动态库(SDL2.dll)复制到build目录(从third_party/sdl2/lib/x64复制);
运行程序:./imgui_idle_game.exe。
步骤 5:验证与排错
运行程序后,弹出 800×600 的窗口,窗口内显示 “挂机游戏主面板”,包含文本和按钮,无报错。
SDL2 头文件未找到:检查 CMake 中 SDL2_INCLUDE_DIR 路径;
链接时找不到 SDL2.lib:确保 SDL2_LIB_DIR 指向 x64(或 x86)目录,且链接了 SDL2.lib 和 SDL2main.lib;
OpenGL 版本不兼容:修改 glsl_version 为对应版本(如 OpenGL 2.1 用#version 120);
ImGUI 函数未定义:检查 CMake 是否包含了所有 ImGUI 源码文件(如 imgui_draw.cpp).

浙公网安备 33010602011771号