SDL入门教程(六):鼠标事件和SDL读取其它格式的图片

7.1:鼠标事件-演示程序源代码

        今天因为一个网上的朋友的请求,做个一个关于鼠标事件的演示程序。实际上,可以完全用到前面我们构造的类和类方法,这里送上主程序,供大家参考。其他两个文件和图片文件均不需要任何改变。
#include "SurfaceClass.h"

int game(int argc, char* argv[]);
int main(int argc ,char* argv[])
{
    int mainRtn = 0;
    try {
        mainRtn = game(argc, argv);
    }
    catch ( const ErrorInfo& info ) {
        info.show();
        return -1;
    }
    
    return mainRtn;
}

int game(int argc ,char* argv[])
{
    //Create a SDL screen.
    const int SCREEN_WIDTH = 640;
    const int SCREEN_HEIGHT = 480;
    ScreenSurface screen(SCREEN_WIDTH, SCREEN_HEIGHT);

    //Create 2 SDL surface for the screen that just created.
    DisplaySurface backGround("bg.bmp", screen);
    DisplaySurface frontImage("image.bmp", screen);

    //Blit backGround surface to screen and flip the screen.
    backGround.blit();
    screen.flip();

    //moving image's coordinate.
    int xpos = 0;
    int ypos = 0;
    //mouse's coordinate.
    int px = 0;
    int py = 0;
    //moving image's size.
    const int IMG_WIDTH = 128;
    const int IMG_HEIGHT = 128;
    //main loop.
    bool gameOver = false;
    while( gameOver == false ){
        //press ESC or click X to quit.
        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;
                }
            }
            //mouse event
            if ( gameEvent.type == SDL_MOUSEMOTION ) {
                px = gameEvent.motion.x;
                py = gameEvent.motion.y;
            }
        }

        if ( xpos < px )
            xpos++;
        if ( xpos > px )
            xpos--;
        if ( ypos < py )
            ypos++;
        if ( ypos > py )
            ypos--;

        backGround.blit(xpos, ypos, xpos, ypos, IMG_WIDTH, IMG_HEIGHT);
        frontImage.blit(xpos, ypos);
        screen.flip();
    }

    return 0;
}



1:扩充库(Extension Libraries)

        SDL本身所支持的,仅仅是读取bmp格式的图片。要使用其它格式的图片,我们需要使用SDL的扩充库。在下面地址,我们可以下载到相关文件SDL_image-devel-1.2.6-VC8.zip
http://www.libsdl.org/projects/SDL_image/
        与SDL本身的设置一样,将include下的*.h文件拷贝到:
C:\MinGW\include\SDL (MinGW)
C:\Program Files\Microsoft Visual Studio 9.0\VC\include\SDL (VC2008)
        将*.lib文件拷贝到:
C:\MinGW\lib (MinGW)
C:\Program Files\Microsoft Visual Studio 9.0\VC\lib (VC2008)
        将*.dll文件拷贝到:
C:\WINDOWS\system32

        在编译的时候,gcc注意增加共同编译的库文件-lSDL_image,比如,我设置了一个批处理文件g++img.bat内容如下:
g++ -o MySDL.exe main.cpp -lmingw32 -lSDLmain -lSDL -lSDL_image -mwindows
        在VC2008中,需要在projec属性中,Configuration Properties -- Linker -- Input -- Additional Dependencies 下增加SDL_image.lib。

        在程序的头文件中,需要增加:
#include "SDL/SDL_image.h"

2:更加通用的Display Surface构造函数

        我们现在可以回头过来修改我们在SDL入门教程(五):6、对C++异常机制的思考,代码重写中的Display Surface类的构造函数,使其能够更加通用的读取其它格式的图片。
DisplaySurface::DisplaySurface(std::string file_name, const ScreenSurface& screen):
fileName(file_name)
{
    SDL_Surface* pSurfaceTemp = IMG_Load(file_name.c_str());
    if ( pSurfaceTemp == 0 )
        throw ErrorInfo(SDL_GetError());
    pSurface = SDL_DisplayFormat(pSurfaceTemp);
    if ( pSurface == 0 )
        throw ErrorInfo(SDL_GetError());
    SDL_FreeSurface(pSurfaceTemp);
    pScreen = screen.point();
}
        IMG_Load()可以读取多种格式的图片文件,包括BMP, PNM, XPM, LBM, PCX, GIF, JPEG, TGA和PNG。

3:将图片修改为适合显示的格式
SDL_Surface *SDL_DisplayFormat(SDL_Surface *surface);
        在上面的程序中,我们使用到了函数SDL_DisplayFormat()。在之前的教程中,我一直没有用到这个函数,是因为我还没有发现用 SDL_LoadBMP()的时候会出现格式兼容性的问题——即使是图片位深与显示不一致。但是使用IMG_Load()的时候,小小的bug出现了。所 以,这里我必须使用SDL_DisplayFormat(),将读取的图片文件转换为适合显示的格式。
        如果转换失败,或者内存溢出,这个函数将返回空指针。

作者: landuochong   发布时间: 2010-12-27