7
\$\begingroup\$

For my project I would like to use a component-based entities in C++. My current implementation is split to these parts:

  • Systems - Contain a map of components of certain class and operate on these. For example PhysicsSystem has a vector of PhysicsComponents.
  • Components - A component contains some public variables and a maybe a constructor to initialize them.
  • Entities - An entity for me is just an Id. It is however not stored anywhere, instead only its components are stored in systems in map (where key is entityId and value is pointer to the component).

My problem is creating instances of different objects in my game. I would like to define objects in XML (could be any text file format). For performance reasons this file should be parsed only once when the program is run.

That means I should create some template from it in my ObjectFactory and associate it with a name. Then I would simply call factory.CreateObject("Player") to add new entity to the game.

I am not really sure how to implement this without too much overhead code. Another concern is, that the I don't want my factory to know about the systems themselves. But because my components are stored in the systems and not an Entity object, I will need to use some messaging system to pass new components to their appropriate system.

My question is, how would I implement the object spawning with template for each object type? And how do some engines describe their objects with configuration files?

\$\endgroup\$
  • 2
    \$\begingroup\$ Looks like the need for the prototype design pattern... \$\endgroup\$ – The Light Spark Sep 30 '15 at 10:31
2
\$\begingroup\$

Give your ObjectFactory class a make_copy function, that takes in an entity and can create a complete separate clone of that given entity, creating new components which are identical to the original entity's components and add these new component to the new entity. You can load this "origional" entity from file once and store it in some map or something with a name as key ( like "Player" ). This entity will now act as a template.

Later when you want to make an instant of that template, you can call factory.CreateObject("Player");, which would look up the map with "Player" and then make a copy of the template entity and return it to you and tada!

EDIT:

To solve your "Passing the component to systems" problem, Have a base System class which will have a pure virtual AddComponent function which would accept a pointer to component. Make all your Systems derive from this System base class. Then let the ObjectFactory store a list of pointers to these Systems and whenever it creates a new Component, it passes it to the respective system.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the answer, this set me on the right track. One issue with this however is, that in my implementation, the components are stored in the systems. When I create a copy of each component some entity should have, I'd need to somehow pass these to their appropriate system. \$\endgroup\$ – davidv Sep 30 '15 at 13:28
  • \$\begingroup\$ @user2715488, added that to the answer. \$\endgroup\$ – The Light Spark Sep 30 '15 at 13:54
  • \$\begingroup\$ @user2715488 I'd be interested in how you solved the problem. I also have two suggestions for you. \$\endgroup\$ – danijar Sep 30 '15 at 15:09
1
\$\begingroup\$

How do you currently communicate between systems? If you have some kind of messaging or event manager, you could have a create_entity message that gets send to all systems along with the parsed XML tree. Systems looks for tags describing their components and create them if found.

You could also share the component arrays between systems. For example you can create a ComponentCollections class and pass a reference to the constructors of your systems. It can be related and doesn't need to know about your component types. This way, a system can create complete entities. You may want one dedicated system to load and create entities though so that the other systems depend on as few components as possible.

This is also useful if the RenderSystem wants to access the world position of objects that is updated by the PhysicsSystem.

By the way, if you want cache-locality, the components must be stored consecutively in memory i.e. in an array or vector rather than a map. You can however have a map from entity id to vector index for random access.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.