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.

I'm creating a 2D game based on entity-system architecture using C++, the C++ port of Artemis, and SFML. I've had to jump through a few hoops, but it's been fairly smooth until now.

In this game, I have an EntityFactory class which basically just makes artemis::Entity objects, does some processing (such as creating sprites or setting the position of the entity) and returns that artemis::Entity. This is represented by a static class, something like this:

class EntityFactory {
public:
    //Creates the player, should only be called once
    static artemis::Entity CreatePlayer(artemis::World& world, sf::Vector2f pos);
    //Creates a bullet, can be called many times
    static artemis::Entity CreateBullet(artemis::World& world, sf::Vector2f pos);
    //Creates a static image
    static artemis::Entity CreateStatic(artemis::World& world, sf::Vector2f pos, std::string imgLoc);

    //Some more entities...
}

It's fairly essential that I call these functions to create the entities; the class does a lot of boilerplate stuff, like adding all the necessary components to the entity.

Lately, I've been thinking about implementing a particle system in the game as well. In addition, I'd like to be able to reuse my bullet entities instead of creating & destroying them all the time. To this end, I figured I'd create a Pool class that holds entities, and disables/enables entities as needed - a common pattern. Here's the basic layout that I was thinking of:

class Pool {
public:
    //Enables/returns a disabled entity, or creates a new
    // one and returns it if there are none available.
    artemis::Entity& get(/*Some data about the object*/);
    //Disables an entity, and marks it as reusable.
    void disable(artemis::Entity&);
private:
    //Data structures for holding the active/disabled entities...
    Function_of_some_sort createEntity;
}

Alright, that's all well and good, except for the one sore spot - that ambiguous Function_of_some_sort. I'd like to let the Pool create its own Entity objects in Pool::get() . Obviously, I want to use the EntityFactory, since it does a bunch of work; however, to do so, I'd need to be able give the Pool a function with an arbitrary number of arguments and be able to pass Pool::get() the same number of arguments.

As I see it, I have these options:

  1. Limit my functions to a single signature and use a function pointer, eliminating possibilities like EntitySystem::CreateStatic (above).
  2. Implement arbitrary, generic callbacks as described here, sacrificing some typesafety.
  3. Give up the idea of an arbitrary-entity Pool, and make a Pool class for each entity I need. Might be ok, since I don't really have that many classes that need a Pool, but I'm only changing a single function call in each Pool class...
  4. Refactor EntityFactory somehow so that I don't need function callbacks. Probably the best solution, but I haven't been able to come up with a good way to do it.

I feel like there has to be some elegant way of pulling this off, as these are two fairly common patterns that I'm sure have been used in conjunction before. I'm stuck in analysis paralysis; does anyone have examples or experience to offer on the subject, or just some suggestions?

share|improve this question
4  
It's so weird seeing my Artemis port actually being used. lol. –  Sidar Jul 18 '13 at 6:40
add comment

1 Answer

up vote 3 down vote accepted

Use data to define these things, not code.

Also, if you're using a real ECS, you don't pool individual objects, you pool components. More generic component-based design will have you pool both separately. You definitely don't need to pool Player objects separate from Bullet objects, though, since all an object is is a collection of component and a few bits/flags/metadata. Creation of these (grabbing a new empty entity and adding all the necessary components) should be cheap or you need to rethink how you're managing your components.

You should have an "archetype" or "blueprint" that defines which components a particular object has. Your level or game logic can specify additional overrides during object initialization, like position. You can make multiple sub-archetypes for your different types of static objects.

Hard-coding a CreatePlayer defeats half the purpose of component-based design the way I look at it. You should be able to easily compose new types of objects with minimal fuss, preferably from an editor (or at least a text file) without needing to recompile the whole app. Good for modders, too.

share|improve this answer
    
I was afraid I was doing something wrong on an architectural level - it's my first attempt at using ECS. So, I should compose my entities outside of the code; what do you mean by pooling components, rather than entities? –  Chaosed0 Jul 18 '13 at 1:44
1  
In an ECS you allocate all the components of a particular type together in a single data structure (an array/pool, typically). In a pure ECS there is no object to represent an entity; entities are abstract concepts materialized as a unique ID used to lookup components in their respective systems/structures. Not saying this is the best way to do things, but that is what ECS is all about. –  Sean Middleditch Jul 18 '13 at 1:51
    
If I understand you, you mean at the architectural level, I should keep track of components; Artemis (the framework I mentioned) is indeed doing that. At the level sitting on top of the framework, though, when I'm creating a particle system, shouldn't I create a pool of reusable particle entities, not a pool of components? –  Chaosed0 Jul 18 '13 at 2:06
2  
particle systems are entirely separate. you should not represent each particle as an entity. a particle system should be a dedicated data structure designed specifically for updating and drawing houndreds of thousands of particle very efficiently. –  Sean Middleditch Jul 18 '13 at 2:24
add comment

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.