拿示例改一改 —— 从照着跑到自己扩展
三步改示例法
第一步:确认能跑
拿到示例代码后,原封不动先编译运行一次,确认它在你的环境里能正确工作。
这个环节看起来浪费时间但非常重要:
- 验证你的库都装对了
- 验证 CMake / 编译器配置没问题
- 排除「示例在我这编译不过」的环境因素
如果原示例编译不过,先解决环境问题(装库、调 CMake),再改代码。
第二步:做最小改动(变色、改字、换尺寸)
在原示例能跑的基础上,做最小幅度的修改:
- 把背景颜色从黑色改成蓝色
- 把显示的文字从「Hello」改成「Cxxdroid」
- 把 SDL_Rect 的宽高从 100×100 改成 200×50
每次改完编译运行一次,确认效果符合预期。这个步骤帮你建立「代码改动 → 效果变化」的直觉。
第三步:做结构性修改(加功能、拆文件、加库)
等你对示例结构熟悉之后,可以:
- 加一个新功能:在 Hello World 上加入一个用户输入的数字,显示它的平方
- 拆分文件:把一个 200 行的 SDL 示例拆成 main.cpp + game.cpp + render.cpp
- 引入新库:在 SDL 示例里加上 SDL_image 来加载图片
- 替换数据来源:把硬编码的数据改成从 SQLite 读取
这个步骤才是真正的「学习」——你在修改的过程中会遇到编译错误、链接错误、运行时错误,每解决一个就是真实的能力提升。
实战示例:从 Hello World 到可交互的小程序
目标:把内置的 Hello World 示例改成一个「点击屏幕显示当前坐标」的 SDL2 小程序。
阶段 1:确认 Hello World 能跑
#include <SDL2/SDL.h>
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *win = SDL_CreateWindow("Hello",
0, 0, 320, 480, SDL_WINDOW_SHOWN);
SDL_Renderer *ren = SDL_CreateRenderer(win, -1, 0);
SDL_SetRenderDrawColor(ren, 255, 0, 0, 255); // 红色
SDL_RenderClear(ren);
SDL_RenderPresent(ren);
SDL_Delay(2000);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
阶段 2:加事件循环 + 触摸处理
bool running = true;
SDL_Event event;
int dotX = 160, dotY = 240;
while (running) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) running = false;
if (event.type == SDL_FINGERDOWN) {
dotX = event.tfinger.x * 320;
dotY = event.tfinger.y * 480;
}
}
// 画背景
SDL_SetRenderDrawColor(ren, 30, 30, 30, 255);
SDL_RenderClear(ren);
// 画点
SDL_SetRenderDrawColor(ren, 255, 255, 0, 255);
SDL_Rect dot = {dotX - 5, dotY - 5, 10, 10};
SDL_RenderFillRect(ren, &dot);
SDL_RenderPresent(ren);
}
阶段 3:加图片加载(引入 SDL_image)
#include <SDL2_image/SDL_image.h>
// 初始化 SDL_image
IMG_Init(IMG_INIT_PNG);
// 加载一张图片
SDL_Surface *surf = IMG_Load("../test.png");
SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, surf);
SDL_FreeSurface(surf);
// 渲染图片而不是画矩形
SDL_Rect dst = {dotX - 32, dotY - 32, 64, 64};
SDL_RenderCopy(ren, tex, nullptr, &dst);
// 释放
SDL_DestroyTexture(tex);
IMG_Quit();
阶段 4(可选):拆成多文件项目
项目/
├── CMakeLists.txt
├── src/
│ ├── main.cpp —— 主循环和事件
│ ├── game.cpp/h —— 游戏逻辑(点的移动)
│ └── render.cpp/h —— 渲染逻辑
└── images/
└── dot.png
每个文件独立编译,改哪个就只重编哪个。
踩坑也是学习的一部分
改示例的过程中你一定会遇到:
- 忘记清理 SDL 资源(内存泄漏)
- 文件路径写错(图片加载失败)
- CMake 忘加 find_package(链接错误)
- 触摸事件的坐标转换错了(点不在手指位置)
不要跳过、不要复制粘贴别人的修复——自己 Google、自己调试、自己解决。每踩一个坑再爬出来,Cxxdroid 的熟练度就上一个台阶。