Как вы уже заметили, каждый урок построен на основе предыдущего, поэтому мы не будем пока отступать от этой традиции. Для того, чтобы отслеживать все события и обрабатывать их в предназначенных для этого функциях, нужно создать новый класс. Добавьте в проект два файла CEvent.h и CEvent.cpp. В этих двух файлах мы будем обрабатывать приходящие сообщения, и вызвать соответствующую функцию. Наш класс CApp будет наследоваться от этого класса, поэтому, когда мы начнем обрабатывать события, просто будем переопределять его функции.
Откройте CEvent.h и добавьте следующий код:
#ifndef _CEVENT_H_ #define _CEVENT_H_ #include <SDL.h> class CEvent { public: CEvent(); virtual ~CEvent(); virtual void OnEvent(SDL_Event* Event); virtual void OnInputFocus(); virtual void OnInputBlur(); virtual void OnKeyDown(SDLKey sym, SDLMod mod, Uint16 unicode); virtual void OnKeyUp(SDLKey sym, SDLMod mod, Uint16 unicode); virtual void OnMouseFocus(); virtual void OnMouseBlur(); virtual void OnMouseMove(int mX, int mY, int relX, int relY, bool Left,bool Right,bool Middle); virtual void OnMouseWheel(bool Up, bool Down); //Not implemented virtual void OnLButtonDown(int mX, int mY); virtual void OnLButtonUp(int mX, int mY); virtual void OnRButtonDown(int mX, int mY); virtual void OnRButtonUp(int mX, int mY); virtual void OnMButtonDown(int mX, int mY); virtual void OnMButtonUp(int mX, int mY); virtual void OnJoyAxis(Uint8 which, Uint8 axis, Sint16 value); virtual void OnJoyButtonDown(Uint8 which, Uint8 button); virtual void OnJoyButtonUp(Uint8 which, Uint8 button); virtual void OnJoyHat(Uint8 which, Uint8 hat, Uint8 value); virtual void OnJoyBall(Uint8 which, Uint8 ball, Sint16 xrel, Sint16 yrel); virtual void OnMinimize(); virtual void OnRestore(); virtual void OnResize(int w,int h); virtual void OnExpose(); virtual void OnExit(); virtual void OnUser(Uint8 type, int code, void* data1, void* data2); }; #endif
Нехилый получился класс? Ну а теперь откройте CEvent.cpp, и добавьте следующий код:
#include "CEvent.h" CEvent::CEvent() { } CEvent::~CEvent() { //Do nothing } void CEvent::OnEvent(SDL_Event* Event) { switch(Event->type) { case SDL_ACTIVEEVENT: { switch(Event->active.state) { case SDL_APPMOUSEFOCUS: { if ( Event->active.gain ) OnMouseFocus(); else OnMouseBlur(); break; } case SDL_APPINPUTFOCUS: { if ( Event->active.gain ) OnInputFocus(); else OnInputBlur(); break; } case SDL_APPACTIVE: { if ( Event->active.gain ) OnRestore(); else OnMinimize(); break; } } break; } case SDL_KEYDOWN: { OnKeyDown(Event->key.keysym.sym,Event->key.keysym.mod,Event->key.keysym.unicode); break; } case SDL_KEYUP: { OnKeyUp(Event->key.keysym.sym,Event->key.keysym.mod,Event->key.keysym.unicode); break; } case SDL_MOUSEMOTION: { OnMouseMove(Event->motion.x,Event->motion.y,Event->motion.xrel,Event->motion.yrel,(Event->motion.state&SDL_BUTTON(SDL_BUTTON_LEFT))!=0,(Event->motion.state&SDL_BUTTON(SDL_BUTTON_RIGHT))!=0,(Event->motion.state&SDL_BUTTON(SDL_BUTTON_MIDDLE))!=0); break; } case SDL_MOUSEBUTTONDOWN: { switch(Event->button.button) { case SDL_BUTTON_LEFT: { OnLButtonDown(Event->button.x,Event->button.y); break; } case SDL_BUTTON_RIGHT: { OnRButtonDown(Event->button.x,Event->button.y); break; } case SDL_BUTTON_MIDDLE: { OnMButtonDown(Event->button.x,Event->button.y); break; } } break; } case SDL_MOUSEBUTTONUP: { switch(Event->button.button) { case SDL_BUTTON_LEFT: { OnLButtonUp(Event->button.x,Event->button.y); break; } case SDL_BUTTON_RIGHT: { OnRButtonUp(Event->button.x,Event->button.y); break; } case SDL_BUTTON_MIDDLE: { OnMButtonUp(Event->button.x,Event->button.y); break; } } break; } case SDL_JOYAXISMOTION: { OnJoyAxis(Event->jaxis.which,Event->jaxis.axis,Event->jaxis.value); break; } case SDL_JOYBALLMOTION: { OnJoyBall(Event->jball.which,Event->jball.ball,Event->jball.xrel,Event->jball.yrel); break; } case SDL_JOYHATMOTION: { OnJoyHat(Event->jhat.which,Event->jhat.hat,Event->jhat.value); break; } case SDL_JOYBUTTONDOWN: { OnJoyButtonDown(Event->jbutton.which,Event->jbutton.button); break; } case SDL_JOYBUTTONUP: { OnJoyButtonUp(Event->jbutton.which,Event->jbutton.button); break; } case SDL_QUIT: { OnExit(); break; } case SDL_SYSWMEVENT: { //Ignore break; } case SDL_VIDEORESIZE: { OnResize(Event->resize.w,Event->resize.h); break; } case SDL_VIDEOEXPOSE: { OnExpose(); break; } default: { OnUser(Event->user.type,Event->user.code,Event->user.data1,Event->user.data2); break; } } } void CEvent::OnInputFocus() { //Pure virtual, do nothing } void CEvent::OnInputBlur() { //Pure virtual, do nothing } void CEvent::OnKeyDown(SDLKey sym, SDLMod mod, Uint16 unicode) { //Pure virtual, do nothing } void CEvent::OnKeyUp(SDLKey sym, SDLMod mod, Uint16 unicode) { //Pure virtual, do nothing } void CEvent::OnMouseFocus() { //Pure virtual, do nothing } void CEvent::OnMouseBlur() { //Pure virtual, do nothing } void CEvent::OnMouseMove(int mX, int mY, int relX, int relY, bool Left,bool Right,bool Middle) { //Pure virtual, do nothing } void CEvent::OnMouseWheel(bool Up, bool Down) { //Pure virtual, do nothing } void CEvent::OnLButtonDown(int mX, int mY) { //Pure virtual, do nothing } void CEvent::OnLButtonUp(int mX, int mY) { //Pure virtual, do nothing } void CEvent::OnRButtonDown(int mX, int mY) { //Pure virtual, do nothing } void CEvent::OnRButtonUp(int mX, int mY) { //Pure virtual, do nothing } void CEvent::OnMButtonDown(int mX, int mY) { //Pure virtual, do nothing } void CEvent::OnMButtonUp(int mX, int mY) { //Pure virtual, do nothing } void CEvent::OnJoyAxis(Uint8 which,Uint8 axis,Sint16 value) { //Pure virtual, do nothing } void CEvent::OnJoyButtonDown(Uint8 which,Uint8 button) { //Pure virtual, do nothing } void CEvent::OnJoyButtonUp(Uint8 which,Uint8 button) { //Pure virtual, do nothing } void CEvent::OnJoyHat(Uint8 which,Uint8 hat,Uint8 value) { //Pure virtual, do nothing } void CEvent::OnJoyBall(Uint8 which,Uint8 ball,Sint16 xrel,Sint16 yrel) { //Pure virtual, do nothing } void CEvent::OnMinimize() { //Pure virtual, do nothing } void CEvent::OnRestore() { //Pure virtual, do nothing } void CEvent::OnResize(int w,int h) { //Pure virtual, do nothing } void CEvent::OnExpose() { //Pure virtual, do nothing } void CEvent::OnExit() { //Pure virtual, do nothing } void CEvent::OnUser(Uint8 type, int code, void* data1, void* data2) { //Pure virtual, do nothing }
Да… Очень много кода, но все SDL события должны быть покрыты (т.е. как-то обрабатываться). В этом обработчике, мы принимаем указатель на событие типа SDL_Event, а затем, в зависимости от вида события (нажатие клавиши или перемещение мыши) вызываем соответствующую функцию. Не пугайтесь такого объема кода, на самом деле тут всё предельно просто.
Теперь, когда у нас всё настроено, давайте перейдем в CApp.h и добавим созданный класс:
#ifndef _CAPP_H_ #define _CAPP_H_ #include <SDL.h> #include "CEvent.h" #include "CSurface.h" class CApp : public CEvent { private: bool Running; SDL_Surface* Surf_Display; SDL_Surface* Surf_Test; public: CApp(); int OnExecute(); public: bool OnInit(); void OnEvent(SDL_Event* Event); void OnLoop(); void OnRender(); void OnCleanup(); }; #endif
Все должно нормально откомпилироваться. У нас есть настроенный класс обработки событий, осталось связать его с основным классом игры. Откройте CApp_OnEvent.cpp и редактировать следующие функции:
#include "CApp.h" void CApp::OnEvent(SDL_Event* Event) { CEvent::OnEvent(Event); }
Теперь наше сообщение будет передаваться в класс и там корректно обрабатываться. Наша функция проверки события теперь переопределена. Мы избавились от проверки на SDL_Quit, и вместо этого передаем событие во внутреннюю функцию. Снова откройте CApp.h снова, и добавить следующие функции:
#ifndef _CAPP_H_ #define _CAPP_H_ #include <SDL.h> #include "CEvent.h" #include "CSurface.h" class CApp : public CEvent { private: bool Running; SDL_Surface* Surf_Display; SDL_Surface* Surf_Test; public: CApp(); int OnExecute(); public: bool OnInit(); void OnEvent(SDL_Event* Event); void OnExit(); void OnLoop(); void OnRender(); void OnCleanup(); }; #endif
Функция OnExit будет обрабатывать событие SDL_Quit (нажатие пользователем крестика). Итак, прототип у нас есть, осталось запрограммировать его функционал. Откройте CApp_OnEvent.cpp, и добавьте следующее:
#include "CApp.h" void CApp::OnEvent(SDL_Event* Event) { CEvent::OnEvent(Event); } void CApp::OnExit() { Running = false; }
Перекомпилируйте, и запустите. Вы можете закрыть приложение, совсем как и раньше.
Я рекомендую вам ознакомиться с другими видами событий событий, попробовать прописать ответ на них в соответствующих функциях-обработчиках, потому-что в дальнейшем мы будем использовать некоторые из этих событий в наших играх.
В следующем уроке нас ждет увлекательное путешествие, в конце которого мы создадим нашу первую реальную игру — Tic-Tac-Toe (Крестики/Нолики).
Какой-то маленький получился урок, несмотря на большой объем кода. Видимо придется мне дополнить его небольшим примером обработки клавиш UP, DOWN, RIGHT и LEFT (стрелочки).
Откройте CEvent.cpp, найдите там функцию CEvent::OnKeyDown и напишите в ней следующее:
#include <iostream> using namespace std;
А потом перепишите функционал CEvent::OnKeyDown
void CEvent::OnKeyDown(SDLKey sym, SDLMod mod, Uint16 unicode) { switch (sym) { case SDLK_ESCAPE: { cout << "Hey, HABR! Escape pressed by m0sk1t\n"; break; } case SDLK_UP: { cout << "Hey, HABR! UP pressed by m0sk1t\n"; break; } case SDLK_DOWN: { cout << "Hey, HABR! DOWN pressed by m0sk1t\n"; break; } case SDLK_LEFT: { cout << "Hey, HABR! LEFT pressed by m0sk1t\n"; break; } case SDLK_RIGHT: { cout << "Hey, HABR! RIGHT pressed by m0sk1t\n"; break; } default: break; } }
Откомпилируйте и запустите, а затем понажимайте стрелочки и закройте окно игры. Вы должны наблюдать примерно это:
Видите консольный вывод? Он отображает результат того что в функции CEvent::OnKeyDown мы теперь отслеживаем факт нажатия одной из стрелочек и выводим описание того какая из них была нажата (ну и клавиша Escape туда попала).
Ссылки на все уроки:
ссылка на оригинал статьи http://habrahabr.ru/post/167245/
Добавить комментарий