2
\$\begingroup\$

I have a question : I'm currently programming a roguelike game (with tiles) using the ECS programming paradigm, and I'm struggling with how to implement the map.

At first, I made every terrain square an entity (with a screenPosition and a sprite components), but that quickly lead to performance issues (a 100x100 map is already 10k entities).

So now, I want to treat the whole map of a level as a single entity, but I'm unsure on how to do it. Should I make a map component, that will store every terrain properties? That seems "bad" to me. Is there a better way?

Thanks


Edit :

My implementation is something like this :

  • Each entity is a struct that store a list of pair of component_id (an int) and component_handle (an int).

  • Components are struct

  • an EntityManagerSystem store all the entities in a vector, and all the components, each kind in its own vector. Each vector is public, the id of each entity is its vector index, and the component handle is the component index too

  • a RenderSystem that iter over the entity vector from EntityManagerSystem, and draw the ones that have the corresponding components

  • an EngineSystem store pointers to all the Systems and call them sequentially to update : it's the "main" class


In RenderSystem, it's this loop the culprit :

em is the entityManager and CT_HASH is a compile time hash.

for (std::vector<GameObject>::iterator it = em->entities.begin(); it != em->entities.end(); ++it)
{
    if (it->HasComponent(CT_HASH("ScreenPosition")) && it->HasComponent(CT_HASH("Sprites")))
    {
        ScreenPosition pos = em->screenPosition[it->GetComponent(CT_HASH("ScreenPosition"))];
        if (0 <= pos.x && pos.x < xSize && 0 <= pos.y && pos.y < ySize)
        {
            Sprites sprites = em->sprites[it->GetComponent(CT_HASH("Sprites"))];
            for (int z = 0; z < 10; z++)
            {
                if (sprites.sprites[z] != 0)
                {
                    spriteMap[pos.x][pos.y][z] = sprites.sprites[z];
                }
            }
        }
    }
}

It takes around 300ms for a 100x100 map with only the terrain entities

\$\endgroup\$
  • \$\begingroup\$ You'll have to explain to us what is your ECS. There is as many ECS implementations than there is dev teams. \$\endgroup\$ – Vaillancourt Dec 23 '15 at 1:51
  • \$\begingroup\$ @AlexandreVaillancourt : is it enough information now or should I detail more? \$\endgroup\$ – Tryss Dec 23 '15 at 2:24
  • 2
    \$\begingroup\$ It's better! You say you have performance issues; what is causing the issue? Did you profile your app? \$\endgroup\$ – Vaillancourt Dec 23 '15 at 2:40
  • \$\begingroup\$ @AlexandreVaillancourt : I think the issue is just "too much entities", or I may do a very big mistake somewhere... But no matter what, I'm sure I will have a bottleneck with my current design : what if I want a 250x250 map? Boom, 62k entities (and the pathfinding will be problematic) \$\endgroup\$ – Tryss Dec 23 '15 at 5:13
  • 1
    \$\begingroup\$ @AlexandreVaillancourt : Thanks for your input. I tried a version where the entities are index of a lookup table of index of components in their own array, and it's 6-7 times faster. So now, I'll implement the map in chunks of terrain, like 16x16, and my entity number will drop and further increase performance \$\endgroup\$ – Tryss Dec 23 '15 at 13:41

Your Answer

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

Browse other questions tagged or ask your own question.