Component based game engine architecture

Started by
14 comments, last by Dominik2000 10 years, 8 months ago

I like your architecture very much!

I like the idea with the model in behind the entity and the component type as initializer. Is your componentType a static class?

What I don't get is who is responsible for the notfiy that an entity should be created? My scene manager should to this, but is this a subsystem also? How do you store your entities? Is this a vector?

Dominik

Advertisement


Is your componentType a static class?

ComponentType isn't a static class. It is ... well ... something complicated. Here comes an explanation what I'm doing ... you've asked for it ;)

ComponentType is derived from Extension. Extension is the mechanism used to, well, extend a basic functionality. The base class Extension provides methods mainly for editor purposes, e.g. what version, designation, description, and so on, i.e. stuff to tell a user for what a concretization of the Extension is good for. The base class also defines an inner template class Extension::Registry. Now, the first level of inheritance are the concrete extensions like said ComponentType (but also my sub-systems Video, Audio, Input, Graphics, Sound, Feedback, and FileSystem are concrete Extensions, and a couple of other, platform independent classes like ProjectType, ResourceType, FileFormat, CompressionScheme, ...).

Each concrete Extension class has a static member instance of Registry. Such a registry is populated with derivatives of the belonging concrete Extension class, e.g. ComponentType::registry is populated with derivatives of ComponentType. This population may be done at application start-up or later on; it may also be done by static objects called a PlugIn which is itself an Extension (just to make things more interesting ;)) However, the static registry must be instantiated before a static PlugIn must be instantiated, or else things goes terribly wrong. Hence I use PlugIn only for dynamic libraries. BTW, registering Extensions goes a similar way of dependency resolution as Entity instantiation described above, so that the order in which Extensions are registered plays no role.

Each registry can be searched for an attached Extension by its Extension::kindName, a 4CC, or perhaps some other criteria. The FileFormat::registry, for example, allows also to search by MIME type, and it also allows to search by competence of the FileFormat to handle a given file. So accessing a specific Extension means to ask the registry of its concrete Extension class to look it up. Iterating all registered Extensions is possible, of course, too.

Now, the functionality of an Extension returned from a registry isn't allow to alter members, because the Extension is a shared class. This may or may not be a problem, depending on what concrete Extension we're speaking. To solve this "problem", such concrete Extensions declare some factory methods for specific abstract, inner classes. E.g. FileFormat declares the Importer and Exporter classes. On the other hand, ComponentType doesn't need to do so, because it isn't a worker class in this sense.

You may ask "what the hell is that man doing there", and you'll a bit right. To justify myself, my engine and my editor are very data driven. Even the functionality becomes somewhat data driven with the above approach. This is because I'm able to iterate e.g. the ResourceType::registry with a set of Profile instances belonging to the ProjectType of the current project, display the Extension::designation of each resulting Extension, allow the user to context click on each of them, so picking e.g. the "create" menu item, instantiate a ResourceCreateCommand that, when finally overhanded to the CommandProcessor, just invokes the ResourceType::runCreation() method. Well, editor-like, isn't it? ;)


What I don't get is who is responsible for the notfiy that an entity should be created?

Instantiation of an Entity during running the game may have the following causes: Loading of level, or else an in-game trigger has fired. Both causes belong to the scene. If your SceneManager is responsible for loading the scene, then it has to start instantiation of Entities, yes. Triggers (regardless of being timed, due to collision detection, or whatever) are used to start a script (a nodal script in my case); one node has the functionality "create entity". So in this case the script processor does the job; however, it does so by invoking the Scene.


My scene manager should to this, but is this a subsystem also?
In my opinion, the scene manager is a (subsystem) Services, right you are. It manages the world by knowing all the entities inside. Please notice that this understanding of a scene is by far different from a scene graph.


How do you store your entities? Is this a vector?
I'm not sure whether I understand you correctly. An Entity in my sense is a set of allocated structures distributed over a couple of Services'. Many Services' store their data in one or more AoS (a.k.a. Array-of-Structures). Some use dynamic, doubly linked lists with indexing. Whatever is suitable for the specific task.

Ok wow, very interesting. But it seem for my "small" project it's a little bit overkill ;) The game engine grows with time, and I think, many things changes after time.


I'm not sure whether I understand you correctly. An Entity in my sense is a set of allocated structures distributed over a couple of Services'. Many Services' store their data in one or more AoS (a.k.a. Array-of-Structures). Some use dynamic, doubly linked lists with indexing. Whatever is suitable for the specific task.

You've said that your entity is nothing more than an id and a reference to the model class. Anywhere you have to save this entity?

I want to thank for the many posts on my thread. Because I'm a newbie I have been afraid to take a "one-way" road and can't get back... I post here the link to my repository: https://github.com/Dominik2000/Cantara/tree/CO/src

Please could you look a little bit over the code, if anything is wrong with it?

Some classes (e.g. BaseMessage) are not used at this time.

A little explanation: The Core class is responsible for the main loop, and it initializes the window in qt. The Engine update method will be called in every frame and calls an update for every subsystem registered. It implements the SceneManager also, which is not a subsystem in the list, but has it's own property. Every subsystem registers itself on the SceneManager.

If the SceneManager creates a new entity it defines the Model for the entity, which has a list with all required components. Then every subsystem will be notified to create the components it needs (RenderManager has two lists one for the MeshComponent and one for the PositionCompnent).

In simple words that's all. I have implement the model class because I think I need default values in the near future, and maybe this class can do this, and not only store a list of components.

Is there a problem with this design?

Thank you

Dominik


You've said that your entity is nothing more than an id and a reference to the model class. Anywhere you have to save this entity?

Okay, now I understand. A bit of clarification, because I haven't expressed exactly what I wanted to say: Some people implement an Entity itself as an object with some responsibility, e.g. as a message dispatcher, as a collection of its components, as carrier of the placement in world, or whatever. My implementation of Entity is, from the functional point of view, distributed over the Services', so there is not a single / root object of an entity. To identify distributed parts to belong to the same entity, the Scene allocates an identifier as first step when the entity gets instantiated. This identifier is a positive integer number with the possibly smallest value currently not yet allocated. In general, this identifier can effectively used as index into an array or as key into a search tree or similar. Each Services' gets the identifier along with the Component when it is invoked during instantiation. The Scene itself uses an array of pointers to Model.

Ok, now I understand. I hope it doesn't bother you, that I have took your model idea. I have implemented this, because this is a good point, for setting default values, I think.

So I think, this part of the engine is enough for the moment.

This topic is closed to new replies.

Advertisement