Sign in to follow this  

Your views on my game object setup

This topic is 2534 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I want't to make a ridiculously dynamic data driven game :) Is this a resonable way to go?


template <typename T>
class GameObjectMessage
{
public:
enum messageAction { CREATE, DESTROY, SET, GET };

unsigned int targetID; //if targetID = 0 you acess the handler andcan create and destroy objects
unsigned int senderID; //if you create a object you get the new ID sent back, or if you request a variable
unsigned short int componentID; //the component you need to access in the target object
unsigned short int action;
int parameter1;
T parameter2;
};

class GameObject
{
public:
void setHandler(ObjectHandler *handler) { this->handler = handler; } //set pointer to the handler object, so the components can send messages

void setID(unsigned int ID) { this->ID = ID; }
unsigned int getID() { return ID; }

void setParentID(unsigned int ID) { this->parentID = ID; }
unsigned int getParentID() { return parentID; }

void addComponent(BaseComponent component); //so the GameObjectHandler can add components when creating the object

void processMessage(GameObjectMessage<int> message); //set or get variable in the correct component
void processMessage(GameObjectMessage<float> message);
void processMessage(GameObjectMessage<string> message);
void processMessage(GameObjectMessage<bool> message);

void update(unsigned int time); //calls update() in all objects, used by object handler

private:
ObjectHandler *handler;
unsigned int ID;
unsigned int parentID;
BaseComponent components[1]; //uses array instead of vector so i can serialize the object
};

class ObjectHandler
{
public:
unsigned int createObject(unsigned int prototypeID); //if no ID is specified in the prototype object, a random is assigned and returned
unsigned int destroyObject(unsigned int objectID);

void loadObjectPrototypes(string directory); //load all object prototypes from the directory, serialized objects in separate files
void saveObjectPrototype(string filename, GameObject object); //save single object prototype (i will use the same classes in the object editor)

void processMessage(GameObjectMessage<int> message); //handles create/destroy message or sends it to object
void processMessage(GameObjectMessage<float> message);
void processMessage(GameObjectMessage<string> message);
void processMessage(GameObjectMessage<bool> message);

void update(unsigned int time); //calls update() in all objects

private:
vector<BaseComponent> objectPrototypes;
vector<GameObject> gameObjects; //i want to be able to serialize och save and load all game objects in a file like a savegame, can't use vector
};

class BaseComponent
{
public:
void setObject(GameObject *object) { this->object = object; } //set pointer to parent object, so the components can send messages to handler

virtual unsigned int getComponentID(); //return a unique id of the derived component
virtual void update(unsigned int time);

private:
GameObject *object;
};

Share this post


Link to post
Share on other sites
Then you just combine the components as you please. like:
door, animation, lockable, breakable, geometry, collidable, sound

and set up parameters in the component objects, so they know where to send and request data. like door what animation and sound it should request when opened.

you could also make a separate object that is a keypad and tell it to "talk" with lockable for example, as long as you have named objects.

Share this post


Link to post
Share on other sites
Using a component-based system is certainly a good start, but if you really want it to be 'ridiculously dynamic', your best bet would probably be to make the engine scriptable (e.g. using Lua), and move the bulk of the game logic to the scripting side.

Share this post


Link to post
Share on other sites
Quote:
Original post by jyk
Using a component-based system is certainly a good start, but if you really want it to be 'ridiculously dynamic', your best bet would probably be to make the engine scriptable (e.g. using Lua), and move the bulk of the game logic to the scripting side.


I recently began doing this and I couldn't agree more. A dynamic language (like Lua) makes it so much easier to write the game object code. I would also recommend it for the user interface as well.

As a matter of fact I have essentially all of my logic in Lua. The script creates the window/renderer and manipulates the scene based on the game objects. All of the heavy weight stuff (rendering, scene interpolation, physics, quaternion/vector/matrix math) is done in C++, but instantiated through Lua. The Lua code is only called 20 times a second and the scene is interpolated between logic timesteps. So even though Lua has complete control, it is not running every frame. So far I love the decision but I am expecting to run into issues (like performance).

In other words. Using a dynamic language to script game logic is a great idea.

Share this post


Link to post
Share on other sites
I read about UML and decided to try it out before doing any more coding!

http://imgur.com/JWZBY.png

The component function getComponent() goes trough Scene.getEntity() and Entity.getComponent() to get a pointer to another component, then it can acess the variables in that component.
A component can also change scene state to exit to a menu, change level, or exit the game.

This is how it should work:
I create a SceneManager in my program.
Register all types of components. (used by entity creation with componentID)
Creates and add a scene.
Use the loadScene(xml file) that then add entities and use loadEntity(xml file) on each of them.
Then call SceneManager.update() and SceneManager.draw() in the game loop.
The game loop checks the sceneState to break the loop or change scene.

The scene xml will hold objectID and a path to another xml file that specifies the objects components and the components variables. Is this a resonable way to load objects? Could become many files fast!

Share this post


Link to post
Share on other sites
Seems like a pretty complex system, but looks like it would be fun to implement as a technical exercise. That said you'll probably find it difficult to actually finish a game out of it. Not sure if that's your intention or not though (actually making a game or just taking on the programming challenge).

One thing I'd throw in there based on your last post - using XML to store everything is going to lead to some pretty long load times as XML parsing can take a while. Your best bet would be to use XML as an intermediate format and convert them to something a bit more compact and laid out like the system would expect it. Whether that's easily possible with this kind of setup though, I'm not sure - you'd need to have a good think about it. But hey, that could be a fun challenge too :)

just thought I'd throw some random XML hate out there ;)

good luck!

edit: one more thing I just noticed in the code - "uses array instead of vector so i can serialize the object" - elements in a vector are stored contiguously just like a normal array, so you may want to use a vector for the convenience functions it provides (or alternatively your own array class, better suited to your game with regard to memory allocations etc)

Share this post


Link to post
Share on other sites
Perhaps it's a little complex :) but it feels more logical for me than other approaches i have seen. Also when this is done and tested, i can just hide the code and start focusing on the components! My goal is to learn something for fun and then see where it leads!

I have thrown away the old code, i decided to skip the messaging system and go for direct communication with pointers between the components.

Perhaps i'll skip the xml approach and just code something own.
A object could be defined by strings that you easily can tokenize and use to create objects:
component;;int;1
component;;int;2
component;;int;3
component;;int;4
variable;1;string;qwerty
variable;2;int;7
variable;3;double;5.7
variable;4;bool;false

And for the scene definition:
objectId;;0 (would create a object with random ID, other would create a "named" object)
objectType;;47 (would load a definition of type 47, like that above)
variable;1;int;10 (if you need to override variables)
and then onto the next object...

I have also been thinking about creating a manager that loads all the data and creates protoypes of each type of object. Should be effective when you reuse the object definitions for many objects.

Share this post


Link to post
Share on other sites
Actually I'd advocate the use of a message parsing/event based system. I have it set up so entities really only expose a HandleEvent function, and can respond to events as they please. It's not that difficult to get going.

The good thing I'd say about XML, is that it is easy to understand. But if you want the fastest performance you'd want a format the requires minimal parsing (or a binary format). There's nothing stopping you from converting XML into another format, though.

That said, that's probably the least of your worries for now.

Share this post


Link to post
Share on other sites
Ok, how does your messages look? I have been thinking a bit about it, something like a struct with:

int targetEntityID (0 for acessing the scene)
int targetComponentID
int senderEntityID (for eventual replies and other stuff)
int senderComponentID
int action (1 = set, 2 = get, 3 = add, 4 = remove)
int variableID
int dataType = (1 = int, 2 = double, 3 = string, 4 = bool)
string value

Then i could set, get add and remove variables from components, create and destoy objects with the scene object, change scene state. add and remove components in a object. Something more i need to be able to do?

also i forgot to mention that i intend to have a Entity (nr 1) with all the basic components like render, sound, control, physics and so on... the rest is just actual game entities.


Share this post


Link to post
Share on other sites
Well my entity system is much simpler. Most stuff is scripted, and most simple entities just use a base entity class (some stuff like NPCs and the player character have their own classes so heavy lifting can be done in C++).

An event for me is just an integer ID describing the event - some examples might be EVENT_CREATE (when the entity is first created, constructor stuff), EVENT_UPDATE (per frame tick update), EVENT_SHOT (fairly self explanatory :P) EVENT_TOUCHED (touched by another entity), etc.

Other than that there are a fixed amount of arguments (I use 2 at the moment, haven't needed any more than that but if I do it's simply a matter of adding an extra argument to the struct). They are Variants (that is, a structure containing basic types like an integer, boolean, float value or even a string, and a field saying what type it is).

