In my previous blog entry about entities you saw two implementation approaches. I will go into detail with the component based method, since it is the most flexible and extendable one. As stated before I suggest to use this method to avoid issues, unless you have a very small entity hierachy.
Keep in mind that the following Entity code is designed for 2D games and that I leave out encapsulation of fields and methods due to readability and performance on some devices/OS (e.g. Android).

General aspects

  • To represent your entity you have to make an Entity class, which holds an EntityComponent array, an EntityType and basic things like the position and appearance.
  • An EntityComponent is another class and is, of course, the component itself, which has effect on the Entity.
  • EntityType is a class that holds the same information for every Entity of the same type (such as Enemy or Projectile). It can hold for example: appearance, components, name, max. speed, velocity.

 

The Entity

Entity should care about very basic things and only hold information for all entities. Let´s create a simple Entity class:

public class Entity {
	public float x = 0.0f;
	public float y = 0.0f;
	public float angle = 0.0f;
	public Sprite sprite;

	public EntityComponent[] components;
	public EntityType type;

	public boolean isDead = false;

	public Entity (EntityType type) {
		this.type = type;
		this.components = type.copyComponentList(); // We´ll look into the type later
		// Construct the Sprite here (this is another topic)
	}

	public void update () {
		int i = 0;
		while (i < components.length) {
			components[i].update(this);
			i++;
		}
	}
}

Some notes:
  • the constructor takes an EntityType as a parameter to initialize the Entity. It copies the EntityComponents of the type and creates an appearance (Sprite).
  • update() loops through the EntityComponent array to update the components.
  • isDead shows if the Entity is no longer used, so that it can be destroyed by the update loop.

Before we go on and write our first EntityComponent we will have a look at the EntityType.

 

Writing the EntityType class

An EntityType holds all information of an Entity, which type has this information in common. Imagine two EntityTypes: Enemy and Projectile. These can both be Entities, but they have a different appearance, different components, a different name and also a different speed. You can see, that storing this information in Entity would be overflow, since it is the same for maybe 100 projectiles. To avoid this we use the type.

Let´s define Enemy and Projectile (I´ll leave out the appearance):

  • Projectile:
    Components: Moveable, Projectile, Collideable
    Name: Projectile
    Speed: 200 pixel/s
  • Enemy:
    Components: Moveable, Collideable
    Name: Enemy
    Speed: 35 pixel/s

To define these types you can choose different methods. One method is to define EntityType in the code itself, another famous approach is to define all entities in files, which are loaded on startup. I´ll choose the first method, since we want to keep it simple. If you develop bigger games, the second method will be yours, because non-programmers can design entities with this method and you can implement an editor (Like the editor in Starcraft 2) to allow users to make their own entities.

So, let´s write the EntityType class:

public class EntityType {

	// The types we will use; Projectile and Enemy
	public static EntityType TYPE_PROJECTILE = new EntityType(new EntityComponent[] { new EntityComponentMoveable(200, 200), new EntityComponentCollideable(), new EntityComponentProjectile()}, "Projectile");
	public static EntityType TYPE_ENEMY = new EntityType(new EntityComponent[] { new EntityComponentMoveable(35, 35), new EntityComponentCollideable()}, "Enemy");

	public EntityComponent[] componentList; // The list that will be copied
	public String name;

	public EntityType (EntityComponent[] componentList, String name) {
		this.componentList = componentList;
		this.name = name;
	}

	// Copy the whole array
	public EntityComponent[] copyComponentList () {
		EntityComponent[] comp = new EntityComponent[componentList.length];

		int i = 0;
		while (i < comp.length) {
			comp[i] = componentList[i].copy(); // Copy it from the list
			i++;
		}

		return comp;
	}
}

This type class is, of course, very basic and leaves out any graphics related content, width and height. I will write another post about collision with those two types; We will now stick to the EntityComponentMoveable component and see how this works.

 

Finally the component

First we have to write the basic EntityComponent class. It is an abstract class, since it doesn’t do anything stand-alone.

public abstract class EntityComponent {
	public abstract void update (Entity e);
	public abstract EntityComponent copy ();
}

It just has an update(Entity e) and a copy() method, can’t be instanciated because of abstract and does not do anything. But we want to do something with those components, so let’s write the EntityComponentMoveable:

public class EntityComponentMoveable extends EntityComponent {

	public float speedX;
	public float speedY;

	public EntityComponentMoveable (float speedX, float speedY) {
		this.speedX = speedX;
		this.speedY = speedY;
	}

	@Override
	public void update(Entity e) {
		e.x += (float) Math.sin(Math.toRadian(e.angle)) * speedX * delta; // Use your delta time. It has to be in seconds.
		e.y += (float) Math.cos(Math.toRadian(e.angle)) * speedY * delta; // You should also be familiar with this formula.
	}

	public EntityComponent copy () {
		return this;
	}

}

Please note that making a new EntityComponent in the copy() method is not required, since the speed is fixed to an EntityType in this case and there is one object per type on initialisation.

And this is what happens overall:

  1. We create a type which has an EntityComponent array.
  2. When we create an Entity we pass any type to the Entity constructor and the EntityComponent array is copied.
  3. Each update the Entity updates the EntityComponentMoveable which moves the Entity based on speed.

I hope this post showed you clearly how to implement a component based entity structure. I will write more about this and my next post will be most likely about collision.

Advertisements