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


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

一、 加载一张图片

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

需要加载头文件

#include <SDL_image.h>

初始化

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 <SDL2/SDL.h>                                                                               
#include <stdio.h>
#include <SDL_image.h>

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值