SDL2 基础绘图 —— 矩形、圆、线条怎么画
渲染器(Renderer)的概念
SDL2 的图形渲染用的是渲染器模式——你所有的绘制操作都发往一个 SDL_Renderer,它会把这些操作批量提交给 GPU 硬件加速执行。
核心流程:
1. 创建窗口和渲染器
2. 每帧循环:
a. 清空上一帧
b. 画所有图形
c. Present(提交到屏幕)
3. 销毁渲染器和窗口
画点
SDL_SetRenderDrawColor(ren, 255, 255, 255, 255); // 白色
SDL_RenderDrawPoint(ren, 160, 240); // 在屏幕中央画一个白点
批量画点效率更高:
SDL_Point points[] = {{100, 100}, {150, 150}, {200, 100}};
SDL_RenderDrawPoints(ren, points, 3);
画直线
SDL_SetRenderDrawColor(ren, 0, 255, 0, 255); // 绿色
SDL_RenderDrawLine(ren, 50, 50, 200, 300);
画矩形
矩形边框:
SDL_SetRenderDrawColor(ren, 0, 0, 255, 255);
SDL_Rect rect = {50, 50, 100, 80}; // x, y, w, h
SDL_RenderDrawRect(ren, &rect);
矩形填充:
SDL_RenderFillRect(ren, &rect);
批量矩形(适合粒子效果或网格):
SDL_Rect rects[100];
// ... 填充 rects 数组 ...
SDL_RenderFillRects(ren, rects, 100);
画圆(需要 SDL_gfx)
SDL2 核心库不直接提供圆的绘制——需要额外的扩展库 SDL_gfx。
如果 Cxxdroid 仓库里有 SDL_gfx(部分版本预装),可以这样画圆:
#include <SDL2/SDL2_gfxPrimitives.h>
circleRGBA(ren, 160, 240, 50, 255, 200, 0, 255);
如果没有 SDL_gfx,自己实现一个简单的圆填充也不难:用 Bresenham 算法算圆上每个点,然后调用 SDL_RenderDrawPoint 批量画出来。
设置颜色
每个绘制调用前都需要设置一次绘制颜色:
SDL_SetRenderDrawColor(ren, R, G, B, A);
R/G/B/A 各占 0-255,A 是透明度(255 = 不透明)。后续所有绘制操作都用这个颜色,直到下次修改。
清屏
每帧开头通常要清空上一帧的内容:
SDL_SetRenderDrawColor(ren, 0, 0, 0, 255); // 黑色背景
SDL_RenderClear(ren);
如果不清空直接在上面画,会产生残影(拖尾效果)——有时候这是你想要的(星空效果),但大多数游戏需要先清屏。
Present:提交帧
所有绘制操作完成后,调用一次:
SDL_RenderPresent(ren);
这一步才会真正把绘制内容提交到屏幕。如果忘记 present,屏幕上什么都不会显示。
完整示例:画一面小旗
#include <SDL2/SDL.h>
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *win = SDL_CreateWindow("Flag",
0, 0, 320, 480, SDL_WINDOW_SHOWN);
SDL_Renderer *ren = SDL_CreateRenderer(win, -1, 0);
// 背景
SDL_SetRenderDrawColor(ren, 240, 240, 240, 255);
SDL_RenderClear(ren);
// 旗杆
SDL_SetRenderDrawColor(ren, 80, 80, 80, 255);
SDL_RenderDrawLine(ren, 80, 40, 80, 440);
// 红旗
SDL_SetRenderDrawColor(ren, 220, 30, 30, 255);
SDL_Rect flag = {80, 40, 150, 100};
SDL_RenderFillRect(ren, &flag);
SDL_RenderPresent(ren);
SDL_Delay(3000);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}