Component Based Objects?

Anything and everything that's related to OGRE or the wider graphics field that doesn't fit into the other forums.
mirlix
Goblin
Posts: 225
Joined: Mon May 01, 2006 12:03 am
Location: Germany
x 5

Re: Component Based Objects?

Post by mirlix »

I use a std:map with std:string as key and boost any as value. Its the most dynamic way but I dont know if it is fast enough when using a lot of message, for my demo game its fast enough, thats all I can say.
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Re: Component Based Objects?

Post by KungFooMasta »

Do you queue your messages, or are they sent and processed immediately? Or do you allow for both queued and immediate processing? What does your message handler function look like? I'm guessing you have an abstract class, ie MessageHandler, and only MessageHandlers are sent Messages? (or how do you send and process messages?)
Creator of QuickGUI!
mirlix
Goblin
Posts: 225
Joined: Mon May 01, 2006 12:03 am
Location: Germany
x 5

Re: Component Based Objects?

Post by mirlix »

I have both, message in one thread are processed immediately interthread message are queued. Also I have messagelists where each message handler can subscribe to recieve messages.
I have a simple virtual function for all components

Code: Select all

virtual void call(pMessage mes) = 0;
And the messageinterface looks like this.

Code: Select all

class IMessage
	{
	public:
		

		
		virtual ~IMessage() {};///<destructor
		virtual HINGE::String getType() = 0;///<returns messagetype
		virtual HINGE::String getGroup() = 0;///<returns group

		virtual void setData(boost::any data,HINGE::String identifier) = 0;///< Saves the data using the identifier
		virtual boost::any getData(HINGE::String identifier) = 0;///< Returns the data associtated with the identifier

	};
Group is the threading group and type is the message type. While processing a message I do a lookup in a hashmap for the type string and get a functionpointer who processes the message.
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Re: Component Based Objects?

Post by KungFooMasta »

If you wanted to allow classes that aren't components to receive messages you'd have to come up with a different design right? Also, how do you route messages? If component A wants to send a message to component B, A has to get access to B, then call B->call(message); ? Or do you have some kind of message manager that will take messages and forward them along to the correct class?

Also, immediate processing won't work well for scenarios involving GO destruction. For example, GO1 sends a message to GO2, but in its handler it wants to destroy GO1. It can't immediately destroy GO1, because the execution pointer would be trying to execute the code of GO1 (when the call function returns) which is now destroyed. Do you have scenarios where messages result in cleaning up/destroying other instances?

Lastly, when queuing up messages, its recommended that you make deep copies, so the data won't go out of scope. I think the Any class just invokes the copy constructor for its data, right? Does this work for std lists/vector/etc?
Creator of QuickGUI!
mirlix
Goblin
Posts: 225
Joined: Mon May 01, 2006 12:03 am
Location: Germany
x 5

Re: Component Based Objects?

Post by mirlix »

KungFooMasta wrote:If you wanted to allow classes that aren't components to receive messages you'd have to come up with a different design right?
Yes, but extracting a MessageHandler interface wouldnt be that difficutl.
KungFooMasta wrote: Also, how do you route messages? If component A wants to send a message to component B, A has to get access to B, then call B->call(message); ? Or do you have some kind of message manager that will take messages and forward them along to the correct class?
I use both, direkt messaging and using a manager to send them using messagelists , which can have only one subscriber which would be like a look up table.
KungFooMasta wrote: Also, immediate processing won't work well for scenarios involving GO destruction. For example, GO1 sends a message to GO2, but in its handler it wants to destroy GO1. It can't immediately destroy GO1, because the execution pointer would be trying to execute the code of GO1 (when the call function returns) which is now destroyed. Do you have scenarios where messages result in cleaning up/destroying other instances?
I use delayes deletin GOs. I have a list with GOs to be destroyed and at the beginning of each frame I destroy all GOs in this list[/quote]
KungFooMasta wrote: Lastly, when queuing up messages, its recommended that you make deep copies, so the data won't go out of scope. I think the Any class just invokes the copy constructor for its data, right? Does this work for std lists/vector/etc?
I havent had problems with this yet, but I can assure that this wont happend. And I havent tested with that in mind, but up until now I didnt have problems with it. EDIT: I just tested it with std::list and it seems to me that any creates deepcopys or rather I think it calls the copy constructor of std::list which in turn calls the copy constructor of the class inside the list, which should make it possible to create a deepcopy if needed.
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Re: Component Based Objects?

