为了感谢开源中国社区,在测试中文使用了一个开源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