3.SDL遊戲開發:把代碼寫長一點(二)

看問題想本質,讀USB驅動源碼時,要讀至thread_run纔到精彩處,那麼對於上層的應用來講,那種至高境界估計是到不了,可是仍是接着把代碼上面代碼理解下,從整個代碼來看,裏面增長的SDL函數就只有兩個, 一個是 SDL_DisplayFormat()另一個 SDL_WM_SetCaption()這兩個函數都很簡單。 html

首先咱們先找男人 #man SDL_DisplayFormat 結果以下: app

#include "SDL.h"
       SDL_Surface *SDL_DisplayFormat(SDL_Surface *surface);
DESCRIPTION
       This  function  takes  a  surface and copies it to a new surface of the
       pixel format and colors of the video  framebuffer,  suitable  for  fast
       blitting onto the display surface. It calls SDL_ConvertSurface
       If you want to take advantage of hardware colorkey or alpha blit accel-
       eration, you should set the colorkey and  alpha  value  before  calling
       this function.

       If you want an alpha channel, see SDL_DisplayFormatAlpha.
使用SDL_DisplayFormat(),將讀取的圖片文件轉換爲適合顯示的格式[引發的緣由是顯示不一樣],其英文好點看函數名就知道了。   SDL_WM_SetCaption設置窗口標題。

咱們知道圖片有不少種格式,可是SDL標準備只支持rBMP格式的,若是你不相信,回頭把sdl02.cpp和sdl01.cpp對應的圖片和代碼修改,試試——,可是經過擴展就OK,其實這件事,咱們早就作了,在安裝SDL時就已經安裝 ide

yum install SDL-devel SDL_mixer-devel SDL_image-devel SDL_ttf-devel

其中SDL_mixer-devel SDL_ttf-devel SDL_image-devel就是擴展庫                                                                         使用也很簡單 函數

g++ -o my my.cpp -lSDL -lSDL_mixer -lSDL_image -lSDL_ttf

固然要用這些文件還得包含相應的頭文件,咱們能夠看下SDL目錄下面的文件, ui

[root@localhost sdl]# ls /usr/include/SDL/
begin_code.h       SDL_endian.h    SDL_loadso.h    SDL_rwops.h
close_code.h       SDL_error.h     SDL_main.h      SDL_stdinc.h
SDL_active.h       SDL_events.h    SDL_mixer.h     SDL_syswm.h
SDL_audio.h        SDL_getenv.h    SDL_mouse.h     SDL_thread.h
SDL_byteorder.h    SDL.h           SDL_mutex.h     SDL_timer.h
SDL_cdrom.h        SDL_image.h     SDL_name.h      SDL_ttf.h
SDL_config.h       SDL_joystick.h  SDL_opengl.h    SDL_types.h
SDL_config-i386.h  SDL_keyboard.h  SDL_platform.h  SDL_version.h
SDL_cpuinfo.h      SDL_keysym.h    SDL_quit.h      SDL_video.h
[root@localhost sdl]#
擦亮你的眼睛,發現SDL_image.h SDL_mixer.h SDL_ttf.h沒??

使用時#include "SDL/SDL_image.h" …… 關於更多SDL_image的文檔的能夠從這裏獲得。像以前用的SDL_Surface *SDL_LoadBMP(const char *file);函數就能夠用IMG_Load代替。換成其它的圖片試試。這裏就不拿出來丟人現眼了。 this

接着把代碼寫長一點,接下我講與鍵盤有關的事。 spa

#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include <string>

const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

//The surfaces
SDL_Surface *image = NULL;
SDL_Surface *screen = NULL;

//The event structure that will be used
SDL_Event event;  /* 注意  */

SDL_Surface *load_image( std::string filename )
{
    SDL_Surface* loadedImage = NULL;

    //The optimized image that will be used
    SDL_Surface* optimizedImage = NULL;

    //果斷用上
    loadedImage = IMG_Load( filename.c_str() );

    //If the image loaded
    if( loadedImage != NULL ){
        //Create an optimized image
        optimizedImage = SDL_DisplayFormat( loadedImage );

        //Free the old image 若是不是很理解SDL_DisplayFormat()注意old說明使用函數時分配了新的內存空間
        SDL_FreeSurface( loadedImage );
    }

    return optimizedImage;
}

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination )
{
    //Temporary rectangle to hold the offsets
    SDL_Rect offset;

    //Get the offsets
    offset.x = x;
    offset.y = y;

    //Blit the surface
    SDL_BlitSurface( source, NULL, destination, &offset );
}

bool init()
{
    //Initialize all SDL subsystems
    if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 ){
        return false;
    }

    //Set up the screen
    screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );

    //If there was an error in setting up the screen
    if( screen == NULL ){
        return false;
    }

    //Set the window caption
    SDL_WM_SetCaption( "Event test", NULL );

    //If everything initialized fine
    return true;
}

bool load_files()
{
    //Load the image
    image = load_image( "x.png" );

    //If there was an error in loading the image
    if( image == NULL ){
        return false;
    }

    //If everything loaded fine
    return true;
}

void clean_up()
{
    //Free the surface
    SDL_FreeSurface( image );

    //Quit SDL
    SDL_Quit();
}

int main( int argc, char* args[] )
{
    //Make sure the program waits for a quit
    bool quit = false;

    //初始化
    if( init() == false ){
        return 1;
    }

    //導入文件
    if( load_files() == false ){
        return 1;
    }

    //Apply the surface to the screen
    apply_surface( 0, 0, image, screen );

    //Update the screen
    if( SDL_Flip( screen ) == -1 ){
        return 1;
    }

    //While the user hasn't quit
    while( quit == false ) {
        //While there's an event to handle
        while( SDL_PollEvent( &event ) ) {
            //If the user has Xed out the window
            if( event.type == SDL_QUIT ){
                //退出程序
                quit = true;
            }
        }
    }

    //Free the surface and quit SDL
    clean_up();

    return 0;
}

保存爲sdl03.cpp 編譯 code

g++ -o sdl03 sdl03.cpp -lSDL -lSDL_image
./sdl03

這個圖就不上了,太easy,若是不-lSDL_image會出現什麼狀況呢! orm

g++ -o sdl03 sdl03.cpp -lSDL
程序會在編譯的出現找不到函數的狀況


[bluesky@localhost sdl]$ g++ -o sdl03 sdl03.cpp -lSDL
/tmp/ccAqStJv.o: In function `load_image(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
sdl03.cpp:(.text+0x23): undefined reference to `IMG_Load'
collect2: ld returned 1 exit status
[bluesky@localhost sdl]$
那如今來看代碼。程序應該不難理解,  看到SDL_Event經過man  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是一個共同體,不是每一件事都要尋根究底的,關於每個字段意思能夠到這裏查看,關於Uint8 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_PollEvent()輪詢事件[還有一個SDL_WaitEvent()],談到這裏會引出一個對於遊戲開發很重的東西,那就是鍵盤、鼠標事件[還有同樣是操做杆],當這裏我前不想打算如今就深刻下去,後面會有專門的篇幅來談這件事。看到

while( SDL_PollEvent( &event ) ) {
            //If the user has Xed out the window
            if( event.type == SDL_QUIT ){

對比SDL_EventType能夠得出退出的條件,運行程序,點擊關閉按鈕試試。再對以前的sdl02 sdl01發現有什麼不一樣,可是咱們按ESC鍵卻無效。

相關文章
相關標籤/搜索