http://blog.csdn.net/lf426/article/details/2086634
.1:准备工作。
找一张*.bmp格式的图片。我在例子中将使用640*480大小的图片。如果你在windows下面,你可以打开画图程序自己简单的画一张,或者将其他格式的图片另存为bmp。然后将图片名字修改为helloworld.bmp(当然,你也可以在程序的相应部分修改为你目标图片的名字。),这是我们将要显示的图片。
2.2:创建一个SDL的执行窗口。
我们讨论过,SDL是跨平台的,它的设计者希望使用SDL的源程序不要依赖于具体平台,甚至具体的GUI和窗口管理器。在前面一节中,我们已经简单使用了SDL_SetVideoMode(),在这里,我们对它做进一步的介绍——使用这个函数实际上遇到的问题会比我们预想中涉及到的问题多,换句话说,这里的介绍仍然是不完整的。我们当前的目的,只是为了简单的显示一张BMP位图。
这个函数的返回值是一个SDL_Surface的结构指针。如果返回是空指针(C中习惯用NULL,而C++标准将空指针表示为0),则表示这个函数调用失败了。我们可以通过SDL_GetError()获得异常的原因。SDL_Surface结构包含了一个surface的数据结构,包括宽,高和每个像素点的具体颜色等等,我们也放在后面具体讨论。这里,我们还是直接把SDL_Surface看成一个类,这个函数返回一个SDL_Surface类对象的指针。
width和height是你希望建立的窗口的宽与高。如果值为0,则建立与你当前桌面等宽高的窗口。bitsperpixel是这个窗口的颜色位深。当前的硬件环境下,相信你的桌面也是32位色的。如果这个值为0,则所建立的窗口使用你当前桌面的位深。
我们试图建立一个640*480大小的,32位色的窗口。并且让返回的surface值储存在系统内存里。(后面会介绍使用显存的方法。)需要注意的是,我们必须记下这个返回的surface的指针,因为所有的图像操作,最后都是通过修改这个surface的数据作用在显示这个surface的窗口上,最终呈现在我们眼前的。
const int SCREEN_HEIGHT = 480 ; // 0 means use current height.
const int SCREEN_BPP = 32 ; // 0 means use current bpp.
const Uint32 SCREEN_FLAGS = SDL_SWSURFACE; // SDL_SWSURFACE == 0,surface in system memory.
SDL_Surface * pScreen = 0 ;
pScreen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SCREEN_FLAGS); // Creat a SDL window, and get the window's surface.
try {
if ( pScreen == 0 )
throw SDL_GetError();
}
catch ( const char * s ) {
std::cerr << " SDL_SetVideoMode() failed!/n " << s << std::endl;
SDL_Quit();
return - 1 ;
}
2.3:装载BMP格式的位图。
pShownBMP = SDL_LoadBMP( " helloworld.bmp " ); // Load a BMP file, and convert it as a surface.
try {
if ( pShownBMP == 0 )
throw SDL_GetError();
}
catch ( const char * s ) {
std::cerr << " SDL_LoadBMP() failed!/n " << s << std::endl;
SDL_Quit();
return - 1 ;
}
2.4:块移图面(blit surface)。
src指的是要进行blit的源surface,dst指的是blit这个surface要去的目的地——另外一个surface。我们这里先忽略SDL_Rect结构的具体意思,仅仅需要了解的是,如果srcrect为空指针,意味着整个源surface将被blit;如果dstrect为空指针,意味着源surface与目的surface的左上角重合(坐标(0,0))。
blit是个有渊源的词语,我将来会在术语解释中具体提到。这个词的本意就是块(block)移动(transfer)的缩写blt,因为这个缩写缺少元音不好读,所以后来加上了i,就变成blit。
如果blit成功,则返回0;否则返回-1。
SDL_Rect * pDstRect = 0 ; // If pDstRect is NULL, then the destination position (upper left corner) is (0, 0).
try {
if ( SDL_BlitSurface(pShownBMP, pSrcRect, pScreen, pDstRect) != 0 ) // Put the BMP's surface on the SDL window's surface.
throw SDL_GetError();
}
catch ( const char * s ) {
std::cerr << " SDL_BlitSurface() failed!/n " << s << std::endl;
SDL_Quit();
return - 1 ;
}
2.5:显示图片。
另外一个需要了解的问题是,我们之前对surface的种种操作,实际上都是在修改surface数据结构中的某些数据,当我们最后需要将这些surface显示到屏幕上(我们打开的SDL操作窗口上),我们需要使用函数SDL_Flip()。如果函数调用成功,则返回0;否则返回-1。
if ( SDL_Flip(pScreen) != 0 ) // Show the SDL window's surface.
throw SDL_GetError();
}
catch ( const char * s ) {
std::cerr << " SDL_Flip() failed!/n " << s << std::endl;
SDL_Quit();
return - 1 ;
}
2.6:这个例子的完整源代码。
#include " SDL/SDL.h "
void pressESCtoQuit();
int main( int argc, char * argv[])
{
try {
if ( SDL_Init(SDL_INIT_VIDEO) != 0 )
throw SDL_GetError();
}
catch ( const char * s ) {
std::cerr << " SDL_Init() failed!/n " << s << std::endl;
return - 1 ;
}
const int SCREEN_WIDTH = 640 ; // 0 means use current width.
const int SCREEN_HEIGHT = 480 ; // 0 means use current height.
const int SCREEN_BPP = 32 ; // 0 means use current bpp.
const Uint32 SCREEN_FLAGS = SDL_SWSURFACE; // SDL_SWSURFACE == 0,surface in system memory.
SDL_Surface * pScreen = 0 ;
pScreen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SCREEN_FLAGS); // Creat a SDL window, and get the window's surface.
try {
if ( pScreen == 0 )
throw SDL_GetError();
}
catch ( const char * s ) {
std::cerr << " SDL_SetVideoMode() failed!/n " << s << std::endl;
SDL_Quit();
return - 1 ;
}
SDL_Surface * pShownBMP = 0 ;
pShownBMP = SDL_LoadBMP( " helloworld.bmp " ); // Load a BMP file, and convert it as a surface.
try {
if ( pShownBMP == 0 )
throw SDL_GetError();
}
catch ( const char * s ) {
std::cerr << " SDL_LoadBMP() failed!/n " << s << std::endl;
SDL_Quit();
return - 1 ;
}
SDL_Rect * pSrcRect = 0 ; // If pSrcRect is NULL, the entire source surface is copied.
SDL_Rect * pDstRect = 0 ; // If pDstRect is NULL, then the destination position (upper left corner) is (0, 0).
try {
if ( SDL_BlitSurface(pShownBMP, pSrcRect, pScreen, pDstRect) != 0 ) // Put the BMP's surface on the SDL window's surface.
throw SDL_GetError();
}
catch ( const char * s ) {
std::cerr << " SDL_BlitSurface() failed!/n " << s << std::endl;
SDL_Quit();
return - 1 ;
}
try {
if ( SDL_Flip(pScreen) != 0 ) // Show the SDL window's surface.
throw SDL_GetError();
}
catch ( const char * s ) {
std::cerr << " SDL_Flip() failed!/n " << s << std::endl;
SDL_Quit();
return - 1 ;
}
pressESCtoQuit();
SDL_Quit();
return 0 ;
}
void pressESCtoQuit()
{
bool gameOver = false ;
while ( gameOver == false ){
SDL_Event gameEvent;
while ( SDL_PollEvent( & gameEvent) != 0 ){
if ( gameEvent.type == SDL_QUIT ){
gameOver = true ;
}
if ( gameEvent.type == SDL_KEYUP ){
if ( gameEvent.key.keysym.sym == SDLK_ESCAPE ){
gameOver = true ;
}
}
}
}
return ;
}
2.7:补充说明。
1) 这个程序用到了前面课程中建立起来的函数pressESCtoQuit();
2) 在VC的IDE中,引用的bmp文件可能会需要提供完整的绝对路径,否则直接通过VC菜单启动的程序可能找不到实际上就与exe文件在同一个文件夹中的bmp图片。你可以直接找到编译后的exe文件,在exe文件夹中直接运行,则不会出现这个问题。或者,你可以修改VC默认的资源文件路径,再或者,你可以尊重VC的默认约定,将资源文件拷贝到工程目录下(与源文件*.cpp在同一个文件夹里面)。