Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

The Setup

I've made a few games (more like animations) using the Object Oriented method with base classes for objects that extend them, and objects that extend those, and found I couldn't wrap my head around expanding that system to larger game ideas. So I did some research and discovered the Entity-Component system of designing games. I really like the idea, and thoroughly understood the usefulness of it after reading Byte54's perfect answer here: Role of systems in entity systems architecture.

With that said, I have decided to create my current game idea using the described Entity-Component system.

Having basic knowledge of C++, and SFML, I would like to implement the backbone of this entity component system using an unordered_multimap without classes for the entities themselves.

Here's the idea:

An unordered_mulitmap stores entity IDs as the lookup term, while the value is an inherited Component object. Examlpe:

 ____________________________
|ID          |Component      |
 ----------------------------
|0           |Movable        |
|0           |Accelable      |
|0           |Renderable     |
|1           |Movable        |
|1           |Renderable     |
|2           |Renderable     |
 ----------------------------

So, according to this map of objects, the entity with ID 0 has three components: Movable, Accelable, and Renderable. These component objects store the entity specific data, such as the location, the acceleration, and render flags. The entity is simply and ID, with the components attached to that ID describing its attributes.

Problem

I want to store the component objects within the map, allowing the map have full ownership of the components. The problem I'm having, is I don't quite understand enough about pointers, shared pointers, and references in order to get that set up. How can I go about initializing these components, with their various member variables, within the unordered_multimap? Can the base component class take on the member variables of its child classes, when defining the map as unordered_multimap<int, component>?

Requirements

I need a system to be able to grab an entity, with all of its' attached components, and access members from the components in order to do the necessary calculations and reassignments for position, velocity, etc.

Need a clarification? Post a comment with your concerns and I will gladly edit or comment back! Thanks in advance!

natebot13

share|improve this question
    
frankly, for memory fragmentation reasons, I would find an implementation of open address hash map on the web (or do my own), because the STL one is close addressing. And I would use a pool of components (not a multimap, but a map of pools), which have enough space for a dozen of components by default (uninitialized), and then would chain list other pools on demand. Also you can consider using the entity ID as a direct index in an array, and use a free slots list when deletion happens. –  v.oddou Jul 25 at 2:14
    
@v.oddou I don't understand all of what you're saying, and to me, seems more complicated than I would like. Thanks for your information though! I have lots to learn... –  natebot13 Jul 25 at 16:09

1 Answer 1

map<Key, Value> (and it's mates) holds Value, well, by value. If you try to give it an instance of derived class to hold as value, most likely "slicing" will occur. More about slicing: http://stackoverflow.com/q/274626/1125702

std::unique_ptr<Component> seems exactly what you want. It manages lifetime and memory of owned object. By convention, only std::unique_ptr may "own" it's objects, i.e. anything other may only temporarily refer to given object (either by raw pointer or by references). It is programmer's task to ensure that std::unique_ptr will outlive any other references to "owned" object.

Usage is quite simple.

// type aliases for convenience
using ComponentPtr = std::unique_ptr<Component>;
using ComponentContainer = std::unordered_map<std::string, ComponentPtr>;

// instance of container
ComponentContainer cc;

// insert component (quick way)
cc["SomeComponent"] = std::make_unique<SomeComponent>(arg1, arg2, ...);

// 'get' returns raw pointer to owned object
SomeComponent * sc_ptr = cc["SomeComponent"].get();
sc_ptr->hello();

// reference, if '->' annoys you
SomeComponent & sc_ref = *cc["SomeComponent"].get();
sc_ref.hello();
share|improve this answer
    
Ok, that makes sense... So, I could create the multimap as std::unordered_multimap<int, std::unique_ptr<Component>>? And how would I go about adding elements into my map? I've tried mymap.emplace(id, Movable()); but the compiler doesn't like the fact that 'Movable()` isn't a Component class... –  natebot13 Jul 25 at 16:16
    
@natebot13 Because you are passing instance of derived class, but your multimap wants unique_ptr to Component. Try inserting std::make_unique<Movable>(). –  Shadows In Rain Jul 27 at 16:04
    
The standard library doesn't have make_unique. –  natebot13 Jul 30 at 6:49
    
@natebot13 make_unique is in C++14, but may be implemented trivially in C++11: stackoverflow.com/a/12580468/1125702 –  Shadows In Rain Jul 30 at 10:11

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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