Jump to content
  • Advertisement
Sign in to follow this  
goulash32

I need a solution for a silly key event problem in SDL!

This topic is 4173 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Please and thank you. I've just become interested in programming again after a six month hiatus, and I've decided to develop a small, portable 3d isometric engine in SDL. This is my first time using the library, but I'm off to a good start. Things were going swimmingly until I came to keyboard event handling. My main application class is inheritable and the Update() function (in addition to others) is virtual. The base definition of Update() polls the event queue for a SDL_QUIT message, and exits if it is found. Now, it's reasonable to expect the programmer to call the base function in the overrided one to handle that message. Here's the problem. From what I've seen, SDL provides no way to poll the event queue without discarding the last polled event. My input class has methods that return booleans if the requested key is hit, down, up, etc. However, these poll the event queue as well. You can see the problem when you handle input after calling the base Update() method: the keys are never processed because the queue is empty after polling for the SDL_QUIT message (or vice versa, where the quit event isn't processed if it's called after input handling.) I've thought of pushing the event back on the stack after it's been processed, but to the best of my knowledge it's a FIFO push system, and that would stick the program in an infinite loop. There's probably a really obvious solution, but I just can't grasp it right now. Help would be much appreciated.

Share this post


Link to post
Share on other sites
Advertisement
If you have 2 places where you poll the queue, your program should really be set up so that only 1 of those places can ever be used. The queue is a shared resource and you need to treat it as such.

Instead, you should probably have just one Update() function outside this hierarchy where the queue is polled, and pass the individual events to the derived classes to attempt to handle them (eg. via a virtual bool Derived::HandleEvent()).

Share this post


Link to post
Share on other sites
Thanks for the reply! That was my last resort, as I wanted the final engine to be totally abstracted from event handling, but I guess I can't have everything :P

Thanks much!

Share this post


Link to post
Share on other sites
Quote:
Original post by goulash32
Thanks for the reply! That was my last resort, as I wanted the final engine to be totally abstracted from event handling, but I guess I can't have everything :P

Thanks much!


How about SDL_PeepEvents()? I believe there may even be a function/macro called SDL_QuitRequested() too...

Share this post


Link to post
Share on other sites
Quote:
Original post by goulash32
Thanks for the reply! That was my last resort, as I wanted the final engine to be totally abstracted from event handling, but I guess I can't have everything :P

Thanks much!


How would your engine be totally abstracted from event handling if every single system has to directly access the event queue? That's even worse in my opinion. There's no way around this - it's a shared resource, and you need access to it. You just have to decide how to use it.

Share this post


Link to post
Share on other sites
I plan to make a handler class for every kind of access to the event queue the engine requires.

I currently have a class called input_control, which owns a class called mouse_control and one called keyboard_control. I then create a singleton input_control, so any other class in the game engine can test the state of the bits i have already handled.
The input_control class looks through the entire event queue and passes the data to the correct classes.
The keyboard_control class can tell me what the state of the keyboard is at any given time.
The mouse control tells me how far the pointer has moved in the last frame, and what the key states are.
Would you like a copy of these classes? They have served me well.
[edit: sorry, too many typos]

Share this post


Link to post
Share on other sites
Quote:
Original post by speciesUnknown
I plan to make a handler class for every kind of access to the event queue the engine requires.

I currently have a class called input_control, which owns a class called mouse_control and one called keyboard_control. I then create a singleton input_control, so any other class in the game engine can test the state of the bits i have already handled.
The input_control class looks through the entire event queue and passes the data to the correct classes.
The keyboard_control class can tell me what the state of the keyboard is at any given time.
The mouse control tells me how far the pointer has moved in the last frame, and what the key states are.
Would you like a copy of these classes? They have served me well.
[edit: sorry, too many typos]


I'd like that very much, thanks.

And Kylotan, I meant abstracted from SDL event handling, not event handling in general. I want the elements of SDL to be totally transparent to the end user of the engine. For example, boolean functions like KeyHit() that check SDL's event queue behind the scenes, and then simply return a true or false for that key.

Share this post


Link to post
Share on other sites
Quote:

I meant abstracted from SDL event handling, not event handling in general. I want the elements of SDL to be totally transparent to the end user of the engine. For example, boolean functions like KeyHit() that check SDL's event queue behind the scenes, and then simply return a true or false for that key.


these classed do exactly that.
here are the six files that you are interested in.

These have been refined my myself for a year, and have survived several game engine re-designs intact.

how to use them:

declare an input_control or, better, use the function get_input_control() which will return an pointer to a static variable it owns, my favourite implementation of a "singleton".

at the beginning of each frame, call input_control::handle_input()
this will return a 1 if you should quit. Ive programmed it to do this when the user presses ESC.

to access keyboard states, call input_control->keyboard->get_key(int). pass it the sdl key name, e.g. "SDLK_w" for the w key.

to access the mouse states:
use input_control->mouse->get_last_movement(float &x, float &y). the floats x and y are set to the distance the pointer has moved since the last time youy called input_control->handle_input()

use input_control->mouse->get_button(int). the integer you set is the mouse button according to SDL.


i believe that simplicity is best, so these are very simple, and not teh fully featured classes you would find in a commercial game engine. IM jsut a hobbiest.
If you make any improvements please share them with me.

gavin_AT_alberonsystems_DOT_co_DOT_uk
replace _AT_ with the at shymbol and _DOT_ with the dot symbol to get my email address. (I hope I wont get spammed if i do this in a forum, since spambots regularly search forums);
It would be great if somebody [cough] who likes this class could write a similar component to handle OS events.

input_control.h:


/*
* input_control.h
* fish tank
*
* Created by gavin on 06/04/2007.
* Copyright 2007 __MyCompanyName__. All rights reserved.
*
*/


class input_control;
#ifndef class_input_control_h
#define class_input_control_h 1
#include "keyboard_control.h"
#include "mouse_control.h"
class input_control
{
private:

public:
keyboard_control * keyboard;
mouse_control * mouse;
input_control();
~input_control();
int handle_keys(unsigned int keysym,unsigned char key_state);
int handle_input();
int update();

};


#endif

#define INPUT_OBJECT get_input_control();
input_control * get_input_control();





input_control.cpp:

/*
* input_control.cpp
* fish tank
*
* Created by gavin on 06/04/2007.
* Copyright 2007 __MyCompanyName__. All rights reserved.
*
*/


#include "input_control.h"

input_control::input_control()
{
keyboard = new keyboard_control();
mouse = new mouse_control();
mouse->new_frame();
};

input_control::~input_control()
{
delete keyboard;
delete mouse;
};

int input_control::handle_keys(unsigned int keysym,unsigned char key_state)
//returns 1 if the key pressed was the escape key, returns 0 otherwise
{
keyboard->set_key(keysym,key_state);
//special cases requiring immediate action:
switch(keysym)
{
case SDLK_ESCAPE:
return 1;
break;
}
return 0;
};

int input_control::handle_input()
//returns 1 if an exit is necessary, and 0 otherwise
//current duties: keyboard, OS events
//calls individual functions to handle events from each source.
{
// Our SDL event placeholder.
mouse->new_frame();
SDL_Event event;
while( SDL_PollEvent( &event ) )
{
switch( event.type )
{
case SDL_QUIT:
return 1;
break;

case SDL_KEYDOWN:
return handle_keys(event.key.keysym.sym,1);
break;

case SDL_KEYUP:
return handle_keys(event.key.keysym.sym,0);
break;

case SDL_MOUSEMOTION:
mouse->set_last_movement(event.motion.xrel,event.motion.yrel);
break;

case SDL_MOUSEBUTTONDOWN:
mouse->set_button(event.button.button,1);
break;

case SDL_MOUSEBUTTONUP:
mouse->set_button(event.button.button,0);
break;
}
}
return 0;
}

