我们可以把表面想象成一张画布, blit 表面就是把一个表面的某个区域 COPY 到另外一个表面上去。
//The headers
#include " SDL.h"
#include <string>
以上就是我们需要的头文件了。
//The attributes of the screen
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;
3 个描述屏幕属性的变量
SCREEN_BPP 是颜色深度,就是每个象素用多少为来表示,我们这里用 4 个字节。
//The surfaces that will be used
SDL_Surface *message = NULL;
SDL_Surface *background = NULL;
SDL_Surface *screen = NULL;
接着我们又定义了 3 个表面,一个用于显示背景,一个用于显示 Hello World ,还有一个当然是代表屏幕了。
SDL_Surface *load_image( std::string filename )
{
//Temporary storage for the image that's loaded
SDL_Surface* loadedImage = NULL;
//The optimized image that will be used
SDL_Surface* optimizedImage = NULL;
好了,我们可以写一个自己的图像装载函数,该函数负责 Load 图片,并返回一个经过优化的表面,当然图片已经在表面上了。
//Load the image
loadedImage = SDL_LoadBMP( filename.c_str() );
首先我们使用 SDL_LoadBMP() 函数 Load 一张 BMP 格式的图片。应为位图是 24 位,所以我们不应该立即使用该表面,因为屏幕是 32 位的。如果在二各具有不同 format 表面进行 Blit ,那么 SDL 将会不停地进行格式之间的转换,程序就会变得很慢。 .
if( loadedImage != NULL )
{
//Create an optimized image
optimizedImage = SDL_DisplayFormat( loadedImage );
//Free the old image
SDL_FreeSurface( loadedImage );
}
以上几行代码检查了图片是否被正确加载了,如果有错误的话,那么 loadedImage 将是 NULL 。
SDL_DisplayFormat() 用于创建一个和屏幕表面相同格式的 Surface 。之所以这样做就是为了加快程序速度,避免 SDL 类库在对二个不同格式表面进行 Blit 时进行格式转换。
好了,现在我们拥有二个表面了,一个上面有图片,还有一个是前一个经过格式转换得到的。
因为第一表面我们不需要了,所以我们就要释放掉, SDL_FreeSurface() 函数就是干这件事情的。
//Return the optimized image
return optimizedImage;
}
好了,我们返回经过优化的表面。
void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination )
{
//Make a temporary rectangle to hold the offsets
SDL_Rect offset;
//Give the offsets to the rectangle
offset.x = x;
offset.y = y;
接下来,我们再写一个 Blit 函数。 X,Y 是目标表面的偏移量,另外二个自然是要进行 Blit 的二个表面了。
首先我们把偏移量塞入到一个 SDL_Rect 变量里面,这样做的原因很简单,就是 SDL_BlitSurface 只接受 SDL_Rect 结构中的偏移。
SDL_Rect 结构代表一个长方形 . 它有四个成员,左上角的坐标,长和宽。
//Blit the surface
SDL_BlitSurface( source, NULL, destination, &offset );
}
好了,调用 SDL_BlitSurface 实现 Blit 。第二个参数是源表面的要被 Blit 的区域,我们用 NULL 表示要对整个源表面进行 Blit 。
int main( int argc, char* args[] )
{
if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
{
return 1;
}
在 SDL_Init() 函数中,我们使用 SDL_INIT_EVERYTHING 参数,表示我们希望启动所有 SDL 子系统,其中包括,视频,声音,时间,以及其他一些制作游戏所用到的组建。
screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );
现在我们用 SDL_SetVideoMode 函数新建一个窗口,它返回一个指向窗口表面的指针,这样我们就可以把图像往屏幕上 Blit 了。
if( screen == NULL )
{
return 1;
}
如果函数有问题的话,就返回 NULL 。下面我们也可以改变一下窗口的标题。 SDL_WM_SetCaption( "Hello World", NULL );
message = load_image( "hello_world.bmp" );
background = load_image( "background.bmp" );
apply_surface( 0, 0, background, screen );
现在我们把背景 Blit 到屏幕上,在 Blit 背景之前,窗口是黑色,如下图。
再这之后,窗口的背景就改变了。
用同样的方法,我们把 message 也 Blit 到屏幕上去。
apply_surface( 180, 140, message, screen );
if( SDL_Flip( screen ) == -1 )
{
return 1;
}
虽然我们把背景表面和消息表面都 Blit 到屏幕表面上去了,窗口还是一片漆黑,因为我们没有调用 SDL_Flip 函数来更新窗口,记住,屏幕表面是建立在系统内存当中的。
SDL_Delay( 2000 );
好了,让窗口停顿二秒,以免我们什么也不到。
//Free the surfaces
SDL_FreeSurface( message );
SDL_FreeSurface( background );
//Quit SDL
SDL_Quit();
//Return
return 0;
}
好了,我们的主函数也写完了,最后我释放了二个表面,并调用了 SDL_Quit 函数,清理我们所使用到其他资源。
好了,运行一下程序,你不意外你就能看到如下的效果了。如果有什么错误的话,看看第一个教程。