views:

67

answers:

3

I'm working on developing a fairly robust 2D game engine as a base that other games can be built off of as a for-fun project (I know theres already things that do this, but that's no fun).

I'm trying to figure out a good way to do message-passing between classes within the engine. At first I was thinking about using a heirarchy of exceptions and throwing them whenever something required it. But as I was developing that way, I realized that there was quite a large number of exceptions being thrown, as they were being used for fairly common things (part of subroutines that handle pathfinding and unit locating and things that need to test the state of the game board alot). The exceptions were being used for things like the pathfinding came across a unit in the way and needed to go around it, it would throw a TileOccupied exception and the pathfinding could gracefully handle that and continue. As can be expected, this created a lot of exceptions.

The internet has told me that exceptions are expensive due to all the run-time processing they need to do. But they handle what I need perfectly, which is being able to propogate a message back to the caller even through branching subroutines to indicate when something has happened or something was not as expected.

Is there any clean/efficient way to do this in c++? Or am I structuring things very wrongly if I am using this type of notification? I'm still learning, so any suggestions would be greatly appreciated (and I'm willing to read / learn any references you can throw my way)

Edit I'm trying to do this in standard c++ btw. I am writing it on linux, and want it to compile and be runnable platform-independent. I'm currently using Boost in it.

A: 

Is there any reason you haven't used an event queue and/or observer setup?

Noah Roberts
The primary reason would be that I have no idea what those are. I shall start looking
Veaviticus
+2  A: 

Although this requires explicit registration, this sounds like you want callbacks (eased by e.g. Boost.Function) or signals (like Boost.Signals/Signals2).

Georg Fritzsche
Veaviticus
@vea: If you care about performance you should measure it for your use-case, also note that these measurements are from 2004. Personally i'd stay with Boost if you are already using components from it unless there really is a performance problem in that part.
Georg Fritzsche
@George I know its a bit off topic and down the road a ways, but do you have any suggestions on how to do timings like that?
Veaviticus
@vea: For just the direct comparison measure the time needed for `N` calls, divide the time-diff by `N`. Though thats rarely useful, only measuring hotspots of a complete application is really helpful - search for "profiler"s here. If it only takes up a small overall amount of processing time, readability/maintainability are more important than speed.
Georg Fritzsche
A: 

Exceptions are the wrong way of doing this. Usual suggestion would be direct events/listeners design, but that quickly gets out of hand within any non-trivial system. I'd point you to a whiteboard design for loose communications.

Nikolai N Fetissov