int input_control::update()
{
mouse->new_frame();

};

input_control * get_input_control()
{
static input_control * input = new input_control();
return input;
};





keyboard_control.h:

/*
* keyboard_control.h
* Project
*
* Created by gavin burton on 29/03/2006.
* Copyright 2006 __MyCompanyName__. All rights reserved.
*
*/


#ifndef _KEYBOARD_CONTROL_
#define _KEYBOARD_CONTROL_

class keyboard_control
{
private:
unsigned char key_state[SDLK_LAST];
//1 would be down, 0 would be up
keyboard_control * next;

public:
keyboard_control::keyboard_control();
void keyboard_control::set_key(unsigned char key_code,unsigned char new_state);
unsigned char keyboard_control::get_key(unsigned char key_code);
};

#endif




keyboard_control.cpp:


/*
* keyboard_control.cpp
* Project
*
* Created by gavin burton on 29/03/2006.
* Copyright 2006 __MyCompanyName__. All rights reserved.
*
*/


#include "keyboard_control.h"

keyboard_control::keyboard_control()
{
int index = 0;
for(index = 0; index <= SDLK_LAST; index++)
key_state[index]=(char)0;
next = NULL;
};

void keyboard_control::set_key(unsigned char key_code,unsigned char new_state)
{
key_state[key_code]=new_state;
}

unsigned char keyboard_control::get_key(unsigned char key_code)
{
return key_state[key_code];
}





mouse_control.h:

/*
* mouse_control.h
* Project
*
* Created by gavin burton on 15/05/2006.
* Copyright 2006 __MyCompanyName__. All rights reserved.
*
*/

#ifndef _MOUSE_CONTROL_CLASS_
#define _MOUSE_CONTROL_CLASS_ 1
#include <cmath>
class mouse_control {
private:
int buttons[10];
//up to 10 mouse buttons can be controlled this is obviously more
//than is needed but you can never be certain what kind of hardware gamers are using
float lastx,lasty;
int xpos,ypos;
//current x and y positions
float sensitivity;

mouse_control * next;

public:
mouse_control();

void set_sensitivity(float s){sensitivity = s;}

float get_sensitivity(){return sensitivity;}

int get_button(int b){return buttons;}

void set_button(int b,int s){buttons=s;}

int set_position(int x, int y);

void get_position(int &x, int &y);

void get_last_movement(float &x, float &y);

void set_last_movement(float x, float y);

void new_frame();//mouse forgets movements in the last frame
};

#endif






mouse_control.cpp:

/*
* mouse_control.cpp
* Project
*
* Created by gavin burton on 15/05/2006.
* Copyright 2006 __MyCompanyName__. All rights reserved.
*
*/


#include "mouse_control.h"
#ifndef DEFAULT_MOUSE_SPEED
#define DEFAULT_MOUSE_SPEED 5
#endif

mouse_control::mouse_control()
{
int index;
for(index=0; index < 3; index++)
buttons[index]=false;
lastx = 0;
lasty = 0;
sensitivity = DEFAULT_MOUSE_SPEED;
next = NULL;

};

int mouse_control::set_position(int x, int y)
{
xpos = x;
ypos = y;

return true;
};

void mouse_control::get_position(int &x, int &y)
{
x = xpos;
y = ypos;
return;
};

void mouse_control::set_last_movement(float x, float y)
{
lastx += x / 300000000 * sensitivity;
lasty += y / 300000000 * sensitivity;
return;
};

void mouse_control::get_last_movement(float &x, float &y)
{
x = lastx * sensitivity*300000;
y = lasty * sensitivity*300000;

};

void mouse_control::new_frame()
{
lastx = 0;
lasty = 0;
};





[Edited by - speciesUnknown on April 20, 2007 6:26:03 PM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!