In the C++ class there's a HandleEvent function which listens for a handful of events (just a simple switch statement), then passes the event off to the script's HandleEvent function. There's not really any validation done on the events, it's assumed if you are sending event X then it will have argument Y of type Z etc.

Once you have the system in place suddenly you start thinking in terms of messages and events and everything starts coming to you pretty clearly. For instance, I wanted a locked door that only unlocked if the player had a certain key/item (duh). So when you touch the door, the door's EVENT_TOUCHED handler sends an event back to the entity which touched it called EVENT_REQUIREITEM with the item type as an argument. If the entity has a handler for that event (which of course the player does), and it has that particular item in its inventory, it can send back an event EVENT_HAVEITEM. As soon as the door gets that, then it opens. Hopefully that makes sense!

Pretty simple system but it's worked well for me so far.

PS: when i say "event handler", I mean it has "if( EventType == EVENT_blah )", I don't do anything fancy ;)

Share this post


Link to post
Share on other sites
Allright! I think i'll stick with my plan, could always add a event component and event handler component later where Entities could register for a type of event, as well as send them.

Have just finished the Variable handler class, made functions to create variables from strings (also load them), will simplify loading and setting up entities later!
"variable;10;test variable name;int;97"
The name of the variable is only used for the editor, will be set in the constructor of the derived component classes.

Share this post


Link to post
Share on other sites
I ran into problems with mutual dependency so i decided try something like this instead:

http://i.imgur.com/Ar58f.png

MessageManager and PropertyManager are separate objects.
Pointers to them are passed down to the components by the sceneManager.
Then i can access properties of all Entities from all Components.
The properties is saved by sceneID and entityID.

With the MessageManager i can send messages to:
SceneManager, to change scene.
Scene, to create or destroy entities, save or load the scene.
Entity, to add or remove components.
Components, to trigger events.

Share this post


Link to post
Share on other sites
Your entity system looks cleaner than mine, I have a lot more functions in my SceneManager class... but also it's because most of my functions in my entity are in the context of rendering things, and not making them interactive. With that said you may be able to separate the drawing function from the entities into its own Scene Renderer like I have. For me this makes more sense for batching and ordering entities to be drawn when it passes through the API's rendering loop. The SceneRenderer will not expose these API rendering functions to the entities. Instead the entities pass the info to the SceneRenderer.

As far as managing the interactive logic for the entities, you seem to be on a good path on enclosing message info as objects, but I can't advise much there. My game logic is still coded in C++ but for me it still works since I just wanted to encapsulate all the rendering stuff and focus on the actual game.

I am not sure if I would want to load each entity as their own files. Maybe it's because I'm used to loading entire scenes and maps in one file... however in the case where you want to limit memory usage and only load entities as you need them on the fly. However, putting each entity in its own file may be less cumbersome if you use another language besides XML which leads to...

Quote:
Original post by mightypigeon
Actually I'd advocate the use of a message parsing/event based system. I have it set up so entities really only expose a HandleEvent function, and can respond to events as they please. It's not that difficult to get going.

The good thing I'd say about XML, is that it is easy to understand. But if you want the fastest performance you'd want a format the requires minimal parsing (or a binary format). There's nothing stopping you from converting XML into another format, though.

That said, that's probably the least of your worries for now.


YAML or JSON are simpler to parse and the text is less verbose. If you want something that is faster to read by the program and still easy to understand and edit by hand and not worry about planning your own binary format, I would go with either one. I may go as far to say as they can be even easier to read than XML once you understand the syntax.

Share this post


Link to post
Share on other sites
I think i'm going to create my own simple format for describing the entities.
The components i just clone from a factory by componentID so thats easy!
The variables i can create from a simple string that i parse.
name;datatype;value

I'm also thinking about creating a entity factory that i load up with each type of object from file/files at the program start, then the parsing don't have to be so fast, and it's a lot faster when i create objects on the fly!

Share this post


Link to post
Share on other sites
I just finished my Entity factory. Works perfect!
I register the available components.
Then use a function that load all files in a directory, describing the different types of entities, and create the entity prototypes, then i just call getEntityClone(int prototypeID) and get a unique entity including cloned components and property list.

So when i load a scene i just have to specify what entity prototypes i want and then change some properties on them.

Share this post


Link to post
Share on other sites

This topic is 2534 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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