Simple DirectMedia Layer 是一个跨平台开发库 ,旨在通过OpenGL 和Direct3D 提供对音频、键盘、鼠标、操纵杆和图形硬件的低级访问 。它被视频播放软件、模拟器和流行游戏使用,包括Valve的获奖目录和许多Humble Bundle游戏。
SDL正式支持Windows、macOS、Linux、iOS和Android。 对其他平台的支持可以在源代码中找到。SDL是用C编写的,可以在C++中原生运行,并且有几种其他语言的绑定,包括C#和Python。
SDL基本使用方法
- 初始化/退出API SDL_Init/SDL_Quit()
- 创建窗口/释放窗口SDL_CreateWindow()/SDL_DestoryWindow()
- 创建渲染器 SDL_CreateRender()
使用例子
cpp
#include <SDL.h>
int main(int argc, char const *argv[])
{
// 初始化SDL
SDL_Init(SDL_INIT_VIDEO);
// 退出SDL
SDL_Quit();
return 0;
}
找到SDL2的动态连接库和头文件地址:
cpp
// 找到对应的链接库
pkg-config --libs sdl2
-L/usr/local/lib -Wl,-rpath,/usr/local/lib -Wl,--enable-new-dtags -pthread -lSDL2
cpp
// 找到对应的头文件
pkg-config --cflags --libs sdl2
-D_REENTRANT -I/usr/local/include/SDL2 -L/usr/local/lib -Wl,-rpath,/usr/local/lib -Wl,--enable-new-dtags -pthread -lSDL2
SDL进行渲染
- SDL_CreateRender/SDL_DestoryRenderer
- SDL_RenderClear 清空数据
- SDL_RenderPresent 把数据推送出去
例子:
cpp
#include <SDL.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
// 创建窗口
SDL_Window * window = NULL;
// 创建对应的渲染
SDL_Renderer * render = NULL;
// 初始化SDL
SDL_Init(SDL_INIT_VIDEO);
// 窗口的具体的创建过程
window = SDL_CreateWindow("SDL2 window",200,200,480,640,SDL_WINDOW_SHOWN);
if(window == NULL){
printf("Couldn't create SDL2 window\n");
goto __EXIT;
}
// 创建对应渲染
render = SDL_CreateRenderer(window,-1,0 );
if(!render){
printf("Couldn't create renderer");
goto __EXIT_WINDOWS;
}
// 推送Render
SDL_SetRenderDrawColor(render,255,255,0,50 );
// 清空render数据
SDL_RenderClear(render);
SDL_RenderPresent(render);
// 延时延时
SDL_Delay(3000);
// 销毁窗口
SDL_DestroyWindow(window);
__EXIT_WINDOWS:
// 销毁对应的render
SDL_DestroyWindow(window);
__EXIT:
// 退出SDL
SDL_Quit();
return 0;
}
编译结果:
SDL事件处理
SDL将所有的事件放在一个对应的事件的队列中 ,所有对事件的操作都是对队列的操作。
事件的类型
- SDL_WindowEvent : Window窗口相关的事件。
- SDL_KeyboardEvent : 键盘相关的事件。
- SDL_MouseMotionEvent : 鼠标移动相关的事件。
- SDL_QuitEvent : 退出事件。
- SDL_UserEvent : 用户自定义事件。
事件处理的类型
- SDL_PollEvent:传统事件的处理方式,以轮询的方式进行处理,事件的处理需要的进行进行事件周期,需要进行等待。
- SDL_WaitEvent:现代事件的处理方式,监听特定的时间,进行休眠等待,会阻塞
cpp
#include <SDL.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
int quit = 1;
// 创建窗口
SDL_Window * window = NULL;
// 创建对应的渲染
SDL_Renderer * render = NULL;
// 初始化SDL
SDL_Init(SDL_INIT_VIDEO);
// 窗口的具体的创建过程
window = SDL_CreateWindow("SDL2 window",200,200,480,640,SDL_WINDOW_SHOWN);
if(window == NULL){
printf("Couldn't create SDL2 window\n");
goto __EXIT;
}
// 创建对应渲染
render = SDL_CreateRenderer(window,-1,0 );
if(!render){
printf("Couldn't create renderer");
goto __EXIT_WINDOWS;
}
// 推送Render
SDL_SetRenderDrawColor(render,255,255,0,50 );
// 清空render数据
SDL_RenderClear(render);
SDL_RenderPresent(render);
// 事件处理
do{
SDL_Event event;
SDL_WaitEvent(&event);
switch(event.type){
case SDL_QUIT:
quit = 0;
break;
default:
SDL_Log("event type is: %d", event.type);
}
}while(quit);
// 销毁窗口
SDL_DestroyWindow(window);
__EXIT_WINDOWS:
// 销毁对应的render
SDL_DestroyWindow(window);
__EXIT:
// 退出SDL
SDL_Quit();
return 0;
}
该例子会打印各种事件类型。
纹理渲染
纹理用于图像信息的表示,占用内存很少,而且计算在的GPU中,之后通过显示。
常用API
- SDL_CreateTexture():创建纹理 format:对应的数据类型,access:访问类型 Target(常用),Stream(流式)
- SDL_DestoryTexture():销毁纹理
- SDL_SetRenderTarget :设置一个纹理作为当前渲染目标。
cpp
/**
* Set a texture as the current rendering target.
*
* Before using this function, you should check the
* `SDL_RENDERER_TARGETTEXTURE` bit in the flags of SDL_RendererInfo to see if
* render targets are supported.
*
* The default render target is the window for which the renderer was created.
* To stop rendering to a texture and render to the window again, call this
* function with a NULL `texture`.
*
* \param renderer 渲染上下文
* \param texture 目标纹理,必须使用.
* \returns 0 on success or a negative error code on failure; call
* SDL_GetError() for more information.
*
* \since This function is available since SDL 2.0.0.
*
* \sa SDL_GetRenderTarget
*/
extern DECLSPEC int SDLCALL SDL_SetRenderTarget(SDL_Renderer *renderer,
SDL_Texture *texture);
- SDL_RenderClear()
cpp
/**
* 用绘图颜色清除当前渲染目标。
*
* This function clears the entire rendering target, ignoring the viewport and
* the clip rectangle.
*
* \param renderer 渲染上下文
* \returns 0 on success or a negative error code on failure; call
* SDL_GetError() for more information.
*
* \since This function is available since SDL 2.0.0.
*
* \sa SDL_SetRenderDrawColor
*/
extern DECLSPEC int SDLCALL SDL_RenderClear(SDL_Renderer * renderer);
- SDL_RenderCopy()拷贝纹理数数据到GPU中,进行计算最终的图像
cpp
/**
* 将纹理的一部分复制到当前渲染目标。 *
* The texture is blended with the destination based on its blend mode set
* with SDL_SetTextureBlendMode().
*
* The texture color is affected based on its color modulation set by
* SDL_SetTextureColorMod().
*
* The texture alpha is affected based on its alpha modulation set by
* SDL_SetTextureAlphaMod().
*
* \param renderer the rendering context
* \param texture the source texture
* \param srcrect the source SDL_Rect structure or NULL for the entire texture
* \param dstrect the destination SDL_Rect structure or NULL for the entire
* rendering target; the texture will be stretched to fill the
* given rectangle
* \returns 0 on success or a negative error code on failure; call
* SDL_GetError() for more information.
*
* \since This function is available since SDL 2.0.0.
*
* \sa SDL_RenderCopyEx
* \sa SDL_SetTextureAlphaMod
* \sa SDL_SetTextureBlendMode
* \sa SDL_SetTextureColorMod
*/
extern DECLSPEC int SDLCALL SDL_RenderCopy(SDL_Renderer * renderer,
SDL_Texture * texture,
const SDL_Rect * srcrect,
const SDL_Rect * dstrect);
- SDL_RenderPresent() 计算好的图像进行显示
cpp
/**
* 使用自上次调用以来执行的任何渲染更新屏幕。 *
* SDL's rendering functions operate on a backbuffer; that is, calling a
* rendering function such as SDL_RenderDrawLine() does not directly put a
* line on the screen, but rather updates the backbuffer. As such, you compose
* your entire scene and *present* the composed backbuffer to the screen as a
* complete picture.
*
* Therefore, when using SDL's rendering API, one does all drawing intended
* for the frame, and then calls this function once per frame to present the
* final drawing to the user.
*
* The backbuffer should be considered invalidated after each present; do not
* assume that previous contents will exist between frames. You are strongly
* encouraged to call SDL_RenderClear() to initialize the backbuffer before
* starting each new frame's drawing, even if you plan to overwrite every
* pixel.
*
* \param renderer the rendering context
*
* \since This function is available since SDL 2.0.0.
*
* \sa SDL_RenderClear
* \sa SDL_RenderDrawLine
* \sa SDL_RenderDrawLines
* \sa SDL_RenderDrawPoint
* \sa SDL_RenderDrawPoints
* \sa SDL_RenderDrawRect
* \sa SDL_RenderDrawRects
* \sa SDL_RenderFillRect
* \sa SDL_RenderFillRects
* \sa SDL_SetRenderDrawBlendMode
* \sa SDL_SetRenderDrawColor
*/
extern DECLSPEC void SDLCALL SDL_RenderPresent(SDL_Renderer * renderer);
例子
cpp
#include <SDL.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
int quit = 1;
SDL_Event event;
// 创建窗口
SDL_Window * window = NULL;
// 创建对应的渲染
SDL_Renderer * render = NULL;
// 创建纹理
SDL_Texture * texture = NULL;
SDL_Rect rect;
rect.w= 30;
rect.h= 30;
// 初始化SDL
SDL_Init(SDL_INIT_VIDEO);
// 窗口的具体的创建过程
window = SDL_CreateWindow("SDL2 window",200,200,480,640,SDL_WINDOW_SHOWN);
if(window == NULL){
printf("Couldn't create SDL2 window\n");
goto __EXIT;
}
// 创建对应渲染
render = SDL_CreateRenderer(window,-1,0 );
if(!render){
printf("Couldn't create renderer");
goto __EXIT_WINDOWS;
}
// 推送Render
SDL_SetRenderDrawColor(render,255,255,0,50 );
// 清空render数据
SDL_RenderClear(render);
SDL_RenderPresent(render);
// 创建初始化纹理
texture= SDL_CreateTexture(render,SDL_PIXELFORMAT_RGBA8888,SDL_TEXTUREACCESS_TARGET,600,440);
// 事件处理
do{
SDL_PollEvent(&event);
switch(event.type){
case SDL_QUIT:
quit = 0;
break;
default:
SDL_Log("event type is: %d", event.type);
}
rect.x = rand()%600;
rect.y = rand()%440;
SDL_SetRenderTarget(render,texture);
SDL_SetRenderDrawColor(render,0,0,0,0);
SDL_RenderClear(render);
SDL_RenderDrawRect(render, &rect);
SDL_SetRenderDrawColor(render,255,0,0,0);
SDL_RenderFillRect(render, &rect);
SDL_SetRenderTarget(render,NULL);
SDL_RenderCopy(render,texture,NULL,NULL);
SDL_RenderPresent(render);
}while(quit);
// 销毁纹理
SDL_DestroyTexture(texture);
// 销毁窗口
SDL_DestroyWindow(window);
__EXIT_WINDOWS:
// 销毁对应的render
SDL_DestroyWindow(window);
__EXIT:
// 退出SDL
SDL_Quit();
return 0;
}
输出的结果为: