Chapter 6: Event handling (SDL4FP)

This is an SDL 1.2 chapter. SDL 1.2 is obsolete since it has been replaced by SDL 2.0. Unless you have good reasons to stay here you may prefer to go for the modern SDL 2.0 :-).

If the user is moving the mouse, pressing/releasing a button on the keyboard or pressing/releasing the fire key on the joystick then you speak of events. Further events are resizing a window or switching between several applications. For games though the events described first are much more important. SDL provides a quite easy way to notice and react to such events, which is called event handling.

First of all using event handling means to understand the concept of event handling. Events have a special structure you should know about. For example an pressed key is an event or a moved mouse is an event. SDL differs altogether fourteen such events. Every event stores different information depending on its kind. For example the key board event stores the information which key was pressed. The mouse motion event stores the information to which position the mouse got moved. If you got a mouse motion event you can’t read out key information and so on. Therefore you have the following general structure to the event data: event.eventstructure.data.

To make event handling possible you have to include the unit SDL_EVENTS. The event handling subsystem is automatically initialized along with the video subsystem.

We have to create an event variable which is of pointer type pSDL_EVENT. We will create a second variable of boolean type just to control the while loop.

PROGRAM chap6_1;
USES crt, SDL, SDL_VIDEO, SDL_EVENTS;

VAR
screen:pSDL_SURFACE;
loopstop:boolean=FALSE;
test_event:pSDL_EVENT;

BEGIN
CLRSCR;
SDL_INIT(SDL_INIT_VIDEO);
screen:=SDL_SETVIDEOMODE(200,200,8,SDL_SWSURFACE);
IF screen=NIL THEN HALT;

NEW(test_event);

DISPOSE(test_event);
SDL_FREESURFACE(screen);
SDL_QUIT;
END.

We want to check the program if any event occured and if so, we want to know which kind of event happened. So we make a while loop which will run until loopstop gets true.

The command SDL_POLLEVENT(parameter) checks if there are pending events and if so it will take the oldest and save it to parameter which is an event record of pSDL_EVENT type. For example if the user presses (then releases) left mouse button, then presses (then releases) space button on keyboard and finally moves the mouse there are altogether five events: 1. left mouse button pressed, 2. left mouse button released, 3. space key pressed, 4. space key released, 5. mouse moved. If you poll for events now you will get the first event (left mouse button pressed) and saved it’s properties to the event variable we specified as parameter. The next poll will save the properties of next event (left mouse button released) to event variable and so on. SDL_POLLEVENT(parameter) will return 1 if it has found pending event or 0 if there wasn’t any pending event.

Fortunately you don’t have to notice any event which is made by the user ;). By event^.eventtype you can easily check which type of event you got. In the case described before it would be 1. SDL_MOUSEBUTTONDOWN, 2. SDL_MOUSEBUTTONUP, 3. SDL_KEYDOWN, 4. SDL_KEYUP, 5. SDL_MOUSEMOTION. It should be senseful to check for the event kind by using the case command.

PROGRAM chap6_1;
USES crt, SDL, SDL_VIDEO, SDL_EVENTS;

VAR
screen:pSDL_SURFACE;
loopstop:boolean=FALSE;
test_event:pSDL_EVENT;

BEGIN
CLRSCR;
SDL_INIT(SDL_INIT_VIDEO);
screen:=SDL_SETVIDEOMODE(200,200,8,SDL_SWSURFACE);
IF screen=NIL THEN HALT;

NEW(test_event);

WHILE loopstop=FALSE DO
BEGIN
IF SDL_POLLEVENT(test_event)=1 THEN
BEGIN
write('pending event: ');

CASE test_event^.eventtype OF
SDL_EVENTACTIVE: writeln('Application is/is not active');
SDL_KEYDOWN: writeln('Key pressed ');
SDL_KEYUP: writeln('Key released');
SDL_MOUSEMOTION: writeln('Mouse motion');
SDL_MOUSEBUTTONDOWN: writeln('Mouse button down');
SDL_MOUSEBUTTONUP: writeln('Mouse button up');
SDL_JOYAXISMOTION: writeln('Joystick axis motion');
SDL_JOYBALLMOTION: writeln('Joystick's trackball motion');
SDL_JOYHATMOTION: writeln('Joystick's hat position changed');
SDL_JOYBUTTONDOWN: writeln('Joystick button pressed');
SDL_JOYBUTTONUP: writeln('Joystick button released');
SDL_EVENTQUIT: writeln('User-requested quit');
END;

END ELSE writeln('no pending events');
DELAY(150);
END;
DISPOSE(test_event);
SDL_FREESURFACE(screen);
SDL_QUIT;
END.

Actually you shouldn’t try this source as it is written there because it will end up in an endless loop. The DELAY command is used because otherwise you won’t notice any pending events because they are polled too fast and it seems as if there would never be any pending events (just remove DELAY to confirm).

We now want to try the program to read out which key the user pressed on the keyboard. If the key is the escape-key (Esc) the program should stop. We already check the type of the event we polled. So if the event is a keyboard event the further checking should proceed. In our case especially if a key gets pressed. An keyboard event record contains a field called keysym. Keysym is a record of SDL_KEYSYM. SDL_KEYSYM is defined in SDL_KEYBOARD unit. It contains four fields. Scancode which is hardware dependent scancode should be avoided if you want to make hardware independent programs. It is usual integer variable. Next is sym which stores SDLKEY. These SDL keys are independent and it is strongly recommended to use them! In the example we want break up if escape key gets pressed. Its SDL key code is 27. If you want to know what SDL keys are defined look up in the table page. The variable modifier stores modifier keys (like shift, ctrl,…) pressed and stores SDLMod. SDL modifier keys can be found at table page as well. The fourth variable is unicode which may be used to read out unicode characters but to use this you have to enable it what is not described in this tutorial.

To read out or compare the key the user pressed we must use the expression test_event^.key.keysym.sym. Do you remember the general structure of an event (event.eventstructure.data)? – test_event^ is the event, the event structure is defined as an key event by key and the data we want to know is the key pressed contained in keysym.sym.

PROGRAM chap6_1;
USES crt, SDL, SDL_VIDEO, SDL_EVENTS;

VAR
screen:pSDL_SURFACE;
loopstop:boolean=FALSE;
test_event:pSDL_EVENT;

BEGIN
CLRSCR;
SDL_INIT(SDL_INIT_VIDEO);
screen:=SDL_SETVIDEOMODE(200,200,8,SDL_SWSURFACE);
IF screen=NIL THEN HALT;

NEW(test_event);

WHILE loopstop=FALSE DO
BEGIN
IF SDL_POLLEVENT(test_event)=1 THEN
BEGIN
write('pending event: ');

CASE test_event^.eventtype OF
SDL_EVENTACTIVE: writeln('Application is/is not active');
SDL_KEYDOWN:

BEGIN
write('Key pressed ');
writeln('(SDLKey=',test_event^.key.keysym.sym,')');
IF test_event^.key.keysym.sym=27 THEN loopstop:=true;
END;

SDL_KEYUP: writeln('Key released');
SDL_MOUSEMOTION: writeln('Mouse motion');
SDL_MOUSEBUTTONDOWN: writeln('Mouse button down');
SDL_MOUSEBUTTONUP: writeln('Mouse button up');
SDL_JOYAXISMOTION: writeln('Joystick axis motion');
SDL_JOYBALLMOTION: writeln('Joystick's trackball motion');
SDL_JOYHATMOTION: writeln('Joystick's hat position changed');
SDL_JOYBUTTONDOWN: writeln('Joystick button pressed');
SDL_JOYBUTTONUP: writeln('Joystick button released');
SDL_EVENTQUIT: writeln('User-requested quit');
END;

END ELSE writeln('no pending events');
DELAY(150);
END;
DISPOSE(test_event);
SDL_FREESURFACE(screen);
SDL_QUIT;
END.

Actually this is easy, isn’t it?

This file contains the source code: chap6_1.pas (right click and “save as”)
This file is the executable: chap6_1.exe (right click and “save as”)

ATTENTION: This is just the first part. The second part will describe mouse handling, which is much easier.

Leave a Reply

Your email address will not be published. Required fields are marked *