Skip to main content
given the relatively high traffic of this answer (at least by my standards), i've updated class names to better reflect the example descriptions
Source Link
Stephan
  • 1.7k
  • 11
  • 25

Essentially it boils down to HashMaps and GUIDs. Each Entity is nothing more than a Globally Unique Identifier (GUID) which serves as the key in each HashMap. A HashMap exists for every ComponentType in your game. There are ways to make this more general purpose, but I'm going with the naivenaïve solution for simplicity of argument.

public class EntityEntityManager
{
  HashMap<GUID,boolean> entities =new HashMap<GUID,boolean>();

  public EntityEntityManager()
  {
  }

  public GUID createcreateEntity()
  {
      GUID entity= new GUID();
      entities.put(entity,false);
      return entity;
  }

  public HashMap<GUID,boolean> getAll()
  {
      return entities;
  }

  public void markPurge(GUID entity)
  {
      entities.put(entity, true);
  }

  public void purgeReady()
  {
      //removes all entities that have a value of true, 
      //only called once all other purges have been called
      for(GUID entity : entities)
      {
        if(entities.get(entity))
          entities.remove(entity);
      }
  }
}

Lets say the object needs health, lets start with creating a Health component. During the initialization of your game, you'd create a HashMap to register Entities that have the HealthComponentHealth Component.

public class HealthHealthComponentRegistry
{
  private HashMap<GUID,int> healths=new HashMap<GUID,int>();

  public HealthHealthComponentRegistry(){}

  public void set(GUID entity, int health)
  {
      healths.put(entity, health);
  }

  public int get(GUID entity)
  {
      return healths.get(entity);
  }

  public void remove(GUID entity)
  {
      healths.remove(entity);
  }

  public void add(GUID entity)
  {
      healths.put(entity, 100);
  }

  public void add(GUID entity, int health)
  {
      healths.put(entity, health);
  }
  
  public void purge(ArrayList<GUID> entities)
  {
    for(GUID entity : entities)
       healths.remove(entity);
  }
}
public void setup()
{
  //spawn an entity, and add a Health component in one step
  HealthHealthComponentRegistry.add(EntityEntityManager.CreatecreateEntity());
}
public class DeathSystem
{
  EntityEntityManager entities;
  HealthHealthComponentRegistry healths;
  public DeathSystem(EntityEntityManager e, HealthHealthComponentRegistry h)
  {
     entities=e;
     healths=h;
  }
  
  public void update()
  {
     for(GUID entity : health.keySet())
     {
       if(healths.get(entity)==0)
           entities.markPurge(entity);
     }
  }
}
EntityEntityManager entities;
HealthHealthComponentRegistry healthComps;
DeathSystem deathSystem;
GUID player;
boolean run = true;

public void main(String args)
{
    setup();
    while(run)
    {
      update();
    }
}

public void setup()
{
    entities= new EntityEntityManager();
    healthComps = new HealthHealthComponentRegistry();
    deathSystem = new DeathSystem(entities, healthComps);
    player=entities.create();
    healthComps.add(player);
}

public void update()
{
    handleInput();
    //attackSystem.update();
    //healSystem.update();
    deathSystem.update();
    //finally, call the function that calls purge on all the component registries to remove any destroyed objects
    purgeAll();
    if(entities.getAll().size()==0)
       run=false;
}

Essentially it boils down to HashMaps and GUIDs. Each Entity is nothing more than a Globally Unique Identifier (GUID) which serves as the key in each HashMap. A HashMap exists for every ComponentType in your game. There are ways to make this more general purpose, but I'm going with the naive solution for simplicity of argument.

public class Entity
{
  HashMap<GUID,boolean> entities =new HashMap<GUID,boolean>();

  public Entity()
  {
  }

  public GUID create()
  {
      GUID entity= new GUID();
      entities.put(entity,false);
      return entity;
  }

  public HashMap<GUID,boolean> getAll()
  {
      return entities;
  }

  public void markPurge(GUID entity)
  {
      entities.put(entity, true);
  }

  public void purgeReady()
  {
      //removes all entities that have a value of true, 
      //only called once all other purges have been called
      for(GUID entity : entities)
      {
        if(entities.get(entity))
          entities.remove(entity);
      }
  }
}

Lets say the object needs health, lets start with creating a Health component. During the initialization of your game, you'd create a HashMap to register Entities that have the HealthComponent.

public class Health
{
  private HashMap<GUID,int> healths=new HashMap<GUID,int>();

  public Health(){}

  public void set(GUID entity, int health)
  {
      healths.put(entity, health);
  }

  public int get(GUID entity)
  {
      return healths.get(entity);
  }

  public void remove(GUID entity)
  {
      healths.remove(entity);
  }

  public void add(GUID entity)
  {
      healths.put(entity, 100);
  }

  public void add(GUID entity, int health)
  {
      healths.put(entity, health);
  }
  
  public void purge(ArrayList<GUID> entities)
  {
    for(GUID entity : entities)
       healths.remove(entity);
  }
}
public void setup()
{
  //spawn an entity, and add a Health component in one step
  Health.add(Entity.Create());
}
public class DeathSystem
{
  Entity entities;
  Health healths;
  public DeathSystem(Entity e, Health h)
  {
     entities=e;
     healths=h;
  }
  
