(Audio and video study notes): Introduction to SDL environment construction and application

table of Contents

Introduction to SDL

Windows environment setup

Linux environment construction

SDL subsystem

SDL Window display: Introduction to SDL video display function

Create project

SDL Windows display: Introduction to SDL data structure

SDL events

SDL multithreading

Introduction to SDL

  • Official website: https://www.libsdl.org/   
  • Documentation: http://wiki.libsdl.org/Introduction
  • SDL (Simple DirectMedia Layer) is a set of open source cross-platform multimedia development libraries written in C language.
    • SDL provides several functions for controlling images, sounds, and I/O , allowing developers to develop application software across multiple platforms (Linux, Windows, Mac OS X, etc.) as long as they use the same or similar code.
    • At present, SDL is mostly used in the development of multimedia applications such as games, simulators, and media players.

Windows environment setup

Linux environment construction

  • Download the SDL source code library, SDL2-2.0.10.tar.gz
  • Unzip, and then execute the commands in turn
./configure
make
sudo make install
  • If the Could not initialize SDL-No available video device (Did you set the DISPLAY variable?) error appears, it means that the x11 library file is not installed in the system, so the compiled SDL library cannot actually be used. Download and install
sudo apt-get install libx11-dev
sudo apt-get install xorg-dev

SDL subsystem

  • SDL divides functions into the following subsystems:
SDL_INIT_TIMER Timer
SDL_INIT_AUDIO Audio
SDL_INIT_VIDEO video
SDL_INIT_JOYSTICK Joystick
SDL_INIT_HAPTIC touch screen
SDL_INIT_GAMECONTROLLER Game Controller
SDL_INIT_EVENTS event
SDL_INIT_EVERYTHING Contains all the above options

SDL Window display: Introduction to SDL video display function

SDL_Init() Initialize the SDL system
SDL_CreateWindow() Create window SDL_Window
SDL_CreateRenderer() Create renderer SDL_Renderer
SDL_CreateTexture() Create texture SDL_Texture
SDL_UpdateTexture() Set the texture data
SDL_RenderCopy() Copy the texture data to the renderer
SDL_RenderPresent () display
SDL_Delay() Utility function for delay
SDL_Quit()

Exit the SDL system

Create project

  • Put the decompressed SDL file under the created project

  • Add library to project file
    • Hold down the Ctrl key and click on the path name to see if the configuration is correct
TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
CONFIG -= qt

SOURCES += \
        main.c
win32 {
INCLUDEPATH += $$PWD/SDL2-2.0.10/include
LIBS += $$PWD/SDL2-2.0.10/lib/x86/SDL2.lib
}
  • Copy the dynamic library file (SDL2-2.0.10\lib\x64, where 32-bit platform is used here) to the project directory

  • Add dynamic library files in the debug directory

  • carry out testing
#include <stdio.h>
#include <SDL.h>

