SDL学习笔记(3)——窗口绘制

目录

    • 一、 加载一张图片
    • 二、 显示一张图片
      • 2.1 调用SDL_CreateWindow创建窗口
      • 2.2 调用SDL_GetWindowSurface获取窗口表面
      • 2.3 更新窗口表面数据
      • 2.4 调用SDL_UpdateWindowSurface进行更新
    • 参考资料

这一节,我们来研究SDL的渲染流程。通过一个非硬件加速的例子,将图片渲染到我们创建的窗口上。硬件加速部分,放到下一节来学习。

一、 加载一张图片

这里我们使用到了SDL的扩展库sdl_image,只需要注意五点即可。

需要加载头文件

#include 

初始化

int imgFlags = IMG_INIT_PNG;
if( !( IMG_Init( imgFlags ) & imgFlags ) ) 
    {   
        printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
    }   

加载图片
入参是文件路径,返回SDL_Surface指针。SDL_Surface数据类型,可以理解为存储的在内存中的2D的图像数据。

SDL_Surface* loadedSurface = IMG_Load( path );

请不要忘记使用SDL_FreeSurface,释放SDL_Surface指针,

SDL_FreeSurface(loadedSurface); 

关闭IMG

IMG_Quit();

至此,图片加载就算是完成了。

二、 显示一张图片

非硬件加速大体的绘制流程如下:

  • 调用SDL_CreateWindow创建窗口
  • 调用SDL_GetWindowSurface获取窗口表面
  • 更新窗口表面数据
  • 调用SDL_UpdateWindowSurface进行更新,否则窗口并不会立刻显示

2.1 调用SDL_CreateWindow创建窗口

定义窗口宽度高度都为400。使用全局的宏变量并不是一个良好的编程习惯,不过好在我们这个例子很简单,我这里把它声明为全局变量。

const int WIDTH = 400;
const int HEIGHT = 400;

因为要绘制视频,这里我们初始化时,使用SDL_INIT_VIDEO类型。

    //Initialize SDL
    if( SDL_Init( SDL_INIT_VIDEO ) != 0 )
    {
        printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
    }

接下来,我们通过SDL_CreateWindow获得了SDL_Window类型的变量window。SDL_Window可以理解为我们可见的窗口。

SDL_Window* window = SDL_CreateWindow( "SDL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN );

2.2 调用SDL_GetWindowSurface获取窗口表面

有了窗口以后,我们就需要获取窗口表面,才能在其上进行绘制,并改变我们看到的窗口。
通过SDL_GetWindowSurface获得了当前屏幕的SDL_Surface类型的变量screenSurface。

SDL_Surface* screenSurface = SDL_GetWindowSurface( window );

2.3 更新窗口表面数据

使用SDL_FillRect将screenSurface填充为白色(R:0xFF, G:0xFF, B:0xFF)。

//Fill the surface white
SDL_FillRect( screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0x00, 0x00 ) );

在这个动作之后,还记得我们使用IMG_Load,加载图片生成的SDL_Surface* loadedSurface吗?我们需要将这个SDL_Surface数据渲染到screenSurface上。这里使用SDL_BlitSurface()函数。

SDL_BlitSurface(loadedSurface, NULL, screenSurface, NULL);

2.4 调用SDL_UpdateWindowSurface进行更新

调用SDL_UpdateWindowSurface进行更新,否则窗口并不会立刻显示。

//Update the surface
SDL_UpdateWindowSurface( window );

给出完整代码如下:

#include                                                                                
#include 
#include 

const int WIDTH = 400;
const int HEIGHT = 400;
const char* path = "test.png";

int main(int argc, char* argv[])
{
    //Initialize SDL
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
    }
    //Init IMG
    int imgFlags = IMG_INIT_PNG;
    if( !( IMG_Init( imgFlags ) & imgFlags ) )
    {
        printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
    }

    SDL_Surface* loadedSurface = IMG_Load(path);

    SDL_Window* window = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED,                 SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN );
    if( window == NULL )
    {
        printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
    }else{
        SDL_Surface* screenSurface = SDL_GetWindowSurface( window );
        
        SDL_Event test_event;
        int isQuit = 0;
        while (!isQuit) {
            SDL_PollEvent(&test_event);
            switch (test_event.type) {
                case SDL_QUIT:
                    isQuit = 1;
                    printf("We got a quit event.\n");
                    break;
                default:
                    break;
            }
            //Fill the surface white
            SDL_FillRect( screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0x00, 0x00  ) );
            
            SDL_BlitSurface(loadedSurface, NULL, screenSurface, NULL);

            //Update the surface
            SDL_UpdateWindowSurface( window );
        }

    }
    SDL_FreeSurface(loadedSurface); 
    SDL_DestroyWindow( window );
    IMG_Quit();
    SDL_Quit();
    return 0;
}

编译:
gcc sdl_show.c `pkg-config --cflags --libs sdl2 sdl2_image` -o sdl_show
运行:
./sdl_show
输出:一个窗口,显示我们加载的图片,需要注意的是,图片没有经过缩放,和窗口不匹配。点击左上角x,程序退出,日志输出:

We got a quit event.

参考资料

[1]. Introduction to SDL 2.0
[2]. Beginning Game Programming v2.0
[3]. SDL介绍
[4]. SDL_image Documentation

你可能感兴趣的:(音视频,sdl)