GOBox* FStateBattle::createBox( const Vertex& position, const Rotation3D& rotation, const Vertex& initialVelocity ) {
GOBox* box = NULL;
Property_ptr properties = m_gameObjectFactory.getPropertiesFor( DESC_PATH_GO_BOX ); // Step 1
if( properties.get() == NULL ) {
mdLog( ( "GeneralError", "Properties were NULL for GO_BOX\n" ) );
}
else {
try {
properties->setProperty<Vertex>( GO_PROP_POSITION, position ); // Step 2
properties->setProperty<Rotation3D>( GO_PROP_ROTATION, rotation ); // Step 2
box = m_gameObjectFactory.createGameObject<GOBox>( properties ); // Step 3-6
}
catch( RequiredPropertyNotFound rpe ) {
mdLog( ( "GeneralError", "Caught Exception: %s\n", rpe.what() ) );
}
catch( ObjectCreationFailed ocf ) {
mdLog( ( "GeneralError", "Caught Exception: %s\n", ocf.what() ) );
}
}
return box;
}
// So the final top level code for creating a box looks like:
GOBox* box = createBox(); // The arguments all have default values to default constructed objects of their type
Game Object Creation System
So I have this object creation system and am interested to get some of you guys-es opinions on it:
Here is an example of a wrapper function we use to create a Game Object.
The idea behind this object creation approach was to avoid using singletons
as managers as well as avoid complicated constructors with tons of dependencies
on loaders.
We also wanted the system to be data driven, so we could specify values in XML
files for the objects. In addition, we needed to be able to tweak those values
at object creation time.
This is our solution:
---------------------
1) The Game Object Factory contains a PropertyFactory which it provides access to.
Passing a path to an objects XML properties file will validate and parse the XML
file, deserializing all of the data into proper data types which are then stored
in a PropertyObject and associated with whatever name they are given by the XML.
This PropertyObject is return to the calling code.
2) The the individual properties in the PropertyObject can be tweaked and new ones can be
added here.
3) The final PropertyObject is passed to the GameObjectFactory. The GOFactory contains
references to all of the support systems for loading every type of data (Models,
textures, ect...).
4) The property object is passed to the constructor of the object that is being created
so basic information not dependent on external support systems can be attained by
the object's constructor.
5) Then the GOFactory takes the property object and loads data for any elements that
require loading and sends just the resource handles to the newly created object.
The resource handles are assigned to the objects using optional interfaces.
6) Finally if the object is created successfully, a pointer to it is returned. If any
step of the process failed, the allocated memory (if any) is deleted, and an
ObjectCreationFailed exception is thrown with information about what failed.
There are several complex (and possibly more robust) methods of doing this sort of thing and I'm sure before long somebody will post something containing templates to solves your problem (and all the other problems in the world) very well.
I can only really present a solution that I've found to work just fine in the past, and continue to use to this day. Apologies if my code appears a little 'old school' (and thus a little unsafe looking)
I've left out the functions that don't really mean much in the context of your problem and aside from a couple of comments I've left out the error checking just to keep things easier to read.
The system I'm about to ramble in great length about basically uses parameter classes that act as factories for particular game objects. so making a particular game object is a simple case of getting a parameter object, filling it in and then using it to create a game object.
Ok, on with the code.
First I'll assume you have some sort of generic list management system. i.e. a class (such as ListItem) that you can derive from and add and remove from a list class (such as List).
Now you'll need a few basic classes.
The basic abstract game object
The basic abstract game parameters object
Somewhere to store the parameters for game objects
That's basically all you'll need. now you just have to write the code to describe real game objects.
Real Game Objects
That's it for defining a real game object, now you just need some code to create them. despite using the rather cheesy 'MyGame' class here, I'm sure you get the idea.
Game Code
Every time you need to add a new type of GameObject to your code you just make a parameter object as well (usually just a few extra lines). Remember, all the different types of parameter object should be added into the manager (using AddParameters) when the game starts up, then whenever you need a new object, just call GetParams, fill in the values and the send it into
CreateGameObject. Result, the correct game object all filled in and ready to go.
Obviously I've missed out some areas where the pointer coming out of a function would need to be cast into a real (useful) pointer (i.e. the return from GetParams) this is because your choice of casting will no doubt be different to mine.
Cast how ever you like. then fill in the parameters how ever you like (my choice is usually to read them from a file) then the cast or un-cast parameters pointer can just be sent into CreateGameObject.
I hope all the ramble helps.
I can only really present a solution that I've found to work just fine in the past, and continue to use to this day. Apologies if my code appears a little 'old school' (and thus a little unsafe looking)
I've left out the functions that don't really mean much in the context of your problem and aside from a couple of comments I've left out the error checking just to keep things easier to read.
The system I'm about to ramble in great length about basically uses parameter classes that act as factories for particular game objects. so making a particular game object is a simple case of getting a parameter object, filling it in and then using it to create a game object.
Ok, on with the code.
First I'll assume you have some sort of generic list management system. i.e. a class (such as ListItem) that you can derive from and add and remove from a list class (such as List).
Now you'll need a few basic classes.
The basic abstract game object
//HEADER -------------------------------------//< GameObject - base class for an actual in game object of any kindclass GameObject : public ListItem{public: GameObject() {;};protected: virtual void Init (GameObjectParams* params) = 0; friend class GameObjectParams;};
The basic abstract game parameters object
//HEADER -------------------------------------//< GameObjectParams - base class for a block of parameters that describe an in game objectclass GameObjectParams : public ListItem{public: GameObjectParams(){;};protected: virtual GameObject* Create () = 0; //< this does the creating of objects virtual void SetDefaults (){;}; //< set any values in these parameters to default values virtual const uint GetTypeID () = 0; //< each parameter object should return a different (preferably unique) value from this friend class GameObjectParamsManager;};
Somewhere to store the parameters for game objects
//HEADER-------------------------------------//< GameObjectParamsManager - a class that contains a list of all possible parameter objectsclass GameObjectParamsManager{public: GameObjectParamsManager(){;}; ~GameObjectParamsManager(){ m_Parameters.Empty();}; GameObjectParams* GetParams (const uint typeID); //< search the parameters list and return one of the right type if it exists GameObject* CreateGameObject(GameObjectParams* params); //< create a game object from a series of parameters void AddParameters (GameObjectParams* params); //< add a parameter object for a specific type of game objectprivate: GameObjectParams* NextParam (GameObjectParams* curr); //< get the next parameter object in the m_Parameters list List m_Parameters;};// CPP ----------------------------------GameObjectParams* GameObjectParamsManager::GetParams(const uint typeID){ GameObjectParams* params = NULL; while((params = NextParam(params))) //< single equals intended { if (typeID == params->GetTypeID()) { params->SetDefaults(); return params; } } return NULL;}GameObject* GameObjectParamsManager::CreateGameObject(GameObjectParams* params){ if (params) { GameObject* object = params->Create(); if (object) { object->Init(params); return object; } //< you could throw an exception here if you wnted to. } return NULL;}
That's basically all you'll need. now you just have to write the code to describe real game objects.
Real Game Objects
//< EXAMPLE CODE//< HEADER#define UID_ObjectTypeA 1210508 //< this can be any number as long as it's unique within the scope of your game - use RTTI instead if you likeclass GameObjectTypeA : public GameObject{public: int m_ObjectAData;protected: virtual void Init (GameObjectParams* params)}class GameObjectTypeAParams : public GameObjectParams{public: int m_ObjectAData;protected: virtual GameObject* Create () { return new GameObjectTypeA;}; virtual void SetDefaults () { ObjectAData = 0;}; virtual const uint GetTypeID () { return UID_ObjectTypeA;};}//< GAME OBJECT SOURCEvoid GameObjectTypeA::Init(GameObjectParams* params){ GameObjectTypeAParams* tparams = (GameObjectTypeAParams*) params; //< this cast is always safe - but feel free to use templates, dynamic casting or what ever here ///< transfer the parameters m_ObjectAData = tparams->m_ObjectAData;}
That's it for defining a real game object, now you just need some code to create them. despite using the rather cheesy 'MyGame' class here, I'm sure you get the idea.
Game Code
//< SOURCEvoid MyGame::AddGameObjectParams(GameObjectParamsManager& GameObjectMan){ //< add all the different types of game parameters into the manager GameObjectMan.AddParameters(new GameObjectTypeAParams); /* obviously new object type would need new calls such as below GameObjectMan.AddParameters(new GameObjectTypeBParams); GameObjectMan.AddParameters(new GameObjectTypeCParams); GameObjectMan.AddParameters(new GameObjectTypeDParams); */}void MyGame::CreateGameObjects(GameObjectParamsManager& GameObjectMan){ GameObjectParams* params = GameObjectMan.GetParams(UID_ObjectTypeA); if (params) { //< cast and fill in any changes to the default parameters here GameObject* object = GameObjectMan.CreateGameObject(params); //< add the created object to your game m_GameObjectsList.InsertAtEnd(object); //< } else { //< throw an exception or what ever you fancy here }}
Every time you need to add a new type of GameObject to your code you just make a parameter object as well (usually just a few extra lines). Remember, all the different types of parameter object should be added into the manager (using AddParameters) when the game starts up, then whenever you need a new object, just call GetParams, fill in the values and the send it into
CreateGameObject. Result, the correct game object all filled in and ready to go.
Obviously I've missed out some areas where the pointer coming out of a function would need to be cast into a real (useful) pointer (i.e. the return from GetParams) this is because your choice of casting will no doubt be different to mine.
Cast how ever you like. then fill in the parameters how ever you like (my choice is usually to read them from a file) then the cast or un-cast parameters pointer can just be sent into CreateGameObject.
I hope all the ramble helps.
After asking a question, and getting a (long and rambling) reply I think it's usually common courtesy to reply, or say thanks ... or anything !!
Hey sorry man, been swamped at work,
I've been pouring over your reply in little bits of time I can find,
and it seems like maybe a bit more lightweight approach to the same method
I am using, which is probably a good thing.
Thanks for the reply, I just haven't had a second to breath lately.
I've been pouring over your reply in little bits of time I can find,
and it seems like maybe a bit more lightweight approach to the same method
I am using, which is probably a good thing.
Thanks for the reply, I just haven't had a second to breath lately.
I will reply later this weekend with what I think is an even better system that is a lot more generic and extendable. I just have to leave the house so people can come look at it and make an offer *fingers crossed* then food shopping and spend time with the wife. So it might not be until Monday. Hopefully the wait will be worth it.
Quote:Original post by Mike2343
I will reply later this weekend with what I think is an even better system that is a lot more generic and extendable. I just have to leave the house so people can come look at it and make an offer *fingers crossed* then food shopping and spend time with the wife. So it might not be until Monday. Hopefully the wait will be worth it.
Looking forward to hearing it.
My solution is a hybrid between Sneftel's posting on Outboard component-based entity system architecture and T=Machine's articles on Entity Systems. You can also find a nice compilation of links on the subject in this post by Nairb.
I basically leaned more towards T=Machine's Entity System then Sneftel's Component system. I just felt it was more game oriented but you can use which ever you think is better or not :)
My entity system is used to create game objects, gui components and other in game items (I made a generic EntitySystem that different systems can use).
So I can create a window entity that loads from an xml file (currently just text files as I threw it together as a test system) and it knows it needs 4 buttons, a text window with a vertical scroll bar. Each of these items are components that make up the larger window component. The window itself has no clue how to interact with each of its sub components. The scroll bar knows how to scroll the text in it's text window. The buttons know (says in the text file) what messages to fire to the system when clicked. So the window is basically dumb as it should be and the logic is held and handled in the components where it should be.
I was thinking about how you could update your objects upon loading and thought of a UpdateComponent which takes itself and passes it to another system that updates all it's data?
Anyways instead of writing up a boat load of information in it, it's already done for me in the links above. So I will let you read them instead of my boring stuff :)
I just thought it would be a great system for your issue which minimizes programmers requirements (aka work) and maximizes designers ability to design and create. It also makes things very, very data driven.
For example the button took me 10 minutes to write up the logic for it and it now works for all buttons. If I needed to add more functionality to it, I could create a different button component OR just add to the one I have. It would still be very trivial either way. I know the button wasn't the best example as I still have to code more logic in to handle the message it dispatches to the engine, but it's what I worked on most recently so it was "close to mind". The articles above give better examples more geared towards your current work.
Hope, in some way, this is handy and/or helpful.
Mike
I basically leaned more towards T=Machine's Entity System then Sneftel's Component system. I just felt it was more game oriented but you can use which ever you think is better or not :)
My entity system is used to create game objects, gui components and other in game items (I made a generic EntitySystem that different systems can use).
So I can create a window entity that loads from an xml file (currently just text files as I threw it together as a test system) and it knows it needs 4 buttons, a text window with a vertical scroll bar. Each of these items are components that make up the larger window component. The window itself has no clue how to interact with each of its sub components. The scroll bar knows how to scroll the text in it's text window. The buttons know (says in the text file) what messages to fire to the system when clicked. So the window is basically dumb as it should be and the logic is held and handled in the components where it should be.
I was thinking about how you could update your objects upon loading and thought of a UpdateComponent which takes itself and passes it to another system that updates all it's data?
Anyways instead of writing up a boat load of information in it, it's already done for me in the links above. So I will let you read them instead of my boring stuff :)
I just thought it would be a great system for your issue which minimizes programmers requirements (aka work) and maximizes designers ability to design and create. It also makes things very, very data driven.
For example the button took me 10 minutes to write up the logic for it and it now works for all buttons. If I needed to add more functionality to it, I could create a different button component OR just add to the one I have. It would still be very trivial either way. I know the button wasn't the best example as I still have to code more logic in to handle the message it dispatches to the engine, but it's what I worked on most recently so it was "close to mind". The articles above give better examples more geared towards your current work.
Hope, in some way, this is handy and/or helpful.
Mike
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement