PDA

View Full Version : Message System, C++


Ed Mack
09-30-2004, 10:03 AM
I've been working away at a simple game framework, and came into a problem/design requirement that I'm sure most of you have faced plenty of times, needing a robust messageing system between objects.

For Keyboard event notification, settings update propagation and so on

I've thought lots. but havn't really came up with a nice OOP way to work it. Please hit some ideas at me with a cluebat :)

NomadRock
09-30-2004, 10:34 AM
Setup one object that controls the messages. The most generic way is like the windows message queue. You can probably find a more specific way of doing this that works better when you restrict the domain to your game framework.

When objects want to find out if the keyboard has been pressed they ask that object. When objects want to simulate a keyboard event they tell that object.

Ed Mack
09-30-2004, 12:11 PM
The most generic way is like the windows message queue.
12184


Any more info? I've never programmed on Win32.

Michael
09-30-2004, 02:24 PM
Basically a queue<Message> ;)

Look for PostMessage, GetMessage, PeekMessage, MSG in the online MSDN.

Ed Mack
09-30-2004, 10:40 PM
Okay, thanks. I'm going to look at more event based models however.

Thanks :)

anubis
10-01-2004, 05:32 AM
When objects want to find out if the keyboard has been pressed they ask that object. When objects want to simulate a keyboard event they tell that object.

i find event polling unelegant somehow. objects shouldn't have to know where the events come from. they should just have to specify which events they want to capture (keyboard or mouse for example) by deriving from some receiver class or provide a delegate for that (depending on the language you use) and receive the events once they happen

Decibit
10-01-2004, 06:06 AM
That is the messaging system from my project. It is not necessary good for everything, I just wanted to make my input platform-independent. The idea is to use Context-Receiver scheme.


struct Message
{
...
};

class Receiver
{
virtual void onKeyDown(unsigned short key, unsigned rep)=0;
virtual void onKeyUp(unsigned short key, unsigned rep)=0;
virtual void onMouseDown(int x, int y, unsigned button)=0;
...
};

class Context
{
protected:
Receiver* m_pTargetReceiver;
public:
virtual ~Context()=0;
virtual void update()=0;
virtual Receiver* setTargetReceiver(Receiver* tr)=0;
virtual void sendMessage(Message mes)=0;
...
};


The system proved to be good for aboth ssinchronous and synchronous events handling.

The framework installs Context.
User adds custom Receiver to Context.
The system scans hardware when updates and sends corresponding messages to the Receiver.
User can send own messages through sendMessage function.
Context-Receiver pairs can be written for most subsystems. The code above is just the example of doing it for input.

Maybe that helps.

bladder
10-01-2004, 07:19 AM
here's something really quick and dirty:



class Event
{
union
{
struct
{
char ScanCode;
};

struct
{
int MouseButton;
};
};
};

class Receiver
{
virtual HandleIOEvent( Event* pe ) = 0;
};

class MouseReceiver : public Receiver
{
virtual OnWheelRotate( int amount ) = 0;
virtual OnLeftButtonDown() = 0;
virtual OnRightButtonDown() = 0;
};

class KeyboardReceiver : public Receiver
{
virtual OnKeyUp( char k ) = 0;
virtual OnKeyDown( char k ) = 0;
};

class EventManager
{
static vector<KeyboardReceivers> m_KRs;
static vector<MouseReceivers> m_MRs;
static RegisterKeyboardReceiver( KeyboardReceiver* pkr );
static RegisterMouseReceiver( MouseReceiver* pkr );
static HandleIO()
{
// get keyboard and mouse info, iterate through all keyboard
// receivers and mouse receivers and handle events
for( each keyboard/mouse receiver handle IO depending on type )
{
switch( IOType )
{
case KeyUp:
// Go through keyboards and call the OnKeyUp function
case KeyDown:
// Go through keyboards and call the OnKeyDown function
// etc...
}
}
};


You basically have your IO module right. And your IO manager checks if any input has taken place, then tell the objects that can handle any type of input to handle it. This way, objects dont have to constantly scan for input. When input happens, they'll be told it happened and can do what they want. Any object that wants to handle the keyboard/mouse will have to register itself with the manager. ie:


class Player : public KeyboardReceiver
{
Player()
{
EventManager::RegisterKeyboardReceiver( this );
}
OnKeyUp( char k )
{
// do whatever
}
};

Michael
10-01-2004, 08:19 AM
http://sigslot.sourceforge.net/

http://www.boost.org/doc/html/signals.html

Ed Mack
10-01-2004, 08:54 AM
Wow! Thank you very much.

Boost is interesting, however I don't like having so much abstracted from me, when I can write more specific code to do the same task.

Decibit, your approach was interesting too, and I think I'll go for an approach similar to Bladder's subscribe/manager pattern.

Thank you, I'm all sorted now :)

NomadRock
10-01-2004, 11:58 AM
Good, glad you found your way.

SnprBoB86
10-01-2004, 12:03 PM
never underestimate the awesomeness of boost...

grusifix
11-20-2004, 04:32 AM
@bladder: Looks lot a like Observer-pattern (?)

Madgibs
03-03-2005, 08:42 AM
You might also consider the Windows GetAsyncKeyState() function to test for whether or not a key is down.

Ed Mack
03-03-2005, 09:14 AM
It's Linux ATM, so I wanted to write it OS agnostic. I went for the Publisher & Subcriber / Observer pattern, and it's worked very nicely so far. Thanks Bladder and rest :)