https://wiki.libsdl.org/SDL3/FrontPage
1.01 创建窗口/绘图
#include <SDL.h>
#include <iostream>
int main(int argc, char* argv[]) {
// 1. 初始化SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cerr << "SDL 初始化失败: " << SDL_GetError() << std::endl;
return -1;
}
auto resoult = SDL_WasInit(SDL_INIT_VIDEO);
// 2. 创建窗口
SDL_Window* window = SDL_CreateWindow(
"SDL2 入门", // 窗口标题
SDL_WINDOWPOS_CENTERED, // X 位置(居中)
SDL_WINDOWPOS_CENTERED, // Y 位置
800, // 宽度
600, // 高度
SDL_WINDOW_SHOWN // 窗口标志
);
if (!window) {
std::cerr << "窗口创建失败: " << SDL_GetError() << std::endl;
SDL_Quit();
return -1;
}
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (!renderer) {
std::cerr << "渲染器创建失败: " << SDL_GetError() << std::endl;
SDL_DestroyWindow(window);
SDL_Quit();
return -1;
}
bool isquit = false;
SDL_Event event;
while (!isquit)
{
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT) {
isquit = true;
}
}
// 设置透明
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
// 设置背景色为蓝色
// - RGBA
// - CMYK - Red Yellow Blue
// - HSV
// - YUV
SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); // RGBA
SDL_RenderClear(renderer);
// 绘制一个点
SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255);
SDL_RenderDrawPoint(renderer, 100, 100);
SDL_Rect rect{ .x = 100, .y = 100, .w = 100, .h = 100 };
//SDL_RenderDrawRect(renderer, &rect);// 绘制矩形
SDL_RenderFillRect(renderer, &rect);// 绘制填充的矩形
// 等等。。。
SDL_RenderPresent(renderer);
}
// 4. 清理资源
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
1.02 SDL_Surface与SDL_Texture(绘制.bmp)
#include <SDL.h>
#include <iostream>
int main(int argc, char* argv[]) {
// 1. 初始化 SDL 子系统
// SDL_INIT_VIDEO 表示只初始化视频(窗口、渲染)子系统
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cerr << "SDL 初始化失败: " << SDL_GetError() << std::endl;
return -1;
}
// 获取成功初始化了 VIDEO 子系统
auto result = SDL_WasInit(SDL_INIT_VIDEO); // 返回已初始化的标志位
if (result & SDL_INIT_VIDEO) {
std::cout << "SDL 视频子系统已成功初始化" << std::endl;
}
// 2. 创建主窗口
// 参数说明:
// - 标题:"SDL2 入门"
// - x/y 位置:居中显示
// - 宽度、高度
// - 窗口标志:SDL_WINDOW_SHOWN(创建后立即显示)
SDL_Window* window = SDL_CreateWindow(
"SDL2 入门",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
800,
600,
SDL_WINDOW_SHOWN
);
// 检查窗口是否创建成功
if (!window) {
std::cerr << "窗口创建失败: " << SDL_GetError() << std::endl;
SDL_Quit(); // 清理 SDL 资源
return -1;
}
// 3. 创建渲染器(Renderer)
// 渲染器用于在窗口上绘制图形、纹理等
// - 关联窗口:window
// - 渲染驱动:-1(自动选择最佳驱动)
// - 标志:SDL_RENDERER_ACCELERATED(使用 GPU 加速)
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (!renderer) {
std::cerr << "渲染器创建失败: " << SDL_GetError() << std::endl;
SDL_DestroyWindow(window); // 销毁窗口
SDL_Quit();
return -1;
}
// 4. 加载 BMP 图像文件为 Surface(CPU 内存中的图像数据)
SDL_Surface* surface = SDL_LoadBMP("resources/number_8.bmp");
if (!surface) {
std::cerr << "图片加载失败: " << SDL_GetError() << std::endl;
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return -1;
}
// 获取图片原始宽度和高度
int w = surface->w;
int h = surface->h;
// 5. 将 Surface 转换为 Texture(GPU 内存中的纹理)
// Texture 可以被高效渲染到屏幕上
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
if (!texture) {
std::cerr << "纹理创建失败: " << SDL_GetError() << std::endl;
SDL_FreeSurface(surface); // 释放 Surface
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return -1;
}
// Surface 已经上传到 GPU,可以安全释放 CPU 端数据
SDL_FreeSurface(surface);
// 6. 主循环控制变量
float degree = 0; // 用于控制旋转角度(每帧递增)
bool isquit = false; // 控制主循环是否退出
SDL_Event event; // 用于存储事件
// 7. 主循环:持续渲染画面并处理事件
while (!isquit) {
// 事件处理:检查是否有用户输入或系统事件
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
isquit = true; // 用户点击关闭窗口,退出循环
}
}
// 8. 清屏:设置背景色为黑色,并清除渲染器内容
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // RGBA: 黑色不透明
SDL_RenderClear(renderer);
// 9. 更新逻辑:每帧旋转角度增加 1 度
degree += 1;
if (degree >= 360) degree -= 360; // 可选:保持角度在 0~360 范围内
// 10. 定义目标矩形(图片在屏幕上的显示位置和大小)
SDL_Rect dstrect;
dstrect.x = 200; // 左上角 X 坐标
dstrect.y = 200; // 左上角 Y 坐标
dstrect.w = w; // 宽度(使用原图宽度)
dstrect.h = h; // 高度(使用原图高度)
// 11. 设置旋转中心点(相对于纹理左上角)
SDL_Point rotateCenter = { w, h }; // 旋转中心设为右下角(w, h)
// 注意:如果想绕中心旋转,应设为 { w/2, h/2 }
// 12. 渲染纹理(多种方式,当前启用的是翻转渲染)
// 方式一:普通渲染(无旋转/翻转)
// SDL_RenderCopy(renderer, texture, NULL, &dstrect);
// 方式二:带旋转和中心点的渲染
// SDL_RenderCopyEx(renderer, texture, NULL, &dstrect, degree, &rotateCenter, SDL_FLIP_NONE);
// 方式三:当前启用 —— 垂直翻转渲染(上下翻转),无旋转
SDL_RenderCopyEx(renderer, texture, NULL, &dstrect, 0, NULL, SDL_FLIP_VERTICAL);
// 13. 显示渲染结果到屏幕(双缓冲机制)
// SDL_RenderPresent 将后台缓冲区内容交换到前台显示
SDL_RenderPresent(renderer);
// 可选:控制帧率,避免 CPU/GPU 过载
// SDL_Delay(16); // 约 60 FPS
}
// 14. 清理资源(重要!防止内存泄漏)
SDL_DestroyTexture(texture); // 销毁纹理
SDL_DestroyRenderer(renderer); // 销毁渲染器
SDL_DestroyWindow(window); // 销毁窗口
SDL_Quit(); // 关闭 SDL 子系统
return 0;
}
1.03 SDL_Surface与SDL_Texture(绘制一个区域)
#include <SDL.h>
#include <iostream>
int main(int argc, char* argv[]) {
// 1. 初始化 SDL 视频子系统
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cerr << "SDL 初始化失败: " << SDL_GetError() << std::endl;
return -1;
}
// 2. 创建窗口
// 窗口标题:"SDL2 入门"
// 位置:居中
// 尺寸:800x600
// 标志:显示 + 可调整大小
SDL_Window* window = SDL_CreateWindow(
"SDL2 入门",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
800,
600,
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE // 支持窗口缩放
);
// 3. 创建渲染器
// 第二个参数:-1 表示自动选择最佳渲染驱动
// 第三个参数:0 表示让 SDL 自动选择最佳渲染标志(可能是硬件加速)
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
if (!renderer) {
std::cerr << "渲染器创建失败: " << SDL_GetError() << std::endl;
SDL_DestroyWindow(window);
SDL_Quit();
return -1;
}
//SDL_Surface* surface_1 = SDL_CreateRGBSurfaceWithFormat(0, 200, 300, 16, SDL_PIXELFORMAT_RGB565);
//// 格式转换
//SDL_Surface* surface_new = SDL_ConvertSurfaceFormat(surface_1, SDL_PIXELFORMAT_RGBA8888, 0);
// 4. 创建一个 SDL_Surface(CPU 内存中的图像)
// 参数说明:
// - flags: 0(无特殊标志)
// - width: 200 像素
// - height: 300 像素
// - depth: 32 位色深(RGBA 各占 8 位)
// - format: 使用 RGBA8888 格式(每个像素 4 字节)
SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormat(
0, // flags
200, // 宽
300, // 高
32, // 位深
SDL_PIXELFORMAT_RGBA8888 // 像素格式
);
// 检查是否创建成功
if (!surface) {
std::cerr << "Surface 创建失败: " << SDL_GetError() << std::endl;
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return -1;
}
// 5. 使用白色填充整个 Surface
// SDL_MapRGBA: 根据 surface 的像素格式,将 RGBA 值转换为对应整数
// NULL 表示填充整个区域
SDL_FillRect(surface, NULL, SDL_MapRGBA(surface->format, 255, 255, 255, 255));
// 6. 直接操作像素数据:将上半部分改为绿色
Uint32* ptr = (Uint32*)surface->pixels; // 获取像素数据起始指针(RGBA8888 下每像素 4 字节)
// pitch 是每行字节数(不是像素数),但这里我们知道是 200 * 4 = 800 字节
SDL_Log("pitch = %d", surface->pitch); // 输出:800(200 像素 * 4 字节)
// 循环修改前一半像素(上半图)为绿色
for (int i = 0; i < surface->w * surface->h / 2; i++) {
*ptr = SDL_MapRGBA(surface->format, 0, 255, 0, 255); // 绿色,不透明
ptr++; // 移动到下一个像素
}
// 7. 将 Surface 转换为 GPU 纹理(Texture)
// Texture 可被高效渲染到屏幕上
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
// 8. 释放 CPU 端的 Surface(数据已上传到 GPU)
SDL_FreeSurface(surface);
// 9. 查询纹理的原始尺寸(用于渲染时参考)
int w, h;
SDL_QueryTexture(texture, NULL, NULL, &w, &h); // 获取纹理宽高
SDL_Log("纹理尺寸: %d x %d", w, h); // 输出:200 x 300
// 10. 主循环控制变量
bool isquit = false;
SDL_Event event;
// 11. 主循环:事件处理 + 渲染
while (!isquit) {
// 事件轮询
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
isquit = true; // 用户点击关闭按钮
}
}
// 清屏:设置背景为黑色
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
// 定义目标渲染区域(dstrect)
SDL_Rect dstrect;
dstrect.x = 100; // 屏幕 X 坐标
dstrect.y = 100; // 屏幕 Y 坐标
dstrect.w = 200; // 宽度(与纹理一致)
dstrect.h = 300; // 高度(与纹理一致)
// 12. 渲染纹理到目标区域
SDL_RenderCopy(renderer, texture, NULL, &dstrect);
// 13. 重置渲染目标(确保渲染到屏幕)
// 在使用离屏渲染(Render Target)时需要,此处可省略,但保留无害
SDL_SetRenderTarget(renderer, NULL);
// 14. 显示渲染结果(双缓冲交换)
SDL_RenderPresent(renderer);
// 可选:控制帧率,避免 CPU 占用过高
// SDL_Delay(16); // 约 60 FPS
}
// 15. 清理资源(重要!防止内存泄漏)
SDL_DestroyTexture(texture); // 销毁纹理
SDL_DestroyRenderer(renderer); // 销毁渲染器
SDL_DestroyWindow(window); // 销毁窗口
SDL_Quit(); // 关闭 SDL 子系统
return 0;
}
1.04 SDL_Image拓展库,加载其他格式图片