#undef main
int main()
{
    printf("Hello World!\n");
    // 声明窗口
    SDL_Window *window = NULL;      
    // 初始化SDL
    SDL_Init(SDL_INIT_VIDEO);       
    // 创建SDL Window
    window = SDL_CreateWindow("Basic Window",
                              SDL_WINDOWPOS_UNDEFINED,
                              SDL_WINDOWPOS_UNDEFINED,
                              640,
                              480,
                              SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
    if(!window) // 检测是否创建成功
    {
        printf("Can't create window, err:%s\n", SDL_GetError());
        return 1;
    }
    // 延迟10000ms
    SDL_Delay(10000);  
    // 销毁窗口
    SDL_DestroyWindow(window); 
    // 释放资源
    SDL_Quit(); 

    return 0;
}
  • Output:

SDL Windows display: Introduction to SDL data structure

  • SDL_Window represents a "window"
  • SDL_Renderer represents a "renderer"
  • SDL_Texture represents a "texture"
  • SDL_Rect a simple rectangular structure

  • The difference between storing RGB and storing texture:
    • For example, for a rectangle that changes from red to blue from left to right, if RGB is used, the specific color value of each point in the rectangle needs to be stored.
    • The texture is just some descriptive information, such as the size of the rectangle, the starting color, the ending color, and other information. The graphics card can use this information to calculate the detailed information of the rectangular block.
    • So compared to storing RGB, the memory used to store textures is much less.
  • Example:
#include <stdio.h>
#include <SDL.h>
#undef main
int main()
{
    int run = 1;
    SDL_Window *window = NULL;
    SDL_Renderer *renderer = NULL;
    SDL_Texture *texture = NULL;
    SDL_Rect rect; // 长方形,原点在左上角
    rect.w = 50;    //方块大小
    rect.h = 50;

    SDL_Init(SDL_INIT_VIDEO);//初始化函数,可以确定希望激活的子系统

    window = SDL_CreateWindow("2 Window",
                              SDL_WINDOWPOS_UNDEFINED,
                              SDL_WINDOWPOS_UNDEFINED,
                              640,
                              480,
                              SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);// 创建窗口

    if (!window)
    {
        return -1;
    }
    renderer = SDL_CreateRenderer(window, -1, 0);//基于窗口创建渲染器
    if (!renderer)
    {
        return -1;
    }

    texture = SDL_CreateTexture(renderer,   //基于渲染器创建纹理
                                   SDL_PIXELFORMAT_RGBA8888,
                                   SDL_TEXTUREACCESS_TARGET,
                                   640,
                                   480); //创建纹理

    if (!texture)
    {
        return -1;
    }

    int show_count = 0;
    while (run)
    {
        rect.x = rand() % 600;
        rect.y = rand() % 400;

        SDL_SetRenderTarget(renderer, texture); // 设置渲染目标为纹理
        SDL_SetRenderDrawColor(renderer, 0, 255, 255, 255); // 纹理背景颜色设置
        SDL_RenderClear(renderer); //清屏

        SDL_RenderDrawRect(renderer, &rect); //绘制一个长方形
        SDL_SetRenderDrawColor(renderer, 255, 0, 255, 255); //长方形颜色设置
        SDL_RenderFillRect(renderer, &rect);

        SDL_SetRenderTarget(renderer, NULL); //恢复默认,渲染目标为窗口
        SDL_RenderCopy(renderer, texture, NULL, NULL); //拷贝纹理到CPU

        SDL_RenderPresent(renderer); //输出到目标窗口上
        SDL_Delay(300);
        if(show_count++ > 30)
        {
            run = 0;        // 不跑了
        }
    }

    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window); //销毁窗口
    SDL_Quit();
    return 0;
}
  • Show results:

SDL events

 

SDL_WaitEvent() Waiting for an event
SDL_PushEvent() Send an event
SDL_PumpEvents() Put the events generated by the hardware device into the event queue for reading events. Before calling this function, you must call SDL_PumpEvents to collect keyboard events and other events
SDL_PeepEvents() Extract an event from the event queue
SDL_Event Represents an event
  • Example:
