SDL入门
其实像SDL、FFMPEG、Opencv 我都是从入门到放弃,我不知道入了几次门了都,用的时候就Google,用完就忘,每次都需要重新搜索关键字。所以后面我的学习过程我都要记录一下,包括我看别人的文章我也要记录下来,有时候记得在哪里看过就是找不到然后就是想用就是不会简直是一个while(true)
,废话不多说,开始SDL的入门记录吧。
Hello World
配置链接库什么的我就不写了,因为无数遍重复已经死死记住了。直接上代码,我参考了bilibili的一个Up主的视频1。
#include <iostream>
#include "SDL2/include/SDL.h"
const int screen_width = 800;
const int screen_height = 600;
int main(int, char**)
{
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window = SDL_CreateWindow("YourGame",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
screen_width, screen_height,
SDL_WINDOW_SHOWN);
SDL_Surface *surface = SDL_GetWindowSurface(window);
SDL_Surface* blackground_surface = SDL_LoadBMP("Hello.bmp");
SDL_BlitSurface(blackground_surface, NULL, surface, NULL);
SDL_UpdateWindowSurface(window);
SDL_Delay(3000);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
因为SDL输出文字是需要扩展功能,SDL本身是没有设计文字的功能,所以Hello World就先输出图片吧。后面我用到字体时我再补充吧。有兴趣的可以参考:SDL显示图像和文字2
上面代码可以看出几点:
- SDL初始化和SDL退出:
SDL_Init(SDL_INIT_VIDEO);
SDL_Quit();
- 创建Window和销毁窗口:
SDL_Window *window = SDL_CreateWindow("YourGame", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_width, screen_height, SDL_WINDOW_SHOWN);
SDL_DestroyWindow(window);
- 让窗口显示图片:
SDL_Surface *surface = SDL_GetWindowSurface(window); SDL_Surface* blackground_surface = SDL_LoadBMP("Hello.bmp"); SDL_BlitSurface(blackground_surface, NULL, surface, NULL); SDL_UpdateWindowSurface(window)
- 让窗口停留3秒:
SDL_Delay(3000);
各个函数参数的意义3 (在左侧搜索框输入自己要搜索的函数,入门可以跳过这段):
初始化函数SDL_Init
参数的意义: (initialize the SDL library)
Value | Description |
---|---|
SDL_INIT_TIMER | timer subsystem |
SDL_INIT_AUDIO | audio subsystem |
SDL_INIT_VIDEO | video subsystem; automatically initializes the events subsystem |
SDL_INIT_JOYSTICK | joystick subsystem; automatically initializes the events subsystem |
SDL_INIT_HAPTIC | haptic (force feedback) subsystem |
SDL_INIT_GAMECONTROLLER | controller subsystem; automatically initializes the joystick subsystem |
SDL_INIT_EVENTS | events subsystem |
SDL_INIT_EVERYTHING | all of the above subsystems |
SDL_INIT_NOPARACHUTE | compatibility; this flag is ignored |
创建函数SDL_CreateWindow
参数的意义: (create a window)
Parameter | Description |
---|---|
title | the title of the window, in UTF-8 encoding |
x | the x position of the window, SDL_WINDOWPOS_CENTERED, or SDL_WINDOWPOS_UNDEFINED |
y | the y position of the window, SDL_WINDOWPOS_CENTERED, or SDL_WINDOWPOS_UNDEFINED |
w | the width of the window, in screen coordinates |
h | the height of the window, in screen coordinates |
flags | 0, or one or more SDL_WindowFlags OR’d together; see Remarks for details |
Value of flags | Description |
---|---|
SDL_WINDOW_FULLSCREEN | fullscreen window |
SDL_WINDOW_FULLSCREEN_DESKTOP | fullscreen window at the current desktop resolution |
SDL_WINDOW_OPENGL | window usable with OpenGL context |
SDL_WINDOW_VULKAN | window usable with a Vulkan instance |
SDL_WINDOW_HIDDEN | window is not visible |
SDL_WINDOW_BORDERLESS | no window decoration |
SDL_WINDOW_RESIZABLE | window can be resized |
SDL_WINDOW_MINIMIZED | window is minimized |
SDL_WINDOW_MAXIMIZED | window is maximized |
SDL_WINDOW_INPUT_GRABBED | window has grabbed input focus |
SDL_WINDOW_ALLOW_HIGHDPI | window should be created in high-DPI mode if supported (>= SDL 2.0.1) |
拷贝绘制函数SDL_BlitSurface
参数的意义: (copy surface to destination surface)
Parameter | Description |
---|---|
src | the SDL_Surface structure to be copied from |
srcrect | the SDL_Rect structure representing the rectangle to be copied, or NULL to copy the entire surface |
dst | the SDL_Surface structure that is the blit target |
dstrect | the SDL_Rect structure representing the rectangle that is copied into |
SDL 官方的 Hello world4
if (SDL_Init(SDL_INIT_VIDEO) != 0){
std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
return 1;
}
SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
if (win == nullptr){
std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (ren == nullptr){
SDL_DestroyWindow(win);
std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
std::string imagePath = getResourcePath("Lesson1") + "hello.bmp";
SDL_Surface *bmp = SDL_LoadBMP(imagePath.c_str());
if (bmp == nullptr){
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
std::cout << "SDL_LoadBMP Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);
SDL_FreeSurface(bmp);
if (tex == nullptr){
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
std::cout << "SDL_CreateTextureFromSurface Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
//A sleepy rendering loop, wait for 3 seconds and render and present the screen each time
for (int i = 0; i < 3; ++i){
//First clear the renderer
SDL_RenderClear(ren);
//Draw the texture
SDL_RenderCopy(ren, tex, NULL, NULL);
//Update the screen
SDL_RenderPresent(ren);
//Take a quick break after all that hard work
SDL_Delay(1000);
}
SDL_DestroyTexture(tex);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
官方的Hello world中和我参考Bilibili Up主的Hello world 有很多不一样的地方,主要突出在错误判断和SDL2和SDL1.2的函数调用。Renderer、Texture 是SDL2新引入的方法,这个在Bilibili Up主后面的视频中也有提到。鉴于本篇文章主题为SDL Hello World,我意在将Hello world 写完整,让其他人入手时可以分清楚你参考的文章是使用的SDL2还是SDL1.2。
关于错误判断的写法风格,我个人觉得这类写法偏向C的风格,这里没有批评与鼓励这种方式,我认为这类写法可以视学习阶段,和开发程度来自己把控这个,学习阶段我不建议过分的进行错误判断,主要目的是以程序跑通可用为主,小型项目也不应该过分关注错误判断,只有在大一点的项目中可以使用这种方式来进行安全检查,毕竟当If分支增多时,进行Code coverage会导致整个coverage下降,到时想提高可不是一件容易的事情。
SDL2 Hello world 中新语法:
- 使用Renderer 来绑定 Window 进行渲染:
SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); SDL_DestroyRenderer(ren);
- 用Texture来使Surface对Renderer 进行纹理表述:
SDL_Surface *bmp = SDL_LoadBMP(imagePath.c_str()); SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp); SDL_FreeSurface(bmp);
- 对Renderer进行Copy以及显示:
SDL_RenderClear(ren); SDL_RenderCopy(ren, tex, NULL, NULL); SDL_RenderPresent(ren);
创建函数SDL_CreateRenderer
参数的意义: (create a texture from an existing surface)
Parameter | Description |
---|---|
window | the window where rendering is displayed |
index | the index of the rendering driver to initialize, or -1 to initialize the first one supporting the requested flags |
flags | 0, or one or more SDL_RendererFlags OR’d together; see Remarks for details |
Value of flags | Description |
---|---|
SDL_RENDERER_SOFTWARE | the renderer is a software fallback |
SDL_RENDERER_ACCELERATED | the renderer uses hardware acceleration |
SDL_RENDERER_PRESENTVSYNC | present is synchronized with the refresh rate |
SDL_RENDERER_TARGETTEXTURE | the renderer supports rendering to texture |
创建函数SDL_CreateTextureFromSurface
参数的意义: (create a texture from an existing surface)
Parameter | Description |
---|---|
renderer | the rendering context |
surface | the SDL_Surface structure containing pixel data used to fill the texture |
在看SDL_CreateTextureFromSurface
函数的官方文档时,看到官方的例子里使用SDL_CreateRGBSurface
创建surface,所以我再列举一下Surface的创建方法:
Function Name | Description |
---|---|
SDL_ConvertSurface | copy an existing surface into a new one that is optimized for blitting to a surface of a specified pixel format. |
SDL_ConvertSurfaceFormat | copy an existing surface to a new surface of the specified format. |
SDL_CreateRGBSurface | allocate a new RGB surface. |
SDL_CreateRGBSurfaceFrom | allocate a new RGB surface with existing pixel data. |
SDL_CreateRGBSurfaceWithFormat | allocate an RGB surface. |
SDL_GetWindowSurface | get the SDL surface associated with the window. |
SDL_LoadBMP | load a surface from a BMP file. |
SDL_LoadBMP_RW | load a BMP image from a seekable SDL data stream (memory or file). |
上面的方法主要集中在SDL_video.h
和SDL_surface.h
两个文件中,其中我加粗部分函数需要与函数SDL_FreeSurface
成对出现。
[正月点灯笼] SDL图形编程入门 :https://space.bilibili.com/24014925/channel/detail?cid=12629 ↩︎
[skywalker_leo] SDL显示图像和文字 :https://blog.csdn.net/skywalker_leo/article/details/42776377 ↩︎
[SDL官方文档] :https://wiki.libsdl.org ↩︎
[SDL官方教程] :https://www.willusher.io/sdl2%20tutorials/2013/08/17/lesson-1-hello-world ↩︎