Post by KungFooMasta »

mirlix thanks for the information. :)

How do you handle the case where somebody subscribes for messages and later gets destroyed?
Creator of QuickGUI!
mirlix
Goblin
Posts: 225
Joined: Mon May 01, 2006 12:03 am
Location: Germany
x 5

Re: Component Based Objects?

Post by mirlix »

Right now Im simply hoping that he will unsubscribe before getting destroyed, but I have encapsulated my message function so I can add a check like using weakpointer, before calling the functionpointer.
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Re: Component Based Objects?

Post by KungFooMasta »

Hey Mirlix, so I have my system set up, its very similar to yours. In my Message class I have:

string messageType
string messageSource
list<Any> values

Since I'm using a list of Any values, the message class can store any kind of data it wants. However the data will be ordered. I guess as an alternative I could have each specific message type have its own struct of data, and have just one Any value to represent the struct. Is this what you do?
Creator of QuickGUI!
mirlix
Goblin
Posts: 225
Joined: Mon May 01, 2006 12:03 am
Location: Germany
x 5

Re: Component Based Objects?

Post by mirlix »

I also have a generic message class.I use any and a hashmap, so I can access message date by name.
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Re: Component Based Objects?

Post by KungFooMasta »

Ah I think you mentioned that before, slipped my mind. Thats a much better idea than using a list.

In your setup do you have the ability to send messages across the network? I have a serialization system setup but its a little more tedious to use than I want, so I'm trying to think of any better designs. Currently I'm thinking of having special data types, for example 'SerializableInt' instead of 'int', or 'SerializableFloat' instead of 'float'. Basically I need data that can be written to string and created from string. I'm able to convert data to/from string now, but I have to very explicitly outline how each class is written to string, and read in from string.
Creator of QuickGUI!
mirlix
Goblin
Posts: 225
Joined: Mon May 01, 2006 12:03 am
Location: Germany
x 5

Re: Component Based Objects?

Post by mirlix »

Right now I have a SerializationManager which stores instances of SerializationObjects which describe how to get variable type into a string and visa versa, its not really practical so Im thinking about switching to boost::lexical_cast, but I havnt had time to check this probably. Also I havent yet tried to convert a complete message into a string, its on my todo list, but I havnt done it yet. I think it should be easy because boost::any can return you the type its contain and with this using lexical cast or an own class should be straight forward.
dzeligman
Gnoblar
Posts: 11
Joined: Tue Oct 28, 2008 9:59 pm

Re: Component Based Objects?

Post by dzeligman »

One large issue i've come up with is how to design certain aspects of the game.

Currently I have functional physics, sound, light, camera, animation, mesh and rendering oriented components.

now for specific game logic I'm having a brain fart.

How would one handle trigger bounding boxes/areas or UI/stat related event/counters and that sort of thing.

I have an event system that allows components to send events to the other components of the parent GameObject or to all other subsystems with the world as a target or to another GameEntity alltogher.
reptor
Ogre Magi
Posts: 1120
Joined: Wed Nov 15, 2006 7:41 pm
Location: Finland
x 5

Re: Component Based Objects?

Post by reptor »

mirlix wrote:I use a std:map with std:string as key and boost any as value. Its the most dynamic way but I dont know if it is fast enough when using a lot of message, for my demo game its fast enough, thats all I can say.

Could you use boost::unordered_map ? It could perform better.
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Re: Component Based Objects?

Post by KungFooMasta »

dzeligman,

