爲了感謝開源中國社區,在測試中文使用了一個開源TTF,字體仍是蠻好看的! app
還記得在第3篇裏的事件,總不能不了了之。如今接着分析,對我而講這也是一個學習的過程,下面先講鍵盤事件裏的方向鍵入手。 ide
#include "SDL/SDL.h" #include "SDL/SDL_image.h" #include "SDL/SDL_ttf.h" #include <string> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; const int SCREEN_BPP = 32; //The surfaces SDL_Surface *background = NULL; SDL_Surface *upMessage = NULL; SDL_Surface *downMessage = NULL; SDL_Surface *leftMessage = NULL; SDL_Surface *rightMessage = NULL; SDL_Surface *message = NULL; SDL_Surface *screen = NULL; //The event structure SDL_Event event; //字體 TTF_Font *font = NULL; //字體的顏色 SDL_Color textColor = { 0, 0, 0 }; SDL_Surface *load_image( std::string filename ) { /* 省略*/ } void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL ) { /*省略*/ } bool init() { //初始化全部的子系統 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; } //初始化 SDL_ttf if( TTF_Init() == -1 ) { return false; } //設置窗口標題 caption SDL_WM_SetCaption( "Press an Arrow Key", NULL ); return true; } bool load_files() { //Load the background image background = load_image( "background.png" ); //打開字體 font = TTF_OpenFont( "lazy.ttf", 72 ); //If there was a problem in loading the background if( background == NULL ) { return false; } //If there was an error in loading the font if( font == NULL ) { return false; } return true; } void clean_up() { //釋放 surfaces SDL_FreeSurface( background ); SDL_FreeSurface( upMessage ); SDL_FreeSurface( downMessage ); SDL_FreeSurface( leftMessage ); SDL_FreeSurface( rightMessage ); //Close the font TTF_CloseFont( font ); TTF_Quit(); SDL_Quit(); } int main( int argc, char* args[] ) { //Quit flag bool quit = false; //Initialize if( init() == false ){ return 1; } //Load the files if( load_files() == false ) { return 1; } //Generate the message surfaces upMessage = TTF_RenderText_Solid( font, "Up was pressed.", textColor ); downMessage = TTF_RenderText_Solid( font, "Down was pressed.", textColor ); leftMessage = TTF_RenderText_Solid( font, "Left was pressed", textColor ); rightMessage = TTF_RenderText_Solid( font, "Right was pressed", textColor ); //Apply the background apply_surface( 0, 0, background, screen ); //While the user hasn't quit while( quit == false ) { //If there's an event to handle if( SDL_PollEvent( &event ) ) { //If a key was pressed if( event.type == SDL_KEYDOWN ) { //Set the proper message surface switch( event.key.keysym.sym ) { case SDLK_UP: message = upMessage; break; case SDLK_DOWN: message = downMessage; break; case SDLK_LEFT: message = leftMessage; break; case SDLK_RIGHT: message = rightMessage; break; } } //If the user has Xed out the window else if( event.type == SDL_QUIT ) { //退出程序 quit = true; } } //If a message needs to be displayed if( message != NULL ) { //Apply the background to the screen apply_surface( 0, 0, background, screen ); //Apply the message centered on the screen apply_surface( ( SCREEN_WIDTH - message->w ) / 2, ( SCREEN_HEIGHT - message->h ) / 2, message, screen ); //Null the surface pointer message = NULL; } //Update the screen if( SDL_Flip( screen ) == -1 ){ return 1; } } clean_up(); return 0; }
保存爲sdl07.cpp 編譯運行 學習
g++ -o sdl07 sdl07.cpp -lSDL -lSDL_image -lSDL_ttf ./sdl07
趕忙按上下左右鍵試試,想一想貪吃蛇,你有沒有這種感受能實現其中某些功能了呢,那就是控制方向,對於軟件開發來講,方法都是相通,只不過有些是通過層層的封裝而已。 要作幾點說明:event.type 和event.type.keysym.sym,這麼變態,前一個仍是好理解,而對於event.type.keysym.sym,若是看過內核代碼確定會很清楚,裏面是結構體嵌套,接下找到SDL_KeyboardEvent結構體。 測試
typedef struct{ Uint8 type; /*SDL_KEYDOWN or SDL_KEYUP */ Uint8 state; /* 狀態:SDL_PRESSED or SDL_RELEASED */ SDL_keysym keysym; } SDL_KeyboardEvent;
繼續深究SDL_keysym 字體
typedef struct{ Uint8 scancode; /* 硬件專用,但不知道與驅動有沒有關係*/ SDLKey sym; /* SDL虛擬鍵 */ SDLMod mod; /* 當前狀態的存儲 */ Uint16 unicode; /* UNICODE使用 */ } SDL_keysym;
SDLKey:: SDLK_LEFT,SDLK_UP……SDLKey的值能夠查閱SDL_keysym.h(代碼就不帖了)文件,SDLMOD的值也能夠在這裏面找到。這樣sdl07.cpp這個程序就沒有問題了,差很少鍵盤的問題均可以解決了,比起Windows下面HOOK處理是否是要爽不少,鍵盤事件是解決了,鼠標確定不能錯過下面接着講。 ui
#include "SDL/SDL.h" #include "SDL/SDL_image.h" #include <string> //Screen attributes const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; const int SCREEN_BPP = 32; //The button states in the sprite sheet const int CLIP_MOUSEOVER = 0; const int CLIP_MOUSEOUT = 1; const int CLIP_MOUSEDOWN = 2; const int CLIP_MOUSEUP = 3; //The surfaces SDL_Surface *buttonSheet = NULL; SDL_Surface *screen = NULL; //The event structure SDL_Event event; //The clip regions of the sprite sheet SDL_Rect clips[ 4 ]; // Button類 class Button { private: //The attributes of the button SDL_Rect box; //The part of the button sprite sheet that will be shown SDL_Rect* clip; public: //Button初始化的值 Button( int x, int y, int w, int h ); //Handles events and set the button's sprite region void handle_events(); //Shows the button on the screen void show(); }; SDL_Surface *load_image( std::string filename ) { /*省略*/ } void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL ) { /* 省略*/ } bool init() { if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 ) { return false; } screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE ); if( screen == NULL ){ return false; } SDL_WM_SetCaption( "Button Test", NULL ); return true; } bool load_files() { buttonSheet = load_image( "button.png" ); if( buttonSheet == NULL ){ return false; } return true; } void clean_up() { SDL_FreeSurface( buttonSheet ); SDL_Quit(); } void set_clips() { //Clip the sprite sheet clips[ CLIP_MOUSEOVER ].x = 0; clips[ CLIP_MOUSEOVER ].y = 0; clips[ CLIP_MOUSEOVER ].w = 320; clips[ CLIP_MOUSEOVER ].h = 240; clips[ CLIP_MOUSEOUT ].x = 320; clips[ CLIP_MOUSEOUT ].y = 0; clips[ CLIP_MOUSEOUT ].w = 320; clips[ CLIP_MOUSEOUT ].h = 240; clips[ CLIP_MOUSEDOWN ].x = 0; clips[ CLIP_MOUSEDOWN ].y = 240; clips[ CLIP_MOUSEDOWN ].w = 320; clips[ CLIP_MOUSEDOWN ].h = 240; clips[ CLIP_MOUSEUP ].x = 320; clips[ CLIP_MOUSEUP ].y = 240; clips[ CLIP_MOUSEUP ].w = 320; clips[ CLIP_MOUSEUP ].h = 240; } Button::Button( int x, int y, int w, int h ) { //Set the button's attributes box.x = x; box.y = y; box.w = w; box.h = h; //Set the default sprite clip = &clips[ CLIP_MOUSEOUT ]; } void Button::handle_events() { int x = 0, y = 0; //If the mouse moved if( event.type == SDL_MOUSEMOTION ) { //Get the mouse offsets x = event.motion.x; y = event.motion.y; //If the mouse is over the button if( ( x > box.x ) && ( x < box.x + box.w ) && ( y > box.y ) && ( y < box.y + box.h ) ) { //Set the button sprite clip = &clips[ CLIP_MOUSEOVER ]; } //If not else { //Set the button sprite clip = &clips[ CLIP_MOUSEOUT ]; } } //If a mouse button was pressed if( event.type == SDL_MOUSEBUTTONDOWN ) { //If the left mouse button was pressed if( event.button.button == SDL_BUTTON_LEFT ) { //Get the mouse offsets x = event.button.x; y = event.button.y; //If the mouse is over the button if( ( x > box.x ) && ( x < box.x + box.w ) && ( y > box.y ) && ( y < box.y + box.h ) ) { //Set the button sprite clip = &clips[ CLIP_MOUSEDOWN ]; } } } //If a mouse button was released if( event.type == SDL_MOUSEBUTTONUP ) { //If the left mouse button was released if( event.button.button == SDL_BUTTON_LEFT ) { //Get the mouse offsets x = event.button.x; y = event.button.y; //If the mouse is over the button if( ( x > box.x ) && ( x < box.x + box.w ) && ( y > box.y ) && ( y < box.y + box.h ) ) { //Set the button sprite clip = &clips[ CLIP_MOUSEUP ]; } } } } void Button::show() { //Show the button apply_surface( box.x, box.y, buttonSheet, screen, clip ); } int main( int argc, char* args[] ) { //Quit flag bool quit = false; //Initialize if( init() == false ) { return 1; } //Load the files if( load_files() == false ) { return 1; } //Clip the sprite sheet set_clips(); //Make the button Button myButton( 170, 120, 320, 240 ); //While the user hasn't quit while( quit == false ) { //If there's events to handle if( SDL_PollEvent( &event ) ) { //Handle button events myButton.handle_events(); //If the user has Xed out the window if( event.type == SDL_QUIT ) { //Quit the program quit = true; } } //Fill the screen white SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB( screen->format, 0xFF, 0xFF, 0xFF ) ); //Show the button myButton.show(); //Update the screen if( SDL_Flip( screen ) == -1 ) { return 1; } } //Clean up clean_up(); return 0; }保存爲sdl071.cpp 編譯運行
g++ -o sdl071 sdl071.cpp -lSDL -lSDL_image -lSDL_ttf ./sdl071
趕忙用鼠標去點點試試,不過這裏一共只有4種狀況以下圖 spa
這個程序裏面見到類了,固然不能用類也能實現,不過會複雜點,關於這個代碼的分析就放在下一篇裏纔講了。還多羅嗦幾句,有一個概念叫人機交互,你想能與你交互有那些東西:仍是鍵盤,鼠標,其次像工業應用比較多,傳感器類,還圖像圖像(人臉識別),語言(如蘋果的siri)……,可是當前最多仍是鼠標鍵盤吧! code