SDL学习

Simple DirectMedia Layer 是一个跨平台开发库 ,旨在通过OpenGLDirect3D 提供对音频、键盘、鼠标、操纵杆和图形硬件的低级访问 。它被视频播放软件、模拟器和流行游戏使用,包括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;
}

输出的结果为:

相关推荐
EasyDSS21 分钟前
国标GB28181-2022平台EasyGBS:安防监控中P2P的穿透方法
网络协议·php·音视频·p2p
Amarantine、沐风倩✨8 小时前
设计一个监控摄像头物联网IOT(webRTC、音视频、文件存储)
java·物联网·音视频·webrtc·html5·视频编解码·七牛云存储
量子-Alex9 小时前
【多模态聚类】用于无标记视频自监督学习的多模态聚类网络
学习·音视频·聚类
mo477613 小时前
Webrtc音频模块(四) 音频采集
音视频·webrtc
icy、泡芙13 小时前
T527-----音频调试
linux·驱动开发·音视频
易我数据恢复大师13 小时前
怎么提取音频保存到本地?电脑音频提取方法
音视频·软件·音频提取
野蛮的大西瓜13 小时前
开源呼叫中心中,如何将ASR与IVR菜单结合,实现动态的IVR交互
人工智能·机器人·自动化·音视频·信息与通信
嘟嘟实验室15 小时前
微信小程序xr-frame透明视频实现
微信小程序·ffmpeg·音视频·xr
红米饭配南瓜汤17 小时前
WebRTC服务质量(09)- Pacer机制(01) 流程概述
网络·音视频·webrtc
m0_7482517218 小时前
Android webview 打开本地H5项目(Cocos游戏以及Unity游戏)
android·游戏·unity