There are probably a lot of alternatives but this is what I do in my system. We define the concept of a Move, and GO's can execute moves, if they have a GCMoveManager. Our Move class has an onEnter, onUpdate, onExit function. (Even GO's that are idling, ie ninja sitting there, are performing an 'Idle' move)

Triggers - create an abstract Trigger class, create a GCTriggerManager that can create Triggers, and create a factory for custom triggers to be registered. Triggers need callbacks such as onEntered, onExited, onUpdate.

UI - if its strictly 2d UI layed on top of the scene, I handle these kinds of things with my SceneComponent classes. If its 3d UI then make some kind of GameObjectComponent that can encapsulate creation/use of UI.
Creator of QuickGUI!
Vectrex
Ogre Magi
Posts: 1266
Joined: Tue Aug 12, 2003 1:53 am
Location: Melbourne, Australia
x 1
Contact:

Re: Component Based Objects?

Post by Vectrex »

dzeligman wrote:One large issue i've come up with is how to design certain aspects of the game.

Currently I have functional physics, sound, light, camera, animation, mesh and rendering oriented components.

now for specific game logic I'm having a brain fart.

How would one handle trigger bounding boxes/areas or UI/stat related event/counters and that sort of thing.

I have an event system that allows components to send events to the other components of the parent GameObject or to all other subsystems with the world as a target or to another GameEntity alltogher.
Check out how Unity does it. It's a C# interface but the concepts are common.
mirlix
Goblin
Posts: 225
Joined: Mon May 01, 2006 12:03 am
Location: Germany
x 5

Re: Component Based Objects?

Post by mirlix »

reptor wrote:
mirlix wrote:I use a std:map with std:string as key and boost any as value. Its the most dynamic way but I dont know if it is fast enough when using a lot of message, for my demo game its fast enough, thats all I can say.

Could you use boost::unordered_map ? It could perform better.
Sure why not, it simply has to a container having a key and a value.

@dzeligman
I use messages as events. An trigger has a messagelist and every component interested in the event can subscribe to this message list and then gets an message when the event is trigged
dzeligman
Gnoblar
Posts: 11
Joined: Tue Oct 28, 2008 9:59 pm

Re: Component Based Objects?

Post by dzeligman »

Alrighty, I've implemented the above suggestions so that now each TriggerComponent has a list of subscribers that will be notified with an event when the triggering condition occurs. Thanks for the help.

I now have a separate question in regards to the discussion of messaging systems.

Currently my system does the following:

Components register with their parent subsystem for what message types they would like to listen for.
The subsystems register with a central eventmanager for what messages their components would like to listen for.

The eventManager will route messages of certain types to the subsystems that care about them.

****Now here is my question/dilemma****
The subsystems will handle the message based off the source of the event and the Target of the event where the Target is a simple enum:Self,World,.

I don't like the eventtarget aspect of an event. I use it for when components of different subsystems but from the same game object want to talk with one another, but I'm not sure how to best approach inter-object communication or if I really even need it quite frankly. I allow for components to query the other components of their parent gameobject, but only in special situations so I can maintain the ideal case where components don't know about the other components.

An example of inter-gameobject communication, a physics character controller component is updated based off some input and the player's state changes from Jumping to Walking. The physics component sends an event saying its state change, the physicssubsystem sends this to the eventmanager and the eventmanager sends the event to the other subsystems that care about the statechange event. The subsystems send the event to components whose parent ID is the same as the sourceID (and who are registered to listen for an event of that type).
--an alternative implementation is where I do gameobject->GetInterface<Component>("AnimationComponent",goID)->handleEvent(event);
This requires me knowing which components care about the provided event, doesnt use the register/subscribing of subsystems and just uses the pure virtual funciton handleEvent's implementation directly.

So right now if I don't have that eventTarget type all component within the system would be receiving a state change event that they shouldn't. If I simply just used the source as the target than I would be unable to send events from one GameObject to another.

