zoukankan      html  css  js  c++  java
  • SDL事件处理

      到目前为止,我们的程序还是静态的,只能显示图片,不能接收任何的按键、不能检测鼠标等。所有窗口程序基本上都是基于事件驱动的,当某个事件发生时,程序会做出相应的相应,这种方式和控制台程序有很大的不同,这种方式更加接近真实的世界.

      那么什么是事件呢?事件可能是由使用者操作产生的,比如使用者按下一个键,松开一个键,或点击了鼠标等,也可能是硬件产生的比如时钟脉冲等。任何一个窗口程序都使用一个事件队列来保存这些事件,队列的一个特性便是先进先出,先进入队列的事件会被优先处理。如下图所示,事件在队尾入队,队头出队,先发生的事件先入队,出队的时候也会先出队。

    image

    事件入队是由系统处理的,我们不用关心,我们关心的是什么事件发生了,如何处理?那么首先要看SDL里有哪些事件呢

    SDL事件可分为四种:

    1. 键盘事件 包括按下键、松开键两类事件,也就是说当你在键盘上按下一个键时发生了一个按键事件,当你松开这个键时又会发生松开键事件。

    2. 鼠标事件 包括鼠标移动事件、按下鼠标键、松开鼠标键,和键盘一样,当你移动鼠标时发生鼠标移动事件,按下一个鼠标键,比如说左键时,发生按下鼠标键事件,松开鼠标键时会发生松开鼠标键事件。

    3. 游戏杆事件 这个暂时用不到,以后再说。

    4. 系统事件 包括:

      a) 活动事件(Active event) 判断当前应用是否处于活动状态;
      b) 离开事件(quit event)当你点击窗口右上角的×关闭窗口时,发生离开事件;
      c) 改变窗口大小事件
      d) 窗口重绘事件
      ) 其他系统事件
      f) 用户自定义事件

      在这节里我们主要讲述键盘事件的处理,当我们按下一个键时,我们首先要从事件队列里接收这个事件,然后检测事件的类型,判别是那种事件,根据事件类型做相应的处理,整个过程就是这样简单。

      要接收一个事件,我们就要定义一个变量来保存该事件,在SDL中事件有专门的类型SDL_Event类型,SDL_Event是一个结构体,其定义如下:

    typedef union SDL_Event
    {
      Uint8 type; //事件类型
      SDL_ActiveEvent active; //窗口焦点、输入焦点及鼠标焦点的失去和得到事件
      SDL_KeyboardEvent key; //键盘事件,键盘按下和释放
      SDL_MouseMotionEvent motion; //鼠标移动事件
      SDL_MouseButtonEvent button; //鼠标按键事件
      SDL_JoyAxisEvent jaxis; //手柄事件
      SDL_JoyBallEvent jball; //手柄事件
      SDL_JoyHatEvent jhat; //手柄事件   SDL_JoyButtonEvent jbutton; //手柄事件   SDL_ResizeEvent resize; //窗口大小变化事件   SDL_ExposeEvent expose; //窗口重绘事件   SDL_QuitEvent quit; //退出事件   SDL_UserEvent user; //用户自定义事件   SDL_SysWMEvent syswm; //平台相关的系统事件 } SDL_Event;

      SDL_Event是一个联合体,其中type字段决定了是那种事件,是一个枚举类型,其定义为:

    typedef enum {
      SDL_NOEVENT = 0, /* 未使用 */
      SDL_ACTIVEEVENT, /* 应用程序失去焦点或得到焦点*/
      SDL_KEYDOWN, /* 按下某键 */
      SDL_KEYUP, /* 松开某键 */
      SDL_MOUSEMOTION, /* 鼠标移动 */
      SDL_MOUSEBUTTONDOWN, /* 鼠标键按下 */
      SDL_MOUSEBUTTONUP, /* 鼠标键松开 */
      SDL_JOYAXISMOTION, /*游戏杆事件 */
      SDL_JOYBALLMOTION, /*游戏杆事件*/
      SDL_JOYHATMOTION, /*游戏杆事件*/
      SDL_JOYBUTTONDOWN, /*游戏杆事件*/
      SDL_JOYBUTTONUP, /*游戏杆事件*/
      SDL_QUIT, /*离开 */
      SDL_SYSWMEVENT, /* 系统事件 */
      SDL_EVENT_RESERVEDA, /* 保留 */
      SDL_EVENT_RESERVEDB, /* 保留 */
      SDL_VIDEORESIZE, /* 用户改变视频模式 */
      SDL_VIDEOEXPOSE, /* 屏幕重画 */
      SDL_EVENT_RESERVED2, /* 保留*/
      SDL_EVENT_RESERVED3, /* 保留 */
      SDL_EVENT_RESERVED4, /* 保留 */
      SDL_EVENT_RESERVED5, /* 保留 */
      SDL_EVENT_RESERVED6, /* 保留*/
      SDL_EVENT_RESERVED7, /* 保留 */
      SDL_USEREVENT = 24, /* 用户自定义事件 */
      /* This last event is only for bounding internal arrays
      It is the number of bits in the event mask datatype -- Uint32
      */
      SDL_NUMEVENTS = 32
    } SDL_EventType;

       所以,我们要检测事件一般会这样写:

    SDL_Event myEvent;//事件
    int quit = 0;
    while (!quit) //建立事件主循环
    {
      while (SDL_PollEvent(&myEvent))//从队列里取出事件
      {
        switch (myEvent.type) //根据事件类型分门别类去处理
        {
        case SDL_QUIT://如果是离开事件
          quit = 1;
          break;
        }
      }
    }

      这是一段典型的事件处理程序,首先建立一个主循环处理事件,然后用SDL_PollEvent从事件队列里取出事件,判断类型,然后处理。直到用户按下离开则结束主循环。在这里从事件队列里取出事件用的函数是SDL_PollEvent,它的原型是:

      int SDL_PollEvent(SDL_Event *event);

      参数:event是SDL_Event类型变量的地址。

      现在myEvent变量保存了事件的信息,如果你按的是离开,则myEvent保存了离开事件的信息,每一种事件都有自己的事件类型,保存处理本类事件的信息,离开事件的结构为:

      typedef struct{

        Uint8 type

      } SDL_QuitEvent;

      其中,type的值就是SDL_QUIT 。

      下面我们以一个例子来说一下如何检测键盘按键,这个例子是在屏幕上显示一个小球,然后我们通过鼠标按键移动小球,代码如下:

    /*
      功能:演示事件处理
      作者:csl
      日期:2012-5-9
    */
    #include <stdio.h> 
    #include <stdlib.h> 
    #include "SDL.h" //根据你加载sdl方式去填写
    
    //屏幕尺寸
    #define SCREENWIDTH  640
    #define SCREENHEIGH  480
    #define BPP  32
    
    //小球尺寸
    #define BALLWIDTH  66
    #define BALLHEIGH  66
    
    SDL_Surface *gpScreen;//显示表面
    SDL_Surface *gpBall;//小球图片表面
    SDL_Surface *gpBackGround;//背景图片
    SDL_Event myEvent;//事件
    
    SDL_Surface *loadImage(char *aFilename);
    int main(int argc,char *argv[])
    {
        int quit = 0;
        SDL_Rect dst;
    
        if((SDL_Init(SDL_INIT_VIDEO)==-1)) //初始化视频子系统
        {
            printf("Unable to init SDL: %s\n", SDL_GetError());
            exit(-1);
        }
        atexit(SDL_Quit);// 注册SDL_Quit,当退出时调用,使得退出时程序自动清理
    
        //创建32位600*480窗口
        gpScreen = SDL_SetVideoMode(640,480, 32, SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF );
        if(!gpScreen) 
        { 
            exit(1);
        }
        gpBall = loadImage("ball.bmp");
        gpBackGround = loadImage("background.jpg");
        SDL_BlitSurface(gpBackGround,NULL,gpScreen,NULL);
        SDL_BlitSurface(gpBall,NULL,gpScreen,NULL);
        SDL_Flip(gpScreen);
        while (!quit)
        {
            while (SDL_PollEvent(&myEvent))
            {
                switch (myEvent.type)
                {
                case SDL_QUIT:
                    quit = 1;
                    break;
                }
            }
        }
        
        SDL_FreeSurface(gpScreen);//退出程序前必须释放 
        SDL_FreeSurface(gpBall);
        SDL_FreeSurface(gpBackGround);
        SDL_Quit();
        //system("pause"); 
        return 0; 
    }
    
    /*--------------------------------------------------------------------
        函数名:    loadImage
        参  数:    char *filename  图像文件的名字
        返回值:    SDL_Surface * 返回指向图像表面的指针
        功  能:    载入图像
        备  注:
    ----------------------------------------------------------------------*/
    SDL_Surface *loadImage(char *aFilename)
    {
        SDL_Surface* loadedImage = NULL;
        SDL_Surface* optimizedImage = NULL;
    
        //载入图像
        loadedImage = IMG_Load( aFilename);
        if( NULL != loadedImage )//If the image loaded
        {
            //创建优化图像
            optimizedImage = SDL_DisplayFormat( loadedImage );
    
            //释放loadImage
            SDL_FreeSurface( loadedImage );
        }
        return optimizedImage;
    }

      程序运行结果:

    image 

           现在在屏幕左上方显示了一个小球图片,这和以前没什么不同,但窗口可以移动,你可以向拖动windows的窗口一样拖动这个窗口,并且当你点击关闭窗口时,可以结束程序,这就是事件主循环里我们写的事件捕捉代码起了作用,当检测到SDL_QUIT事件(也就是关闭窗口)将quit赋值为1,则结束主循环,接着释放资源,关闭程序。但小球并不能移动,所以下面我们要检测键盘上下左右键的按键,以移动小球。

    switch (myEvent.type)
    {
    case SDL_QUIT:
        quit = 1;
        break;
    case SDL_KEYDOWN:
        //处理按下键
        break;
    case SDL_KEYUP:
        //处理松开键;
        break;
    }

      我们增加了两个case块,检测是否按下或松开了键盘上的键。一个是检测是否按下了键,一个检测是否松开了按键。如果有按下或松开了键,那么myEvent中保存的是键盘事件,键盘事件的结构是:

      typedef struct{

        Uint8 type; // SDL_KEYDOWN 或 SDL_KEYUP

        Uint8 state; // SDL_PRESSED 或 SDL_RELEASED

        SDL_keysym keysym; // 包含按键的信息

      } SDL_KeyboardEvent;

      这个结构用来保存键盘按键的信息,type和state记录相同的信息,如果是

      按下键则:type = SDL_KEYDOWN 和 state = SDL_PRESSED

      当松开键时:type = SDL_KEYUP 和 state = SDL_RELEASED

      keysym记录了按键的信息,其结构为:

        typedef struct{

          Uint8 scancode; // 键盘硬件产生的扫描码

          SDLKey sym; // SDL所定义的虚拟码

          SDLMod mod; // 修饰键

          Uint16 unicode; //按键的Unicode码

        } SDL_keysym;

      对于一般程序只要检测sys就够了,最多再检测是否同时按下alt、shelft键等修饰键mod。sym是SDL定义的枚举类型,其中常用的虚拟键有:

    虚拟码

    按键

    SDLK_0 … SDLK_9

    0 … 9

    SDLK_a … SDLK_z

    a … z

    SDLK_UP, SDLK_DOWN,

    SDLK_LEFT, SDLK_RIGHT

    上下左右键

    SDLK_F1 … SDLK_F15

    F1 … F15

    SDLK_LSHIFT, SDLK_RSHIFT

    左 SHIFT键、右 SHIFT键

    SDLK_LALT, SDLK_RALT

    左 ALT键、右 ALT键

    SDLK_LCTRL, SDLK_RCTRL

    左 CTRL键、右 CTRL键

      mod是修饰键信息,常用的修饰键有:

    SDL 修饰键

    意义

    KMOD_NONE

    无修饰键

    KMOD_NUM

    数字锁定键开启

    KMOD_CAPS

    大写键开启

    KMOD_LCTRL, KMOD_RCTRL

    按下左 CTRL 键、右 CTRL键

    KMOD_CTRL

    按下任一 CTRL键

    KMOD_LSHIFT, KMOD_RSHIFT

    按下左 SHIFT键、右 SHIFT键

    KMOD_SHIFT

    按下任一 SHIFT键

    KMOD_LALT, KMOD_RALT

    按下左 ALT键、右 ALT键

    KMOD_ALT

    按下任一 ALT键

      现在我们知道了键盘事件结构和常用键值,那么我们就可以完善键盘检测功能了。   

    switch (myEvent.type)
    {
    case SDL_QUIT:
      quit = 1;
      break;
    case SDL_KEYDOWN:
      (myEvent.key.keysym.sym)
      {
      case SDLK_LEFT:
        printf("你按下了←\n");
        break;
      case SDLK_RIGHT:
        printf("你按下了→\n");
        break;
      case SDLK_UP:
        printf("你按下了↑\n");
        break;
      case SDLK_DOWN:
        printf("你按下了↓\n");
        break;
      }
      break;
    case SDL_KEYUP:
      switch(myEvent.key.keysym.sym)
      {
      case SDLK_LEFT:
        printf("你松开了←\n");
        break;
      case SDLK_RIGHT:
        printf("你松开了→\n");
        break;
      case SDLK_UP:
        printf("你松开了↑\n");
        break;
      case SDLK_DOWN:
        printf("你松开了↓\n");
        break;
      }
      break;
    }

      将这一段代码加到程序里,我们按一下上下左右键,可以看到控制台窗口里显示了printf输出的信息,你按一个←键,输出“你按下←键”,“你松开了←键”。证明我们写的键盘检测代码起了作用。

    image

      switch的括号里的表达式myEvent.key. keysym.sym的含义是这样,从左往右看,myEvent.key这是取出键盘事件,key是事件结构中的成员,当发生的是键盘事件时,key保存键盘事件的信息, myEvent.key.keysym中keysym是键盘事件结构中按键信息成员,至此我们得到按键的信息,按键信息是一个结构体,我们只需检测它的sym成员的值就可以判定用户按的是那个键。

      到现在为止,你应经明白了如何检测键盘按键,那么我们可以处理键盘按键,移动图片了,原理就是当我们按向右的键时,我们可以让图片的x坐标加1,然后将背景图片重新刷到屏幕上,将小球图片刷到新的位置,然后刷新屏幕就可以了。

      我们要在主函数开头定义两个整型变量:ballX,ballY,来表示小球的坐标,然后修改按下键代码检测程序段为:

        while (SDL_PollEvent(&myEvent))
            {
                switch (myEvent.type)
                {
                case SDL_QUIT:
                    quit = 1;
                    break;
                case SDL_KEYDOWN:
                    switch(myEvent.key.keysym.sym)
                    {
                    case SDLK_LEFT:
                        ballX--;
                        break;
                    case SDLK_RIGHT:
                        ballX++;
                        break;
                    case SDLK_UP:
                        ballY--;
                        break;
                    case SDLK_DOWN:
                        ballY++;
                        break;
                    }
                    break;
                case SDL_KEYUP:
                    switch(myEvent.key.keysym.sym)
                    {
                    case SDLK_LEFT:
                        printf("小球的坐标:(%d,%d)\n",ballX,ballY);
                        break;
                    case SDLK_RIGHT:
                        printf("小球的坐标:(%d,%d)\n",ballX,ballY);
                        break;
                    case SDLK_UP:
                        printf("小球的坐标:(%d,%d)\n",ballX,ballY);
                        break;
                    case SDLK_DOWN:
                        printf("小球的坐标:(%d,%d)\n",ballX,ballY);
                        break;
                    }
    
                    break;
                }
                SDL_BlitSurface(gpBackGround,NULL,gpScreen,NULL);
                dst.x = ballX;
                dst.y = ballY;
                dst.w = gpBall->w;
                dst.h = gpBall->h;
                SDL_BlitSurface(gpBall,NULL,gpScreen,&dst);
                SDL_Flip(gpScreen);
    
            }

      我们通过按上下左右键,修改小球的坐标,然后将坐标赋给dst(目标矩形),表面里有每个图像的宽和高,所以dst.w = gpBall->w;dst.h = gpBall->h;取得小球的宽度和高度赋给dst的w和h;然后重新将背景传输到显示表面上,将小球表面传输到显示表面上,dst指出小球表面在显示表面的位置。然后刷新屏幕。运行程序,可以看到如下结果:

    image

       现在我们可以移动小球,但程序还有一些bug,1)我们一次移动一个像素,移动速度很慢;2)从结果上看小球的坐标可以负的,也就是小球可以移动到显示表面外,这是没有意义的;3)我们必须不停按键才能移动小球,而在记事本里如果我们按住一个字母键不松开,可以输入一串字母,如果移动小球时也可以按下键不松开来移动小球效果会更好。

      我们可以定一个speed变量表示小球移动速度,将这个变量定义到主函数开头:int speed = 1;//初始值为1个像素。然后我们增加一个对“+”键的检测,如果按了“+”我们把speed的值增1,这样就可以控制速度了,同样增加一个对“-”键的检测,当用户按下“-”后将speed的值减1。然后将原来的ballX++修改成ballX+=speed;这样就可以增加移动的速度了,其他类似修改。当这样解决不了小球会移动到屏幕外的问题,所以我们应对ballX的值检测,若果ballX小于0,则让它等于0;若ballX+BALLWIDTH的值大于屏幕宽度则让ballX等于SCREENWIDTH-BALLWIDTH。这样小球在x方向就不能移动出屏幕了,y方向做同样的处理。修改后的代码:

    while (SDL_PollEvent(&myEvent))
            {
                switch (myEvent.type)
                {
                case SDL_QUIT:
                    quit = 1;
                    break;
                case SDL_KEYDOWN:
                    switch(myEvent.key.keysym.sym)
                    {
                    case SDLK_LEFT:
                        ballX-=speed;
                        ballX = ballX<0?0:ballX;
                        break;
                    case SDLK_RIGHT:
                        ballX+=speed;
                        ballX = (ballX+BALLWIDTH)>SCREENWIDTH?(SCREENWIDTH-BALLWIDTH):ballX;
                        break;
                    case SDLK_UP:
                        ballY-=speed;
                        ballY=ballY<0?0:ballY;
                        break;
                    case SDLK_DOWN:
                        ballY+=speed;
                        ballY = (ballY+BALLHEIGH)>SCREENHEIGH?(SCREENHEIGH-BALLHEIGH):ballY;
                        break;
                    case SDLK_MINUS:
                        speed--;
                        speed=speed>0?speed:0;
                    case SDLK_EQUALS:
                        speed++;
                    }
                    break;
                case SDL_KEYUP:
                    switch(myEvent.key.keysym.sym)
                    {
                    case SDLK_LEFT:                    
                        printf("小球的坐标:(%d,%d)\n",ballX,ballY);
                        break;
                    case SDLK_RIGHT:                    
                        printf("小球的坐标:(%d,%d)\n",ballX,ballY);
                        break;
                    case SDLK_UP:                    
                        printf("小球的坐标:(%d,%d)\n",ballX,ballY);
                        break;
                    case SDLK_DOWN:                    
                        printf("小球的坐标:(%d,%d)\n",ballX,ballY);
                        break;
                    }
                    break;
                }
                SDL_BlitSurface(gpBackGround,NULL,gpScreen,NULL);
                dst.x = ballX;
                dst.y = ballY;
                dst.w = gpBall->w;
                dst.h = gpBall->h;
                SDL_BlitSurface(gpBall,NULL,gpScreen,&dst);
                SDL_Flip(gpScreen);
         }

      还有第3个问题,其实第3个问题是“粘连键”,在SDL中有一个函数:

      int SDL_EnableKeyRepeat(int delay, int interval);

      参数 delay是指按下多长时间才启动键的粘连;毫秒

      interval 是连续键的间隔时间,时间单位毫秒

      这个函数可以启动键的粘连,所谓粘连就是如果你按下一个键超过一定毫秒数,比如说500毫秒,每个interval毫秒就认为你又按了一次该建。比如说我们传进两个实参500,30,则系统认为如果你按一个键500毫秒以上,每个30毫秒,则等价你又按了一次这个键。我们把这个函数调用放到事件主循环外。整个程序代码如下:

    /*
      功能:演示事件处理
      作者:csl
      日期:2012-5-9
    */
    #include <stdio.h> 
    #include <stdlib.h> 
    #include "SDL.h"
    
    //屏幕尺寸
    #define SCREENWIDTH  640
    #define SCREENHEIGH  480
    #define BPP  32
    
    //小球尺寸
    #define BALLWIDTH  66
    #define BALLHEIGH  66
    
    SDL_Surface *gpScreen;//显示表面
    SDL_Surface *gpBall;//小球图片表面
    SDL_Surface *gpBackGround;//背景图片
    SDL_Event myEvent;//事件
    
    SDL_Surface *loadImage(char *aFilename);
    int main(int argc,char *argv[])
    {
        int quit = 0;
        SDL_Rect dst;
        int ballX = 0;//小球的初始坐标
        int ballY = 0;
        int speed = 1;
        
    
        if((SDL_Init(SDL_INIT_VIDEO)==-1)) //初始化视频子系统
        {
            printf("Unable to init SDL: %s\n", SDL_GetError());
            exit(-1);
        }
        atexit(SDL_Quit);// 注册SDL_Quit,当退出时调用,使得退出时程序自动清理
    
        //创建32位600*480窗口
        gpScreen = SDL_SetVideoMode(SCREENWIDTH,SCREENHEIGH, BPP, SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF );
        if(!gpScreen) 
        { 
            exit(1);
        }
        gpBall = loadImage("ball.bmp");
        gpBackGround = loadImage("background.jpg");
        SDL_BlitSurface(gpBackGround,NULL,gpScreen,NULL);
        SDL_BlitSurface(gpBall,NULL,gpScreen,NULL);
        SDL_Flip(gpScreen);
        SDL_EnableKeyRepeat(500,30);
        while (!quit)
        {
            while (SDL_PollEvent(&myEvent))
            {
                switch (myEvent.type)
                {
                case SDL_QUIT:
                    quit = 1;
                    break;
                case SDL_KEYDOWN:
                    switch(myEvent.key.keysym.sym)
                    {
                    case SDLK_LEFT:
                        ballX-=speed;
                        ballX = ballX<0?0:ballX;
                        break;
                    case SDLK_RIGHT:
                        ballX+=speed;
                        ballX = (ballX+BALLWIDTH)>SCREENWIDTH?(SCREENWIDTH-BALLWIDTH):ballX;
                        break;
                    case SDLK_UP:
                        ballY-=speed;
                        ballY=ballY<0?0:ballY;
                        break;
                    case SDLK_DOWN:
                        ballY+=speed;
                        ballY = (ballY+BALLHEIGH)>SCREENHEIGH?(SCREENHEIGH-BALLHEIGH):ballY;
                        break;
                    case SDLK_MINUS:
                        speed--;
                        speed=speed>0?speed:0;
                    case SDLK_EQUALS:
                        speed++;
                    }
                    break;
                case SDL_KEYUP:
                    switch(myEvent.key.keysym.sym)
                    {
                    case SDLK_LEFT:                    
                        printf("小球的坐标:(%d,%d)\n",ballX,ballY);
                        break;
                    case SDLK_RIGHT:                    
                        printf("小球的坐标:(%d,%d)\n",ballX,ballY);
                        break;
                    case SDLK_UP:                    
                        printf("小球的坐标:(%d,%d)\n",ballX,ballY);
                        break;
                    case SDLK_DOWN:                    
                        printf("小球的坐标:(%d,%d)\n",ballX,ballY);
                        break;
                    }
                    break;
                }
                SDL_BlitSurface(gpBackGround,NULL,gpScreen,NULL);
                dst.x = ballX;
                dst.y = ballY;
                dst.w = gpBall->w;
                dst.h = gpBall->h;
                SDL_BlitSurface(gpBall,NULL,gpScreen,&dst);
                SDL_Flip(gpScreen);
            }
        }
        
        SDL_FreeSurface(gpScreen);//退出程序前必须释放 
        SDL_FreeSurface(gpBackGround);
        SDL_FreeSurface(gpBall);
        SDL_Quit();
    
        //system("pause"); 
        return 0; 
    }
    
    /*--------------------------------------------------------------------
        函数名:    loadImage
        参  数:    char *filename  图像文件的名字
        返回值:    SDL_Surface * 返回指向图像表面的指针
        功  能:    载入图像
        备  注:
    ----------------------------------------------------------------------*/
    SDL_Surface *loadImage(char *aFilename)
    {
        SDL_Surface* loadedImage = NULL;
        SDL_Surface* optimizedImage = NULL;
    
        //载入图像
        loadedImage = IMG_Load( aFilename);
    
        if( NULL != loadedImage )//If the image loaded
        {
            //创建优化图像
            optimizedImage = SDL_DisplayFormat( loadedImage );
    
            //释放loadImage
            SDL_FreeSurface( loadedImage );
        }
        return optimizedImage;
    }

      这个程序还有一点不够完善的地方,就是小球白色背景没有去除,这个将在后续课程讲述,你可以点击这儿下载源代码。

  • 相关阅读:
    Android简单的聊天室开发(client与server沟通)
    由于物化视图定义为on commit导致update更新基表慢的解决方案
    Eclipse中JBOSS5.1无法启动的问题解决办法
    自定义Web控件写事件
    Axis2(10):使用soapmonitor模块监视soap请求与响应消息
    Axis2(9):编写Axis2模块(Module)
    举例android项目中的string.xml出现这个The character reference must end with the ';' delimiter.错误提示的原因及解决办法
    Axis2(8):异步调用WebService
    Axis2(7):将Spring的装配JavaBean发布成WebService
    动态内存空间初始化方式的比较
  • 原文地址:https://www.cnblogs.com/landmark/p/2494542.html
Copyright © 2011-2022 走看看