Event Receiver for a Game/Engine. (Mouse, Keys, & Joysti

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Event Receiver for a Game/Engine. (Mouse, Keys, & Joysti

Post by Ulf »

I want to make an event receiver for a game or game engine taking care of mouse, keyboard and joystick events.
I want to develop it into something useful for anyone wanting to create games.
I also want it to be bug free and unproblematic as I develop it.
So I made it very simple to start with, even though it's probably not the way most game makers would want it to run.

So,
I'd really appreciate all constructive criticism and also ideas on modifying or expanding it. (I'll put the code below)

I want to make a note:
For a game/game engine you obviously need game specific event handlers, since different games will do different things.
So in it's current simple state, the OnEvent() function will call the appropriate game specific event handlers to handle the events.
OnEvent() basically gets the event, then selects which game specific handler to call and calls it passing some or all of the event data as parameter/s.
I also keep track of KeyDown.

and raise my 1st question
Should I keep track of the state of the keyboard keys, but only call the game specific HandleKeys() function once per game loop?
What is appropriate for a game? and what are the reasons?

I know that joystick events only occur once per loop anyway.

And I'm pretty sure that I should leave Mouse events as instant rather than maintaining a state of buttons and then calling a game specific mouse handler once per game cycle. Because we could miss mouse clicks if the button gets released before the handler is called during each loop. But, at the same time, should I keep track of the state of the mouse buttons like I do with the keyboard?

(I hope I'm not being too confusing) :shock:

A typical game loop may look something like this:

Code: Select all

 
while (device->run())
{
    HandleKeys();
    HandleJoystick();

    GameCycle();
    GamePaint();
}


Or it can be done directly as in my code.

Any opinions or advice, please explain your reasons, especially if you have experience making or attempting to make games.

I'll post the code next...
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Header file

Post by Ulf »

Code: Select all

#ifndef __C_IRR_C_GAME_EVENT_RECEIVER_H_INCLUDED__
#define __C_IRR_C_GAME_EVENT_RECEIVER_H_INCLUDED__

namespace irr
{
	//! Enumeration for all mouse buttons
	enum EMOUSE_BUTTON
	{
		//! The number of mouse buttons.
		MOUSE_BUTTONS = 3,

		//! Left mouse button.
		LEFT_BUTTON = 0,

		//! Middle mouse button.
		MIDDLE_BUTTON,

		//! Right mouse button.
		RIGHT_BUTTON
	};

	//! Struct to keep the actual event PLUS the state of all keys held down or up at any instant.
	struct SKeyEventState
	{
	public:
		SKeyEventState()
		{
			for (u8 i=0; i < KEY_KEY_CODES_COUNT; ++i)
			{
				KeyIsDown[i] = 0;
			}
		}

		SEvent	KeyEvent;
		u8		KeyIsDown[KEY_KEY_CODES_COUNT];
	};

/*
To receive events like mouse, keyboard and joystick input, we need an object which
is derived from the IEventReceiver object.
We must override IEventReceiver::OnEvent();
This method will be called by the engine once when an event happens.
For Key input we really want to know whether a key is being held down, so 
we will remember the current state of each key.
For Mouse input we made an enum to describe each of the three buttons (EMOUSE_BUTTON).
We use this in the OnEvent() method when we call the game event handler as below:
case EMIE_LMOUSE_PRESSED_DOWN
	MouseButtonDown(event.X, event.Y, LEFT_BUTTON);
For Joystick input we simply temporarily keep each Joystick event as it happens,
and we pass it straight to the game specific joystick handler.
*/

class CGameEventReceiver : public IEventReceiver
{
public:
	//! Constructor
	CGameEventReceiver() {};

	//! Destructor
	~CGameEventReceiver() {};

protected:
	//! This is the one method that we have to implement 
	bool OnEvent(const SEvent& event);
	
	//! We use this struct to store the key event PLUS the current state of each key
	SKeyEventState			m_KeyState;

	//! We use this struct to store the last joystick state received in OnEvent
	/** Not really needed at the moment	*/
	SEvent::SJoystickEvent	m_JoystickState;

}; // end class BK_EventReceiver

} // end namespace irr

#endif // __C_IRR_C_GAME_EVENT_RECEIVER_H_INCLUDED__
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Source file

Post by Ulf »

Code: Select all

// Game specific EVENT handlers
extern void	HandleKeys(const irr::SKeyEventState& keyState);
extern void	MouseButtonDown(irr::s32 x, irr::s32 y, irr::EMOUSE_BUTTON button);
extern void	MouseButtonUp(irr::s32 x, irr::s32 y, irr::EMOUSE_BUTTON button);
extern void	MouseMove(irr::s32 x, irr::s32 y);
extern void	MouseWheel(irr::s32 x, irr::s32 y, irr::f32 wheel);
extern void	HandleJoystick(irr::SEvent::SJoystickEvent joystickState);

namespace irr
{

//! This is the one method that we have to implement
bool CGameEventReceiver::OnEvent(const SEvent& event)
{
	//! Mouse Events
	if (event.EventType == EET_MOUSE_INPUT_EVENT)
	{
		switch(event.MouseInput.Event)
		{
			// For each different case of mouse event, we call the appropriate 
			// game specific event handler, passing it the necessary parameters.

			//! Left mouse button was pressed down.
			case EMIE_LMOUSE_PRESSED_DOWN:
				MouseButtonDown(event.MouseInput.X, event.MouseInput.Y, LEFT_BUTTON);
				break;

			//! Right mouse button was pressed down.
			case EMIE_RMOUSE_PRESSED_DOWN:
				MouseButtonDown(event.MouseInput.X, event.MouseInput.Y, RIGHT_BUTTON);
				break;

			//! Middle mouse button was pressed down.
			case EMIE_MMOUSE_PRESSED_DOWN:
				MouseButtonDown(event.MouseInput.X, event.MouseInput.Y, MIDDLE_BUTTON);
				break;

			//! Left mouse button was left up.
			case EMIE_LMOUSE_LEFT_UP:
				MouseButtonUp(event.MouseInput.X, event.MouseInput.Y, LEFT_BUTTON);
				break;

			//! Right mouse button was left up.
			case EMIE_RMOUSE_LEFT_UP:
				MouseButtonUp(event.MouseInput.X, event.MouseInput.Y, RIGHT_BUTTON);
				break;

			//! Middle mouse button was left up.
			case EMIE_MMOUSE_LEFT_UP:
				MouseButtonUp(event.MouseInput.X, event.MouseInput.Y, MIDDLE_BUTTON);
				break;

			//! The mouse cursor changed its position.
			case EMIE_MOUSE_MOVED:
				MouseMove(event.MouseInput.X, event.MouseInput.Y);
				break;

			//! The mouse wheel was moved.
			case EMIE_MOUSE_WHEEL:
				MouseWheel(event.MouseInput.X, event.MouseInput.Y, event.MouseInput.Wheel);
				break;

			default: // return false
				return false;
		} //! end switch(event.MouseInput.Event)

		return true;

	} // end (event.EventType == EET_MOUSE_INPUT_EVENT)

	//! Keyboard Events
	if (event.EventType == EET_KEY_INPUT_EVENT)
	{
		// For key events we use the struct m_KeyState to keep track of the state 
		// of all keys, and to hold the irrlicht key event data. 
		// We call the game key event handler, passing it m_KeyState.

		//! Remember whether each key is down or up.
		m_KeyState.KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
		
		//! Keep the actual event data to pass to the game event handler.
		m_KeyState.KeyEvent = event;

		//! Call game specific event handler with the data in m_KeyState.
		HandleKeys(m_KeyState);

		return true;
	} // end (event.EventType == EET_KEY_INPUT_EVENT)

	//! Joystick Events
	if (event.EventType == EET_JOYSTICK_INPUT_EVENT)
	{
		// The state of each connected joystick is sent to us once every run() 
		// of the Irrlicht device.  Store the state of the joystick, and call 
		// the game specific joystick handler, passing it the joystick event.
		m_JoystickState = event.JoystickEvent;

		//! Call game specific event handler with irr::SEvent::JoystickEvent parameter.
		HandleJoystick(m_JoystickState);

		return true;
	}

	return false;

} // end OnEvent

} // end namespace irr
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Post by Seven »

I use a very similar style, deriving the levels and event he game objects from it. by deriving the gameobjects, they can receive input also.

http://irrlicht.sourceforge.net/phpBB2/ ... highlight=
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Future modifications

Post by Ulf »

Ok.

I will get back with some modifications soon. Maybe a week or 2.
I am working on mouse double click and extra buttons.

In this event handler I am making, I think I will incorporate a button pressed functionality as well. I've seen a few examples with that, including yours Seven.

But I have a couple of ideas how to do it differently. I have to think about it a bit more, and implement it of course!

Also,
I was thinking, about repeated key presses.

Would it be useful to have 2 separate events for keyPressed and keyRepeated?

If you look at my SKeyEventState struct, it has KeyIsDown[].

Would it be useful to have another array KeyIsRepeated[] ? ?

Or could use the one array and have DOWN and REPEATED value?

Or could build into irrlicht

Code: Select all

bool PressedDown
variable, but the variable would have to change type.

It's probably wrong to build it into irrlicht as people may want to disable repeated keys?? Not sure.

Any ideas?
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
Post Reply