This sound ok? : /
User avatar
oddrose
Orc
Posts: 470
Joined: Thu Feb 15, 2007 2:08 pm
Location: Gothenburg, Sweden
Contact:

Re: Component Based Objects?

Post by oddrose »

Any news guys?
mirlix
Goblin
Posts: 225
Joined: Mon May 01, 2006 12:03 am
Location: Germany
x 5

Re: Component Based Objects?

Post by mirlix »

Not really, I have used my framework for a first game prototype but now my to do list is way to long and Im planning on refactoring the framework quite a bit to add new functions or use the experiences colleted during working with it. But the idea itselft is working, but the framework isnt as smoth as I would like it to be.
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Re: Component Based Objects?

Post by KungFooMasta »

Hey guys! My messaging system is working great so far, I'm very happy with it. I've also refactored my engine/framework recently, I don't think I'll be doing any major refactoring in the future, unless its needed when I decide to take a stab at a more multi-threaded approach.

My new system is very decoupled, there is a Core class that stores pointers to subsystems for accessibility, and has a main loop that sends out messages. If anybody is listening to these messages, they will respond and handle them in their own way. (For example, I broadcast messages of type "RenderOneFrame" and "StepPhysics", etc.)

The best part of the system is having the subsystems be very open ended. The Core library outlines a bunch of interfaces that must be used, in order for a class to represent a GraphicsSystem, PhysicsSystem, InputSystem, etc. So right now I have the following projects:

GaiaCore
GaiaOgreGraphicsSystem
GaiaRakNetNetworkSystem
GaiaHavokPhysicsSystem
GaiaWinSplashScreen
GaiaOgreOggSoundSystem
etc.

At any time I could choose to swap out systems, for example I could create the following projects and use them:

GaiaLinuxSplashScreen
GaiaENetNetworkSystem
GaiaFModSoundSystem
GaiaDirectXGraphicsSystem
etc.

As long as each project follows the interfaces outlined by the Core class, my Game application can get these systems and use them, without needing to know how they are specifically implemented.

For example, the following classes/interfaces must be implemented in order to have a valid Gaia GraphicsSystem:
- GraphicsSystem, Window, Scene, Renderable, Mesh, Terrain, SceneNode, Camera, Viewport

Also the Core library outlines all fundamental data types, ie Vector2, Vector3, ColorValue, Quaternion, etc. and I have string and math utility classes (copied from Ogre basically, because its pretty good and all I need at this point :) ). There are no problems doing conversions between Ogre Vector3 and Gaia Vector3, or Havok hkpVector4, etc. because they all implement interfaces using Gaia data types. The end application doesn't know all these types, and only needs to know of Gaia Vector3.

Not necessarily related to Components, but architecture. Thought I would share, I really love this design. :D
Creator of QuickGUI!
Trefall
Gnoblar
Posts: 13
Joined: Tue Mar 13, 2007 4:39 pm
x 1

Re: Component Based Objects?

Post by Trefall »

Thanks a lot savuporo for your patch. I'm really sorry that it took me this long to implement it. No excuses!

I've updated my component library some for convencience and through testing. I'm building a tower defense game on top of it now, and I also have an online game in development on it. I've finished a small demo on it also with good results :)

I added a small example of usage too. A simple console text application that demonstrates the interaction between two objects using three components (Health, Claws, Explosive). On top of that I included the necessary dependencies to ClanLib in a small additional library on my subversion for convenience, but the Entity Engine source code has been typedefed out of a direct dependency to it. Check out Types_ClanLib.h for typedef definitions.

To accompany the commands system, I've also added a similar event system that can flow through components. Basically a command is a way to tell something what to do, while an event is something that happens in the world and one can choose to react to it. I bind my input system to commands, for example. I switched the input type for commands to enums now too, for better performance.

There's probably some other small changes in the code too, hopefully for the better! :)

Here's the link to my repository: http://svn2.xp-dev.com/svn/Trefall-ComponentSystem

