SDL 图片软拉伸

参考自:https://blog.csdn.net/qq_31024569/article/details/78128166

直到现在我们的代码都仅仅是按原生大小显示图片而已。因为我们一次展示一张图像,这样做没什么问题。但当你制作游戏的时候,这样做会导致不必要的减速(needless slowdown)。现在我们将要把图像转为更加优化的格式以加快速度。

SDL2有一个新特性叫做软拉伸,它允许你将图像缩放到不同的大小。在这篇教程中我们会把一张只有窗口一半尺寸的图像拉伸到整个窗口大小。

当你每次加载位图的时候,基本上它都会以24位的格式加载因为大部分位图都是24位。但这只是大部分,现在的显示器默认的都不是24位。如果我们把24位的图像投射到32位的图像上,SDL就会在每一次投射的时候对它进行转化。

所以我们要做的就是在图像被加载的时候对其以与屏幕相同的格式进行转化来保证投射的过程中不再发生转化的工作。使用SDL_ConvertSurface()函数可以很轻松地完成这个工作。因为我们要做的就仅仅是传入想要转化的surface和格式给这个函数。

很重要的一点是SDL_ConvertSurface()以新的格式返回原来的surface。原来已经加载过的图像在这个调用之后仍然在内存之中。这意味着我们得把原来已经加载的surface释放掉,否则内存中就会有两份相同的图像。(其中一个还是不会用到的)

在图像被加载并完成转换之后,将最终优化过的图像返回。

 

SDL2有新的专用的函数来把图像以不同的尺寸投射到屏幕——SDL_BlitScaled(),就像之前投射图像那样,SDL_BlitScaled()需要接收一个源surface以投射到目标surface上。它同样要接收定义了将要投射到的位置和尺寸的SDL_Rect作为参数。

所以如果我们想要把比窗口尺寸小的图像拉伸到窗口尺寸大小,你就把要投射的尺寸设定为窗口的尺寸。

 

完整代码如下:

//Using SDL, standard IO, and strings
#include <SDL2/SDL.h>
#include <stdio.h>
#include <string>
 
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
 
//Starts up SDL and creates window
bool init();
 
//Loads media
bool loadMedia();
 
//Frees media and shuts down SDL
void close();
 
//Loads individual image
SDL_Surface* loadSurface( std::string path );
 
//The window we'll be rendering to
SDL_Window* gWindow = NULL;
 
//The surface contained by the window
SDL_Surface* gScreenSurface = NULL;
 
//Current displayed image
SDL_Surface* gStretchedSurface = NULL;
 
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 stretching surface
   gStretchedSurface = loadSurface( "stretch.bmp" );

   if( gStretchedSurface == NULL )
   {
      printf( "Failed to load stretching image!\n" );
      success = false;
   }
   return success;
}
 
void close()
{
   //Free loaded image
   SDL_FreeSurface( gStretchedSurface );
   gStretchedSurface = NULL;
 
   //Destroy window
   SDL_DestroyWindow( gWindow );
   gWindow = NULL;
 
   //Quit SDL subsystems
   SDL_Quit();
}
 
SDL_Surface* loadSurface( std::string path )
{
   //The final optimized image
   SDL_Surface* optimizedSurface = NULL;
 
   //Load image at specified path
   SDL_Surface* loadedSurface = SDL_LoadBMP( path.c_str() );
   if( loadedSurface == NULL )
   {
      printf( "Unable to load image %s! SDL Error: %s\n", path.c_str(), SDL_GetError() );
   }
   else
   {
      //Convert surface to screen format
      optimizedSurface = SDL_ConvertSurface( loadedSurface, gScreenSurface->format, NULL );
      if( optimizedSurface == NULL )
      {
         printf( "Unable to optimize image %s! SDL Error: %s\n", path.c_str(), SDL_GetError() );
      }
      //Get rid of old loaded surface
      SDL_FreeSurface( loadedSurface );
   }
 return optimizedSurface;
}
 
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
      { 
         //Main loop flag
         bool quit = false;
         //Event handler
         SDL_Event e;
         //While application is running
         while( !quit )
         {
            //Handle events on queue
            while( SDL_PollEvent( &e ) != 0 )
            {
               //User requests quit
               if( e.type == SDL_QUIT )
               {
                  quit = true;
               }
            }
 
            //Apply the image stretched
            SDL_Rect stretchRect;
            stretchRect.x = 0;
            stretchRect.y = 0;
            stretchRect.w = SCREEN_WIDTH;
            stretchRect.h = SCREEN_HEIGHT;
            SDL_BlitScaled( gStretchedSurface, NULL, gScreenSurface, &stretchRect );
   
            //Update the surface
            SDL_UpdateWindowSurface( gWindow );
         }
      }
   }
   //Free resources and close SDL
   close();
   return 0;
}
posted @ 2019-05-07 22:47  HenryLiuY  阅读(664)  评论(0)    收藏  举报