#include <SDL.h>
#include <stdio.h>
#define FF_QUIT_EVENT    (SDL_USEREVENT + 2) // 用户自定义事件
#undef main
int main(int argc, char* argv[])
{
    SDL_Window *window = NULL;              // Declare a pointer
    SDL_Renderer *renderer = NULL;

    SDL_Init(SDL_INIT_VIDEO);               // Initialize SDL2

    // Create an application window with the following settings:
    window = SDL_CreateWindow(
                "An SDL2 window",                  // window title
                SDL_WINDOWPOS_UNDEFINED,           // initial x position
                SDL_WINDOWPOS_UNDEFINED,           // initial y position
                640,                               // width, in pixels
                480,                               // height, in pixels
                SDL_WINDOW_SHOWN | SDL_WINDOW_BORDERLESS// flags - see below
                );

    // Check that the window was successfully created
    if (window == NULL)
    {
        // In the case that the window could not be made...
        printf("Could not create window: %s\n", SDL_GetError());
        return 1;
    }

    /* We must call SDL_CreateRenderer in order for draw calls to affect this window. */
    renderer = SDL_CreateRenderer(window, -1, 0);

    /* Select the color for drawing. It is set to red here. */
    SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);

    /* Clear the entire screen to our selected color. */
    SDL_RenderClear(renderer);

    /* Up until now everything was drawn behind the scenes.
       This will show the new, red contents of the window. */
    SDL_RenderPresent(renderer);

    SDL_Event event;
    int b_exit = 0;
    for (;;)
    {
        SDL_WaitEvent(&event);
        switch (event.type)
        {
        case SDL_KEYDOWN:	/* 键盘事件 */
            switch (event.key.keysym.sym)
            {
            case SDLK_a:
                printf("key down a\n");
                break;
            case SDLK_s:
                printf("key down s\n");
                break;
            case SDLK_d:
                printf("key down d\n");
                break;
            case SDLK_q:
                printf("key down q and push quit event\n");
                SDL_Event event_q;
                event_q.type = FF_QUIT_EVENT;
                SDL_PushEvent(&event_q);
                break;
            default:
                printf("key down 0x%x\n", event.key.keysym.sym);
                break;
            }
            break;
        case SDL_MOUSEBUTTONDOWN:			/* 鼠标按下事件 */
            if (event.button.button == SDL_BUTTON_LEFT)
            {
                printf("mouse down left\n");
            }
            else if(event.button.button == SDL_BUTTON_RIGHT)
            {
                printf("mouse down right\n");
            }
            else
            {
                printf("mouse down %d\n", event.button.button);
            }
            break;
        case SDL_MOUSEMOTION:		/* 鼠标移动事件 */
            printf("mouse movie (%d,%d)\n", event.button.x, event.button.y);
            break;
        case FF_QUIT_EVENT:
            printf("receive quit event\n");
            b_exit = 1;
            break;
        }
        if(b_exit)
            break;
    }

    //destory renderer
    if (renderer)
        SDL_DestroyRenderer(renderer);

    // Close and destroy the window
    if (window)
        SDL_DestroyWindow(window);

    // Clean up
    SDL_Quit();
    return 0;
}

SDL multithreading

SDL thread creation SDL_CreateThread
SDL thread waiting SDL_WaitThead
SDL Mutex SDL_CreateMutex/SDL_DestroyMutex
SDL lock mutex SDL_LockMutex/SDL_UnlockMutex
SDL condition variable (semaphore) SDL_CreateCond/SDL_DestoryCond
SDL condition variable (semaphore) wait/notify

SDL_CondWait/SDL_CondSingal

  • Example:
#include <SDL.h>
#include <stdio.h>

SDL_mutex *s_lock = NULL;
SDL_cond *s_cond = NULL;

int thread_work(void *arg)
{
    SDL_LockMutex(s_lock);
    printf("                <============thread_work sleep\n");
    sleep(10);      // 用来测试获取锁
    printf("                <============thread_work wait\n");
    // 释放s_lock资源,并等待signal。之所以释放s_lock是让别的线程能够获取到s_lock
    SDL_CondWait(s_cond, s_lock); //另一个线程(1)发送signal和(2)释放lock后,这个函数退出

    printf("                <===========thread_work receive signal, continue to do ~_~!!!\n");
    printf("                <===========thread_work end\n");
    SDL_UnlockMutex(s_lock);
    return 0;
}

#undef main
int main()
{
    s_lock = SDL_CreateMutex();
    s_cond = SDL_CreateCond();
    SDL_Thread * t = SDL_CreateThread(thread_work,"thread_work",NULL);
    if(!t)
    {
        printf("  %s",SDL_GetError);
        return -1;
    }

    for(int i = 0;i< 2;i++)
    {
        sleep(2);
        printf("main execute =====>\n");
    }
    printf("main SDL_LockMutex(s_lock) before ====================>\n");
    SDL_LockMutex(s_lock);  // 获取锁,但是子线程还拿着锁
    printf("main ready send signal====================>\n");
    printf("main SDL_CondSignal(s_cond) before ====================>\n");
    SDL_CondSignal(s_cond); // 发送信号,唤醒等待的线程
    printf("main SDL_CondSignal(s_cond) after ====================>\n");
    sleep(10);
    SDL_UnlockMutex(s_lock);// 释放锁,让其他线程可以拿到锁
    printf("main SDL_UnlockMutex(s_lock) after ====================>\n");

    SDL_WaitThread(t, NULL);
    SDL_DestroyMutex(s_lock);
    SDL_DestroyCond(s_cond);

    return 0;
}
  • Output:

Guess you like

Origin blog.csdn.net/baidu_41388533/article/details/112703088