The property based component system resides under /Source/, in addition I've added the ClanLibExtract folder, the EventEngine folder and the TestEntity folder. The solution file under Source includes all these projects for compilation in VC++.
User avatar
ahmedali
Gnome
Posts: 302
Joined: Fri Feb 20, 2004 8:52 pm
Location: Lahore, Pakistan

Re: Component Based Objects?

Post by ahmedali »

I see a lot of people are using strings for properties and messaging for params. Who uses StringTables or StringIDs??? and How?

I used to use StringIDs and std::strings interchangeably in the code. Because once strings are converted into unique IDs its faster to do searching.

Now a days i tend to use boost::flyweight lib for string ids, which is good, with nice features and its customizable. You can see the performance benchmark of boost::flyweight to see string initialization, access, assignment and comparison timmings with standard std::string.
User avatar
koirat
Orc
Posts: 446
Joined: Mon Feb 25, 2008 7:56 pm
x 13

Re: Component Based Objects?

Post by koirat »

I'm using array index for my properties. To be more precise all my properties/services have to be registered (in a special manager) before using, when you do it you will obtain special object let's call it (accessor). You can use this object to acccess such a properties on a different containers. Internally I'm storing properties as array so if you have two properties one that is going to be on index 0 and the second that is going to be on index 20 you will have a lot of empty array indexes between them. Also there is no problem by accessing property via string, or obtaining accessor via string. The beauty of accessor is that it's faster than string hash table and you can change it's implementation later on without messing everywhere.
This is a block of text that can be added to posts you make. There is a 255 character limit.
crancran
Greenskin
Posts: 138
Joined: Wed May 05, 2010 3:36 pm
x 6

Re: Component Based Objects?

Post by crancran »

Over the last 3 months, I have spent countless hours reading up on varying open source libraries, reviewing example code snippets by other software developers, and even taking time to dive into some open source engines to see what design choices were made and evaluating the pros/cons of those choices. After stumbling onto this thread a few weeks ago, I have repeated found myself coming back to it and referencing posts that are made, trying to learn from what others have posted here and drafting my own implementation.

So first we need a GameObject.

Code: Select all

// Game Object
class GameObject 
{
public:
  GameObject(const std::string& objectId);
  ~GameObject();
  void addComponent(GameComponent* pComponent);
protected:
  std::string&              m_ObjectId;
  std::list<GameComponent*> m_Components;
};
The GameObject class contains a list of GameComponent objects which provide the heart and meat of what this GameObject does and what it reacts to in the game world.

So obviously the next thing we need is this GameComponent.

Code: Select all

// Game Component
class GameComponent 
{
public:
  GameComponent(const std::string& componentName, const std::string& familyName);
  void setParent(GameObject* pGameObject);
protected:
  std::string& m_ComponentName;
  std::string& m_FamilyName;
  GameObject*  m_pParent;
};
Several have indicated the use of an event-driven message system to decouple the communication between your components. What did your event system class look like, how did you go about registering the listeners and dispatching the events when they happened? For example, a strike against your character reduced their health by 10 points or being notified to move forward by 1 step, etc.

My goal is to make a very simple game, nothing fancy like WOW. I want to be capable of rendering multiple objects to the screen and allowing my character to navigate around these objects and even interact with them in some way such as using an emote (/bow) and the NPC would bow back to saying "Hi" to a target and they reply with "Hello".

Anyone willing to help?
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Re: Component Based Objects?

Post by KungFooMasta »

I have my own projects that need attention, but I'm willing to share my messaging system, its very simple:

Message:

Code: Select all

	class _GaiaCoreExport Message
    {
	public:

		Message() :
		  messageType(""),
		  messageSource("")
		{}

		Message(const std::string& MessageType, const std::string& MessageSource) :
		  messageType(MessageType),
		  messageSource(MessageSource)
		{}

		// A string identifier representing the type of message.
		std::string messageType;
		// A string identifier representing the source of this message.
		std::string messageSource;
		// A map storing data corresponding to a string (ID) key.
		std::map<std::string,boost::any> dataMap;

	protected:
	};
