SDL Events
SDL Tutorials October 25th, 2007Alongside the basics of game development is something called Events. Events are basically interactions the program has with the user. These events can be keyboards, mice, joysticks, gamepads, and so on, or events from our operating system. It’s important to understand how events work if we are to approriately interact a user with a game. We’ve already been using events, but only for closing our window, now we’ll look at how to receive events from the user.
If you haven’t caught on, each tutorial builds off the previous, so we’ll be using the code from the previous lesson. In order to track all these events and throw them into nice functions, lets create a new class. Create two files called CEvent.h and CEvent.cpp. These two files will handle our events, and call the appropriate function. CApp will inherit this class, so when we need to catch an event we simply override a function.
Open up CEvent.h and add the following code:
#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
Pretty hefty class right? Alright, open up CEvent.cpp, and add the following code:
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
}
Lots of code, but all the SDL events should be covered. What we basically are doing is taking an SDL_Event pointer, and switching through the types, and then calling the appropriate function. It just looks like a lot since they are quite a bit of events.
Now that this has been all setup, let’s jump over to CApp.h and link the two together:
#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
Everything should compile just fine. We have the event class setup, now lets actually link events to our new class structure. Open up CApp_OnEvent.cpp and edit the following function:
void CApp::OnEvent(SDL_Event* Event) {
CEvent::OnEvent(Event);
}
We’re passing the Event structure to our class now, it will take care of the correct function calls. Now when we want to check for an event, we override the function. Since we got rid of checking for the SDL_QUIT event, lets use the function instead. Open up CApp.h again, and add the following function:
#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
The OnExit function handles the SDL_QUIT events. Now that we have the prototype, lets define what it does. Open up CApp_OnEvent.cpp, and add the following:
void CApp::OnEvent(SDL_Event* Event) {
CEvent::OnEvent(Event);
}
void CApp::OnExit() {
Running = false;
}
Recompile, and try it out. You should be able to close the application just like before.
I encourage you to look through some of the various events that we can check. Later on we’ll use some of these events in our games, but for now try to familiarize yourself with them.
Jump on over to the next tutorial to take a look at creating our first game, Tic-Tac-Toe.
SDL Events – Tutorial Files:
Win32: Zip, Rar
Linux: Tar (Thanks Gaten)












