Sign in to follow this  
Jookia

State Event design.

Recommended Posts

Okay, I have a class-based state machine, each state is a child class of CState and gets events. Right now I have events like keyboard input and functions like CState::onHidden(bool hidden). My question is this: Would it be better to remove onHidden and replace with an event or keep adding more onX functions? Also, on another topic, how do I hide the GNOME panels?

Share this post


Link to post
Share on other sites
Quote:
Original post by JookiaRight now I have events like keyboard input and functions like CState::onHidden(bool hidden). My question is this: Would it be better to remove onHidden and replace with an event or keep adding more onX functions?


You mean replace with a single event function taking an event object as a parameter? It depends on a lot of other factors, like how many events you have now, how many you're likely to have in the future, how the events are produced, and how they are meant to be be used. code pls?

Share this post


Link to post
Share on other sites
I prefer the onEvent(GenericEvent) interface mentioned above, because it keeps the interface clean. I am also fine with trading speed and type safety for flexibility and extensibility here (my events have a string type, and the dispatcher has no idea about the event type except for registering interest of listeners in a specific event type, so it can handle any event that might ever be created without any code rewrite), but this is not necessarily the prevalent opinion.

This kind of system also has the advantage of being easier on logging - just dump all events to a log file in that class and you've got yourself a cheap accounting trail. You can also inject fake events for testing purposes.

Share this post


Link to post
Share on other sites
I plan to have key press events along with object and world events like onObjectTouch and all that crap. Is it better to have onEvent and have all those as events or scrap the onEvent and have those as functions?

If I do the onEvent method, how am I going to have generic events that need special params like onObjectTouch(player, normal) and onStateHidden(hidden)

Share this post


Link to post
Share on other sites
Quote:
Original post by Jookia
If I do the onEvent method, how am I going to have generic events that need special params like onObjectTouch(player, normal) and onStateHidden(hidden)


The way I solved this was to add an argument map to the message class. In pseudocode:


class Event:
string type
map<string, object> arguments



I'm sure it's possible to cook up something similar with the collection classes in C++. Another possibility is subclassing Event and downcasting in the onEvent() handler based on event type. Strictly speaking that's not very OOP-like, though.

Share this post


Link to post
Share on other sites
But that'd require more memory wouldn't it? Why not an enum? Or some crap? I don't know what I'm talking about, could you spoon feed me an example event + how to send/recieve it?

Share this post


Link to post
Share on other sites
Quote:
Original post by Jookia
But that'd require more memory wouldn't it? Why not an enum? Or some crap?


Those are speed vs flexibility tradeoffs that you have to decide for yourself. Both kinds of systems are being used out there.

Share this post


Link to post
Share on other sites
I still don't quite get what you're asking. You want a way to make a flexible event class that can be used to pass a wide variety of information to an event receiver, right? lightbringer already gave you a template for that.

As for casting, using RTTI (runtime type information) is not exactly cheap performance-wise. And an enum has a fixed number of elements in it, which doesn't help with extensibility.

Share this post


Link to post
Share on other sites
Here's the thing: I'm torn on what to do.

My events range from a bool being changed to a player being hit by a projectile with X damage.

The problem is, isn't an entire derived class from the event class just to signal that a bool is changed a bit.. overkill?

All I want is a unified way of sending messages and bits of data. I don't know what to do.

Should I just use functions like onX() and forget onEvent all together? Wouldn't that build up code? Ugh.

Maybe I should design a system then try and implement it based on the design, not the other way around.

Share this post


Link to post
Share on other sites
Quote:
Original post by Jookia
The problem is, isn't an entire derived class from the event class just to signal that a bool is changed a bit.. overkill?

You probably don't want to use events for regular processing. Use events for situations such as taking damage or colliding with something. Talking about event systems, I found this presentation to be quite useful, although it's not very detailed. Make sure to view it as outline because there are also extensive notes below the slides.

Quote:
Original post by Jookia
All I want is a unified way of sending messages and bits of data. I don't know what to do.

Should I just use functions like onX() and forget onEvent all together? Wouldn't that build up code? Ugh.

You can also do this, and then implement an event system once you actually feel that you need one. There is such a thing as over-engineering, or seeing nails everywhere once you find a hammer.

Quote:
Original post by Jookia
Maybe I should design a system then try and implement it based on the design, not the other way around.

That's always a good idea!

Share this post


Link to post
Share on other sites
I'd say be prepared to do both. If there are a few "events" that make more sense as functions, you can have those alongside onEvent. As you dig in to actually implementing it, you'll start to feel the factors involved, and it will be easier to decide what you should do with each new bit of info that needs to go to the class. Think of which events/functions it makes sense for every class to have.

Share this post


Link to post
Share on other sites
I've decided to settle for a basic event(string name, void* object) system (object can be 0, so I can send an object or not). I'll probably add type_info stuff one day, but this fits the bill for big events and just simple onX events.

Share this post


Link to post
Share on other sites
Okay, I made a basic implementation of it.

		case WM_KEYDOWN:
{
SEventKeyboard data;
data.key = wideParam;
data.pressed = true;

stateLayer->event("keyboard", (void*)&data);
return 0;
}


void CMainMenuState::onEvent(char* eventName, void* object)
{
IOLayer->log("%s_%i", eventName, eventName == "keyboard");


The output is:

keyboard_0

I don't understand.

Share this post


Link to post
Share on other sites
in the expression 'eventName == "keyboard"'
"char *eventName" points to memory, where any string or other bytes could be.
"keyboard" boils down to another pointer in this expression, which points to bytes of memory with the character values needed to spell keyboard.

These 2 memory locations are not the same, regardless of whether the actual data in these 2 locations match or not, which evaluates to false, which rings up as "0" in your log statement.

What you want, is to either use stricmp(eventName, "keyboard") or much more preferably, use a real string class, such as std::string, which implements comparison on strings internally.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this