MessageHandler:

Code: Select all

	class _GaiaCoreExport MessageHandler
    {
	public:

		virtual ~MessageHandler();

		virtual void handleMessage(Message m) = 0;

	protected:
	};
MessageManager (the meat of the system):

Code: Select all

	class _GaiaCoreExport MessageManager :
		public Singleton<MessageManager>
    {
	public:

		// Core is the only class that can create and destroy the MessageManager
		friend class Core;

	public:

		/**
		* Broadcasts a message immediately to all subscribed messageHandlers.
		*/
		void broadcastMessage(const Message& msg);

		/**
		* Modifies disabled MessageHandlers to resume receiving of Messages.
		*/
		void enableMessageHandler(MessageHandler* instance);

		/**
		* Prevents Messages from being routed to a MessageHandler.
		*/
		void disableMessageHandler(MessageHandler* instance);

		/**
		* Broadcasts queued messages, starting with the highest priority ones.
		*/
		void processQueuedMessages();

		/**
		* Remove any associations to the given handler, so it cannot receive any messages.
		*/
		void removeAssociations(MessageHandler* instance);

		/**
		* Queues a message to be broadcast.  All subscribed messageHandlers will be notified on next MessageManager update.
		* Priority dictates the order in which queued messages will be broadcast. (All high pri messages are broadcast first, then med pri, etc.)
		*/
		void queueMessage(const Message& msg, MessagePriority p = MESSAGEPRIORITY_LOW);

		/**
		* Subscribes a MessageHandler instance to receive messages of a certain type.
		*/
		void subscribeToMessage(const std::string& messageType, MessageHandler* instance);
		/**
		* Subscribes a MessageHandler instance to receive messages of a certain type, from a specific source.
		*/
		void subscribeToMessage(const std::string& messageType, const std::string& source, MessageHandler* instance);

		/**
		* Unsubscribes a MessageHandler instance, preventing it from receiving messages of certain types.
		*/
		void unsubscribeFromMessage(const std::string& messageType, MessageHandler* instance);
		/**
		* Unsubscribes a MessageHandler instance, preventing it from receiving messages of certain types from a specific source.
		*/
		void unsubscribeFromMessage(const std::string& messageType, const std::string& source, MessageHandler* instance);

	protected:

		MessageManager();
		virtual ~MessageManager();

		std::list<Message> mLowPriMessageQueue;
		std::list<Message> mMedPriMessageQueue;
		std::list<Message> mHiPriMessageQueue;

		// List of Listeners that are currently unable to receive messages.
		std::set<MessageHandler*> mDisabledListeners;

		// The key is the message Type, the value is a list of MessageHandlers that will receive the message
		std::map< std::string, std::set<MessageHandler*> > mGenericMessageListeners;
		// The key is the source of the message, the value is a list of MessageHandlers that will receive the message
		std::map< std::string, std::map< std::string, std::set<MessageHandler*> > > mSpecificMessageListeners;
	};
Example usage:

Code: Select all

		{
			...
			// Subscribe to Message types
			MessageManager* mm = MessageManager::getSingletonPtr();

			mm->subscribeToMessage(DefaultMessageType::DestroyCamera,this);
			mm->subscribeToMessage(DefaultMessageType::DestroyMesh,this);
			...
		}

		void Scene::handleMessage(Gaia::Message m)
		{
			if(m.messageType == DefaultMessageType::DestroyCamera)
			{
				Camera* camera = boost::any_cast<Camera*>(m.dataMap["camera"]);

				Ogre::Camera* cam = camera->mOgreCamera;

				delete camera;

				// If cam is NULL, it means it has already been cleaned up, prior to the
				// Gaia::OgreGraphicsSystem::Camera class.
				if(cam != NULL)
				{
					mOgreSceneManager->destroyCamera(cam);
				}
			}
String comparison isn't the most efficient comparisons out there, but premature optimization isn't a priority for me. :wink:
Creator of QuickGUI!
Post Reply