  public void update()
  {
     for(GUID entity : health.keySet())
     {
       if(healths.get(entity)==0)
           entities.markPurge(entity);
     }
  }
}
Entity entities;
Health healthComps;
DeathSystem deathSystem;
GUID player;
boolean run = true;

public void main(String args)
{
    setup();
    while(run)
    {
      update();
    }
}

public void setup()
{
    entities= new Entity();
    healthComps = new Health();
    deathSystem = new DeathSystem(entities, healthComps);
    player=entities.create();
    healthComps.add(player);
}

public void update()
{
    handleInput();
    //attackSystem.update();
    //healSystem.update();
    deathSystem.update();
    //finally, call the function that calls purge on all the component registries to remove any destroyed objects
    purgeAll();
    if(entities.getAll().size()==0)
       run=false;
}

Essentially it boils down to HashMaps and GUIDs. Each Entity is nothing more than a Globally Unique Identifier (GUID) which serves as the key in each HashMap. A HashMap exists for every ComponentType in your game. There are ways to make this more general purpose, but I'm going with the naïve solution for simplicity of argument.

public class EntityManager
{
  HashMap<GUID,boolean> entities =new HashMap<GUID,boolean>();

  public EntityManager()
  {
  }

  public GUID createEntity()
  {
      GUID entity= new GUID();
      entities.put(entity,false);
      return entity;
  }

  public HashMap<GUID,boolean> getAll()
  {
      return entities;
  }

  public void markPurge(GUID entity)
  {
      entities.put(entity, true);
  }

  public void purgeReady()
  {
      //removes all entities that have a value of true, 
      //only called once all other purges have been called
      for(GUID entity : entities)
      {
        if(entities.get(entity))
          entities.remove(entity);
      }
  }
}

Lets say the object needs health, lets start with creating a Health component. During the initialization of your game, you'd create a HashMap to register Entities that have the Health Component.

public class HealthComponentRegistry
{
  private HashMap<GUID,int> healths=new HashMap<GUID,int>();

  public HealthComponentRegistry(){}

  public void set(GUID entity, int health)
  {
      healths.put(entity, health);
  }

  public int get(GUID entity)
  {
      return healths.get(entity);
  }

  public void remove(GUID entity)
  {
      healths.remove(entity);
  }

  public void add(GUID entity)
  {
      healths.put(entity, 100);
  }

  public void add(GUID entity, int health)
  {
      healths.put(entity, health);
  }
  
  public void purge(ArrayList<GUID> entities)
  {
    for(GUID entity : entities)
       healths.remove(entity);
  }
}
public void setup()
{
  //spawn an entity, and add a Health component in one step
  HealthComponentRegistry.add(EntityManager.createEntity());
}
public class DeathSystem
{
  EntityManager entities;
  HealthComponentRegistry healths;
  public DeathSystem(EntityManager e, HealthComponentRegistry h)
  {
     entities=e;
     healths=h;
  }
  
  public void update()
  {
     for(GUID entity : health.keySet())
     {
       if(healths.get(entity)==0)
           entities.markPurge(entity);
     }
  }
}
EntityManager entities;
HealthComponentRegistry healthComps;
DeathSystem deathSystem;
GUID player;
boolean run = true;

public void main(String args)
{
    setup();
    while(run)
    {
      update();
    }
}

public void setup()
{
    entities= new EntityManager();
    healthComps = new HealthComponentRegistry();
    deathSystem = new DeathSystem(entities, healthComps);
    player=entities.create();
    healthComps.add(player);
}

public void update()
{
    handleInput();
    //attackSystem.update();
    //healSystem.update();
    deathSystem.update();
    //finally, call the function that calls purge on all the component registries to remove any destroyed objects
    purgeAll();
    if(entities.getAll().size()==0)
       run=false;
}
fixed examples to me more accurate
Source Link
Stephan
  • 1.7k
  • 11
  • 25
public class Entity
{
  HashMap<GUID,bool>boolean> entities =new HashMap<GUID,bool>boolean>();

  public Entity()
  {
  }

  public GUID create()
  {
      GUID entity= new GUID();
      entities.put(entity,false);
      return entity;
  }

  public HashMap<GUID,bool>boolean> getAll()
  {
      return entities;
  }

  public void markPurge(GUID entity)
  {
      entities.put(entity, true);
  }

  public void purgeReady()
  {
      //removes all entities that have a value of true, 
      //only called once all other purges have been called
      for(GUID entity : entities)
      {
        if(entities.get(entity))
          entities.remove(entity);
      }
  }
}
public void Startsetup()
{
  //spawn an entity, and add a Health component in one step
  Health.add(Entity.Create());
}
public class DeathSystem
{
  Entity entities;
  Health healths;
  public DeathSystem(Entity e, Health h)
  {
     entities=e;
     healths=h;
  }
  
  public void Updateupdate()
  {
     for(GUID entity : health.keySet())
     {
       if(healths.get(entity)==0)
           entities.markPurge(entity);
     }
  }
}