October 25th, 2007 at 4:55 pm
This is a really nice tutorial – I’m really looking forward to this tic-tac-toe game.
January 29th, 2008 at 8:15 am
Hi, your tutorials are very good and they helped me a lot. But this article seems to be incomplete and the content of the CEvent.cpp stops suddenly in the CEvent::OnEvent Method body. I hope there’s going to be more on that article …
greetings, Benjamin
January 29th, 2008 at 11:05 am
Sorry for that, it seems that Wordpress deleted part of my post for some odd reason. At any rate, I will no longer be using the Wordpress form to submit tutorials, but will be inserting directly into the database. Besides, the stupid RTE editor keeps freezing my Firefox (go figure).
Thanks for the comments!
February 28th, 2008 at 12:00 am
Linux archive with makefile: http://gaten.homelinux.net/sdltuts/sdl_events.tar.gz
March 22nd, 2008 at 6:11 pm
I really like your tutorials, not just because the SDL parts , it’s nice to see some more advanced stuffs in use like singleton and abstract classes, the examples in textbooks are usually quite bad about them.
March 31st, 2008 at 7:12 am
Thanks zakalwe!
April 1st, 2008 at 2:33 am
Very nice tutorials, thank you. One note, shouldn’t event functions in CEvent be protected, not public?
April 1st, 2008 at 7:18 am
I suppose that would be a better way to do it, but I don’t really expect people to instantiate CEvent objects (though they could). That’s the thing about C++, if I could make the class an interface I would. For stricter OOP, by all means make it protected.
June 2nd, 2008 at 1:25 pm
A good addition to your tutorials could be a section with practice exercises, where you’d give us the description and any necessary image files, etc., and we’d code the answer. Just a suggestion though
June 3rd, 2008 at 12:03 pm
I might do something like that in the future, thanks Arseniy.
June 23rd, 2008 at 4:38 pm
[...] rzeczy, które mnie tam jeszcze zainteresowały, przy okazji założonego celu – znalazłem zarządzanie zdarzeniami wykorzystujące SDL – akurat jestem na etapie adaptowania tej lekcji na własny użytek. Szczerze polecam:) Zwłaszcza [...]
June 26th, 2008 at 8:11 pm
This is a really good tutorial I have ever seen. But During the study, I do have one problem. I run the source code which download from this website on vs2005 in Vista sys. The SDL window only appear for a second and then disappear. So can you guys help me with this?
Thank you for providing such a good tutorial!
July 15th, 2008 at 1:04 pm
Charles,
Sorry for not replying sooner! Usually that means something is not loading right. Such as the program not being able to find graphics or the like. Make sure your exe is in the same folder as all your images and such.
July 26th, 2008 at 7:37 pm
Charles, Tim,
First, Tim, thanks for the SDL course. It’s awsome.
Charles, I had the same problem as you, to solve it:
Remove all the .o file from your project folder (they are .o files from the previous tutorial) Now rebuild your project and the problem is solved.
September 5th, 2008 at 11:00 am
I’ve been working through the tutorials (excellent job, by the way, I’ve gone through a few at this point and yours are the best) and while attempting to compile in VS2005 I get the error C2352 "Illegal call of a non-static member function." The problem is in the CApp.cpp file with the OnEvent function. But since CEvent::OnEvent is virtual, it can’t also be static. Anyway, I guess the point is, do you have any advice, or is there something that I’m missing?
September 5th, 2008 at 6:21 pm
Nevermind. I FINALLY found my mistake. It was an inheritance issue, or lack of inheritance entirely, as it turned out. Again, thanks for all of your excellent work!
November 29th, 2008 at 4:59 am
Any suggestions on idiot proofing one’s self to save on debugging time…
(I don’t copy and paste so that I make sure I won’t kill myself by forgetting things later on, when I don’t have a nice neat, step for step guide.)
Anyway, thank you, yet another fabulous tutorial.
December 5th, 2008 at 7:57 am
Anthony Compton, No problem! I am guessing you were trying to call a CEvent function, but didn’t inherit CEvent first into CApp?
Xavier, Cool name… But anyway, a few hints. Always set your pointers to NULL, always check if a pointer is NULL before you use it, always make sure you are within bounds of an array (int X[2]; cout << X[3]; //Error!). These are the most common mistakes I find. Also, always make sure you put that semi-colon where it needs to be, including the end of classes. I’ve seen that a lot as well.
March 5th, 2009 at 3:14 pm
Great Tutorials!
I wanted to mention I had the same problem as Charles at first however Sefo’s solution worked for me.
March 18th, 2009 at 4:40 am
Just wanting to say much props on the fantastic SDL tuts. It’s helped me get into C++ to a level where I now feel almost comfortable with it! Thanks loads and keep up the excellent work!
X-T
March 21st, 2009 at 7:20 pm
The source code wont compile…CEvent has not been declared and no “‘voidCApp::OnExit()’ member function declared in class `CApp’”
A little assistance, please?
March 26th, 2009 at 12:36 am
Dave, did you put “void OnExit();” in the CApp.h?
April 8th, 2009 at 8:48 pm
Hey guys, Im getting this error:
error: cannot call member function `virtual void CEvent::OnEvent(SDL_Event*)’ without object|
I have absolutely no idea what this mean, so any help you can offer would be greatly appreciated.
PS, great guide, everything ran perfectly to this point (which i find very uncommon in tutorials)
April 9th, 2009 at 5:49 pm
just incase anyone else gets the same error I did, I missed this section out of CApp.h (inside the brackets)
class CApp ( : public CEvent { )
Now it builds/runs perfectly
May 7th, 2009 at 10:51 am
Where is the next one? Don’t leave me hanging, bro!
Actually, this is a lot of good info I didn’t understand before, so thanks. I’d still love a bit more though… =D
June 2nd, 2009 at 6:19 am
This site is freaking awesome! I’ve been looking for a nice way to combine what I’ve been learning in SDL (My class is very messy). This site has a great example! Keep up the awesome work!
June 2nd, 2009 at 6:53 am
Thanks for the compliments guys.
June 14th, 2009 at 5:45 am
OMG, infinite loop!
I cannot get out from the first while loop in “CApp.cpp”.
while( Running ) {…}
and it never ends.
I think the problem is the second while loop.
while( SDL_PollEvent( &Event ) )
{ OnEvent( &Event ); }
Either SDL_PollEvent() is false, or OnEvent() is not setting this ” Running = false; “.
But I don’t know which and why.
(probably “OnEvent()” )
June 14th, 2009 at 7:52 am
Never mind. I forgot to put
case SDL_QUIT: {…}
on CEvent.cpp