Lazyfoo's SDL_Tutorial 摘要翻译2

我会删掉一大把废话然后大概翻译一下酱紫

Tutorial 2:Getting an Image on the Screen

原文
依然是非常基础的一节,只是把上一节的显示白色矩形变成了一张图片。

//Starts up SDL and creates window
bool init();

//Loads media
bool loadMedia();

//Frees media and shuts down SDL
void close();

作者先废话一波告诉我们不要把所有的代码放在main函数里面,简直多此一举,跳过。
作者在示例代码里面用了void close()这样的函数名称,非常危险.他自己说没事,但是在C/C++里面没事别起这个名字,万一哪天和系统库冲突了.

//The window we'll be rendering to
SDL_Window* gWindow = NULL;
    
//The surface contained by the window
SDL_Surface* gScreenSurface = NULL;

//The image we will load and show on the screen
SDL_Surface* gHelloWorld = NULL;

说一下SDL_Surface类型.这个类型的本质上是一个图像数据类型,用来提供渲染图像所需的数据.这里的渲染采用CPU渲染,可能后续的课程中会讲到GPU渲染的方法吧.

作者非常友善地提醒了我们要记得初始化指针.对了,这里之所以全部使用指针,不仅仅是为了体现c++特色,主要是这样方便传参,避免大规模的内存复制.

bool init()
{
    //Initialization flag
    bool success = true;

    //Initialize SDL
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
        success = false;
    }
    else
    {
        //Create window
        gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
        if( gWindow == NULL )
        {
            printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
            success = false;
        }
        else
        {
            //Get window surface
            gScreenSurface = SDL_GetWindowSurface( gWindow );
        }
    }

    return success;
}

直接照抄上次的代码,只不过放到了单独的过程里面.

bool loadMedia()
{
    //Loading success flag
    bool success = true;

    //Load splash image
    gHelloWorld = SDL_LoadBMP( "02_getting_an_image_on_the_screen/hello_world.bmp" );
    if( gHelloWorld == NULL )
    {
        printf( "Unable to load image %s! SDL Error: %s\n", "02_getting_an_image_on_the_screen/hello_world.bmp", SDL_GetError() );
        success = false;
    }

    return success;
}

这段代码是全新的.这里使用SDL_LoadBMP来加载一张图片.记得自行注意路径问题.

void close()
{
    //Deallocate surface
    SDL_FreeSurface( gHelloWorld );
    gHelloWorld = NULL;

    //Destroy window
    SDL_DestroyWindow( gWindow );
    gWindow = NULL;

    //Quit SDL subsystems
    SDL_Quit();
}

在这段代码里面,注意到对自行加载的surface进行了释放,但是没有对之前通过SDL_GetWindowSurface获取的screensurface进行释放.其实这是不必要的,DestroyWindow会自动处理这些问题,我们只需要把自己加载的surface对象释放掉就可以了.(当然你甚至可以啥也不做,反正程序结束了系统也会释放内存的)

int main( int argc, char* args[] )
{
    //Start up SDL and create window
    if( !init() )
    {
        printf( "Failed to initialize!\n" );
    }
    else
    {
        //Load media
        if( !loadMedia() )
        {
            printf( "Failed to load media!\n" );
        }
        else
        {
            //Apply the image
            SDL_BlitSurface( gHelloWorld, NULL, gScreenSurface, NULL );

解释一下新函数SDL_BlitSurface.在这里使用这个函数将加载到gHelloWorld这个surface对象里的数据blit到screen surface上.

blit这个词貌似是个编程方面的生造词,Oxford和Longman上面都没查到.含义为将一个平面的一部分或全部图象整块从这个平面复制到另一个平面.实在不行自己看原文去意会一下.

在blit完之后,还需要update一下,才能将图片显示出来.接下来关于双缓冲的讲解照抄原文.

在我们要为此帧显示的屏幕上绘制所有内容之后,我们必须使用SDL_UpdateWindowSurface更新屏幕。这里的绘制并不是直接绘制到屏幕上.默认情况下,大多数渲染系统都是双缓冲的。这两个缓冲区是前缓冲区和后缓冲区。

进行SDL_BlitSurface之类的绘制调用时,将渲染到后台缓冲区。在屏幕上看到的是前端缓冲区。我们这样做的原因是因为大多数框架都需要在屏幕上绘制多个对象。如果只有前缓冲区,我们将能够在看到事物时看到框架,这意味着我们将看到未完成的框架。因此,我们要做的是先将所有内容绘制到后缓冲区,一旦完成,我们将交换后缓冲区和前缓冲区,以便用户现在可以看到完成的帧。

这也意味着不会在每次blit之后都调用SDL_UpdateWindowSurface,只有在完成当前帧的所有blit之后才调用SDL_UpdateWindowSurface

其实也就是在后台先画,画完了再直接啪一下贴到前台.

之后就是惯例delay2秒,然后结束.

posted @ 2020-05-09 09:19  Prisrak  阅读(99)  评论(0编辑  收藏  举报