Now we simply call our systems in our main game loop, after handling user input. Altogether yielding the following

Entity entities;
Health healthComps;
DeathSystem deathSystem;
GUID player;
boolean run = true;

public void Updatemain(String args)
{
    HandleInputsetup();
    while(run)
    {
      update();
    }
}

public void setup()
{
    entities= new Entity();
    healthComps = new Health();
    deathSystem = new DeathSystem(entities, healthComps);
    player=entities.create();
    healthComps.add(player);
}

public void update()
{
    handleInput();
    //AttackSystemattackSystem.Updateupdate();
    //HealSystemhealSystem.Updateupdate();
    DeathSystemdeathSystem.Updateupdate();
    //finally, call the function that calls purge on all the component registries to remove any destroyed objects
    purgeAll();
    if(entities.getAll().size()==0)
       run=false;
}
public class Entity
{
  HashMap<GUID,bool> entities =new HashMap<GUID,bool>();

  public Entity()
  {
  }

  public GUID create()
  {
      GUID entity= new GUID();
      entities.put(entity,false);
      return entity;
  }

  public HashMap<GUID,bool> getAll()
  {
      return entities;
  }

  public void markPurge(GUID entity)
  {
      entities.put(entity, true);
  }

  public void purgeReady()
  {
      //removes all entities that have a value of true, 
      //only called once all other purges have been called
      for(GUID entity : entities)
      {
        if(entities.get(entity))
          entities.remove(entity);
      }
  }
}
public void Start()
{
  //spawn an entity, and add a Health component in one step
  Health.add(Entity.Create());
}
public class DeathSystem
{
  Entity entities;
  Health healths;
  public DeathSystem(Entity e, Health h)
  {
     entities=e;
     healths=h;
  }
  
  public void Update()
  {
     for(GUID entity : health.keySet())
     {
       if(healths.get(entity)==0)
           entities.markPurge(entity);
     }
  }
}

Now we simply call our systems in our main game loop, after handling user input

public void Update()
{
    HandleInput();
    //AttackSystem.Update();
    //HealSystem.Update();
    DeathSystem.Update();
    //finally, call the function that calls purge on all the component registries to remove any destroyed objects
    purgeAll();
}
public class Entity
{
  HashMap<GUID,boolean> entities =new HashMap<GUID,boolean>();

  public Entity()
  {
  }

  public GUID create()
  {
      GUID entity= new GUID();
      entities.put(entity,false);
      return entity;
  }

  public HashMap<GUID,boolean> getAll()
  {
      return entities;
  }

  public void markPurge(GUID entity)
  {
      entities.put(entity, true);
  }

  public void purgeReady()
  {
      //removes all entities that have a value of true, 
      //only called once all other purges have been called
      for(GUID entity : entities)
      {
        if(entities.get(entity))
          entities.remove(entity);
      }
  }
}
public void setup()
{
  //spawn an entity, and add a Health component in one step
  Health.add(Entity.Create());
}
public class DeathSystem
{
  Entity entities;
  Health healths;
  public DeathSystem(Entity e, Health h)
  {
     entities=e;
     healths=h;
  }
  
  public void update()
  {
     for(GUID entity : health.keySet())
     {
       if(healths.get(entity)==0)
           entities.markPurge(entity);
     }
  }
}

Now we simply call our systems in our main game loop, after handling user input. Altogether yielding the following

Entity entities;
Health healthComps;
DeathSystem deathSystem;
GUID player;
boolean run = true;

public void main(String args)
{
    setup();
    while(run)
    {
      update();
    }
}

public void setup()
{
    entities= new Entity();
    healthComps = new Health();
    deathSystem = new DeathSystem(entities, healthComps);
    player=entities.create();
    healthComps.add(player);
}

public void update()
{
    handleInput();
    //attackSystem.update();
    //healSystem.update();
    deathSystem.update();
    //finally, call the function that calls purge on all the component registries to remove any destroyed objects
    purgeAll();
    if(entities.getAll().size()==0)
       run=false;
}
typo
Source Link
Stephan
  • 1.7k
  • 11
  • 25

We first need to track existing Entities. I do this with a HasMapHashMap with a GUID as the Key, and a boolean as the Value which indicates whether or not the entity should be destroyed.

Lets say the object needs health, lets start with creating a Health component. During the initialization of your game, you'd create a HashMap to register Entities that have the Transform ComponentHealthComponent.

We first need to track existing Entities. I do this with a HasMap with a GUID as the Key, and a boolean as the Value which indicates whether or not the entity should be destroyed.

Lets say the object needs health, lets start with creating a Health component. During the initialization of your game, you'd create a HashMap to register Entities that have the Transform Component.

We first need to track existing Entities. I do this with a HashMap with a GUID as the Key, and a boolean as the Value which indicates whether or not the entity should be destroyed.

Lets say the object needs health, lets start with creating a Health component. During the initialization of your game, you'd create a HashMap to register Entities that have the HealthComponent.

Source Link
Stephan
  • 1.7k
  • 11
  • 25
Loading