Design In-game Entities. Object Composition Strategies. Part 1 – The Strategy Pattern

In this part I will try to explain what I understand on good game design elements.
I will use droids in the examples and I will script a basic fight simulator to see how they behave.

The problem:

I command a single robot and I want to obliterate my enemies. To face the same type of enemy all over again is boring. I need new challenges and this means new types of enemies. For example in the first level I want only to practice my target. So I need a pretty dumb enemy that does not do much but takes the shots. After I mastered that skill (shooting a helpless droid), I need a bit of a challenge and I want the enemy droid to fight back, but because I am still a beginner I don’t want to die quickly so I need weak droids. After I am over with them I want a tougher challenge. I need better and stronger droids. Not just stronger, but different in behaviour as well as it can get boring killing the same type of enemy over and over again.

The obvious solution:

Create 3 classes for the 3 types of enemy droids. To keep it simple, each droid has 2 abilities: move and attack. It makes sense to create a Droid interface with these two methods and have each droid implement them.

They can move and shoot. Well, not all of them but we can provide an empty implementation for the ones that do nothing.

The droid types:
  • Decoy Droid – will have no weapon and can’t move.
  • Scout Droid – will have a weak weapon and moves fast.
  • Assault Droid - will have a heavy weapon and moves slowly.

Looking at the 3 types we can implement the following simple class diagram:

Implementing the Droid interface

The interface has 3 simple methods which the droids need to implement:

public interface Droid {

	// display some info of the droid
	public void display();
	
	// move the droid
	public void move(int x, int y);
	
	// attack position
	public void shoot(int x, int y);
}

The 3 classes are as follow:

DecoyDroid.java

public class DecoyDroid implements Droid {

	@Override
	public void display() {
		System.out.println("I am a DECOY droid");
	}
		@Override
	public void move(int x, int y) {
		System.out.println("Can't move.");
	}

	@Override
	public void shoot(int x, int y) {
		System.out.println("Have no weapon.");
	}
}

ScoutDroid.java

public class ScoutDroid implements Droid {

	private float damage = 0.5f;
	
	@Override
	public void display() {
		System.out.println("I am a scout droid");
	}
	
	@Override
	public void move(int x, int y) {
		System.out.println("Moving QUICKLY to: " + x + "," + y + ".");
	}

	@Override
	public void shoot(int x, int y) {
		System.out.println("Light Laser Canon targeting: " + x + "," + y
				+ ". Damage: " + damage);
	}
}

AssaultDroid.java

public class AssaultDroid implements Droid {

	private float 	damage = 2.5f;
	private boolean loaded = true;
	
	@Override
	public void display() {
		System.out.println("I am an ASSAULT droid");
	}
	
	@Override
	public void move(int x, int y) {
		System.out.println("Moving SLOWLY to: " + x + "," + y + ".");
	}

	@Override
	public void shoot(int x, int y) {
		if (loaded) {
			System.out.println("Heavy laser targeting: " + x + "," + y
					+ ". Damage: " + damage);
			loaded = false;
		} else {
			System.out.println("Reloading...");
			loaded = true;
		}
	}
}

Both ScoutDroid and AssaultDroid have the argument damage. This holds the value of the damage inflicted by them.

To give the AssaultDroid a heavy weapon with a slow reload time we added the loaded variable. This way it takes the assault droid two turns to fire its weapon once.

I have created a simple simulator for the droids to take turns to move and shoot.
Run the simulator for this design:

BadDroidSimulator.java

public class BadDroidSimulator {

	public static void main(String[] args) {
		// for generating random numbers
		Random rand = new Random();
		
		Droid scout = new ScoutDroid();
		Droid assailant = new AssaultDroid();
		Droid decoy = new DecoyDroid();
		
		scout.display();
		assailant.display();
		decoy.display();
		
		// shoot-out - each droid fires once per turn
		for (int i = 1; i <= 5; i++) {
			System.out.println("\n<=== BEGIN TURN " + i + " ===>");
			scout.shoot(rand.nextInt(10), rand.nextInt(10));	// we assume this is an enemy position
			scout.move(rand.nextInt(10), rand.nextInt(10));
			System.out.println();
			assailant.shoot(rand.nextInt(10), rand.nextInt(10));
			assailant.move(rand.nextInt(10), rand.nextInt(10));
			System.out.println();
			decoy.shoot(rand.nextInt(10), rand.nextInt(10));
			decoy.move(rand.nextInt(10), rand.nextInt(10));
			System.out.println("<=== END TURN " + i + " ===>");
		}
	}
}

The result (console output) will look like this:

I am a scout droid
I am an ASSAULT droid
I am a DECOY droid

<=== BEGIN TURN 1 ===>
Light Laser Canon targeting: 9,0. Damage: 0.5
Moving QUICKLY to: 4,6.

Heavy laser targeting: 6,2. Damage: 2.5
Moving SLOWLY to: 9,1.

Have no weapon.
Can’t move.
<=== END TURN 1 ===>

<=== BEGIN TURN 2 ===>
Light Laser Canon targeting: 3,4. Damage: 0.5
Moving QUICKLY to: 6,5.

Reloading…
Moving SLOWLY to: 1,6.

Have no weapon.
Can’t move.
<=== END TURN 2 ===>

<=== BEGIN TURN 3 ===>
Light Laser Canon targeting: 6,7. Damage: 0.5
Moving QUICKLY to: 9,7.

Heavy laser targeting: 7,1. Damage: 2.5
Moving SLOWLY to: 2,0.

Have no weapon.
Can’t move.
<=== END TURN 3 ===>

<=== BEGIN TURN 4 ===>
Light Laser Canon targeting: 3,7. Damage: 0.5
Moving QUICKLY to: 1,4.

Reloading…
Moving SLOWLY to: 5,9.

Have no weapon.
Can’t move.
<=== END TURN 4 ===>

<=== BEGIN TURN 5 ===>
Light Laser Canon targeting: 0,8. Damage: 0.5
Moving QUICKLY to: 3,9.

Heavy laser targeting: 1,2. Damage: 2.5
Moving SLOWLY to: 3,2.

Have no weapon.
Can’t move.
<=== END TURN 5 ===>


Challenges to extend the design

The droids take turns to move and shoot. This is all good, but:

  • What if you want to create a hybrid droid? A droid that moves as fast as the scout but with a heavy weapon?
    You will have to create a new class and copy paste the respective methods from the Scout and Assault droid, right?
  • Also imagine that the shooting mechanism is not that simple and it needs collision detection and so on. For each droid the same redundant code needs to be rewritten.
  • What if the fire power could be enhanced with power ups?
  • What if the droid gains self-conscientiousness and finds a weapon to use it instead of the current one?

I am sure you have plenty ideas on how to enhance the gameplay and extend the world but the most obvious solution (described above) seems ill-suited for this. It requires new droid classes to be created and each droid type will implement its methods separately. Many of these methods are identical. The current design doesn’t allow you to change the droid’s internals at runtime without significant effort.

Here is one proposed solution: Composition and the Strategy Pattern.

Designing a Droid (properly)

A very simple droid consists of a weapon put on a chassis. The first design consisted of a “is a” type relationship. A ScoutDroid is a generic Droid with some peculiarities.
Composition is based on “has a” relationships.
A Droid has a Chassis. A Droid has a Weapon. What type of components a droid has, determines its type.

Let’s decompose the Scout Droid for example.
The Scout Droid is a Droid which has a Light Laser Canon has a set of Wheels to move. We want to make the scout move quickly with a light weapon.
The Assault Droid on the other hand is a Droid too but it has a Heavy Laser Canon and it runs on Tracks. This makes it extremely powerful but a bit slow.

Think from a factory perspective. How does a car production line work? You get the chassis with a specific place for the engine, wheels, drive-shaft, gear-box and so on.
All these components are produced separately. The teams that produce them have no idea of the other parts. They must fulfil one criteria: the gearbox must fit in perfectly in its place and connected up with the engine.. Different makes have different ways of doing this. The connector in this instance is the interface.
The engine has a similar story. If it hooks up nicely with the wheels and gearbox then it can be fitted. Its internal design, capacity, power, fuel consumption can be completely different. The engine is one of the car’s components.

So is our droid. But to keep it simple we have only 2 components. We need one generic droid that has all the wirings built so its components will be triggered by the droid through those interfaces. For example a droid needs to only pull the trigger of the weapon and doesn’t care what type of weapon it is as long as it has a trigger. The droid needs to understand the pullTrigger method and to do this it needs to be implemented, in order for us to give weapons to the droid to use.
The same thing with the changing of location. It needs to trigger the movement. The wheels or track or anti-gravity propulsion will take the droid there. The droid only needs to set the coordinates.

To fulfil this we need a class with implemented methods instead of an interface.
We create the abstract Droid class. We make it abstract because we actually implement the methods that trigger the weapon, and action the moving mechanism but we don’t have concrete weapons and movement mechanisms attached to the droid. The assembly of a concrete droid will be delegated to the type constructor along with the description method.

public abstract class Droid {

	protected Weapon 	weapon;		// the weapon which will be used in fights
	protected Chassis	chassis;	// the chassis on which the droid is placed

	public void moveToPosition(int x, int y) {
		System.out.print(id + " > " );
		chassis.moveTo(x, y);
	}
	
	/**
	 *  Engages the position on the screen whether it is occupied by
	 *  an enemy or not. Each strategy should decide how to do it. 
	 */ 
	public void attackPosition(int x, int y) {
		System.out.print(id + " > ");
		weapon.useWeapon(new Vector2f(x, y));
	}
	
	/**
	 * Displays some info on the droid
	 */
	public abstract void display();
}

If you examine the class you will see that the Droid has 3 methods from which 2 are implemented. It also has two components: Weapon and Chassis.
The components are interfaces so the droid does not know what it is doing when triggering the actions on them. It is all delegated to the implementation.

The interfaces are as follows:

Weapon.java

public interface Weapon {
	/**
	 * The trigger to use the weapon.
	 * @param target - where on the map is the target
	 */
	public void useWeapon(Vector2f target);
	
	/**
	 * Returns the description of the weapon
	 */
	public String getDescription();
}

Chassis.java

public interface Chassis {
	/**
	 * Delegates the movement to the supporting chassis and
	 * tries to move the unit to x,y
	 */
	public void moveTo(int x, int y);
	
	/**
	 * Returns the description of the chassis
	 */
	public String getDescription();
}

We will enhance our base Droid class. We will add setter and getter methods for both Weapon and Chassis. This will allow us to change the droid’s behaviour at runtime. This is what the strategy pattern is all about. A Droid has behaviours: it can use a weapon and it can move. These two strategies (behaviours) need to be implemented.

We also add an id which will be unique in our game for each droid instance. I use a very simple id generation strategy. I increment the nextId static field and append it to the concrete droid type prefix in the constructor for each type.

Here is the new Droid class:


public abstract class Droid {

	protected static int nextId	= 0;	// the next available ID

	protected String 	id;			// unique id
	protected Weapon 	weapon;		// the weapon which will be used in fights
	protected Chassis	chassis;	// the chassis on which the droid is placed

	// the unique ID of the droid in the game
	public String getId() {
		return id;
	}
	
	public Weapon getWeapon() {
		return weapon;
	}
	public void setWeapon(Weapon weapon) {
		this.weapon = weapon;
	}
	
	public Chassis getChassis() {
		return chassis;
	}
	public void setChassis(Chassis chassis) {
		this.chassis = chassis;
	}
	
	public void moveToPosition(int x, int y) {
		System.out.print(id + " > " );
		chassis.moveTo(x, y);
	}
	
	/**
	 *  Engages the position on the screen whether it is occupied by
	 *  an enemy or not. Each strategy should decide how to do it. 
	 */ 
	public void attackPosition(int x, int y) {
		System.out.print(id + " > ");
		weapon.useWeapon(new Vector2f(x, y));
	}
	
	/**
	 * Displays some info on the droid
	 */
	public abstract void display();
}

Let’s build some weapons

NoWeapon.java

/**
 * This is a null object. A null object is a dummy that does nothing and it 
 * is a mere place-holder and eliminates the need to check for null.
 * @author impaler
 *
 */
public class NoWeapon implements Weapon {

	@Override
	public void useWeapon(Vector2f target) {
		// We are doing nothing
		System.out.println("No weapon equipped!");
	}

	@Override
	public String getDescription() {
		return "Nothing";
	}
}

This is the null object. The class description should give you an idea what it is.

LightLaserCanon.java


/**
 * This is a light laser cannon whit a quick reload time and high accuracy
 * 
 * @author impaler
 * 
 */
public class LightLaserCanon implements Weapon {

	private float damage = 0.5f; // the damage inflicted

	@Override
	public void useWeapon(Vector2f target) {
		System.out.println("Shooting my laser canon to " + (int)target.getX() + ","
				+ (int)target.getY() + ". Bang on! Done " + damage + " damage.");
	}

	@Override
	public String getDescription() {
		return "First generation laser canon. Street use only!";
	}
}

HeavyLaserCanon.java


/**
 * This is a heavy assault laser cannon with high accuracy but slow reload time.
 * @author impaler
 */
public class HeavyLaserCanon implements Weapon {

	private boolean loaded 	= true;	// after fire needs to be reloaded
	private float 	damage 	= 1.5f;	// the damage is considerable
	
	@Override
	public void useWeapon(Vector2f target) {
		if (loaded) {
			// we fire the canon
			System.out.println("Eat this! Laser beam hit target (" + (int)target.getX() + "," + (int)target.getY() + ") and dealt " + damage + " damage.");
			// next time needs reloading
			loaded = false;
		} else {
			System.out.println("Darn! Out of ammo! Reloading...");
			loaded = true;
		}
	}

	@Override
	public String getDescription() {
		return "DASS-5000 - The ultimate in siege weaponry provided by Obviam Enterprises.";
	}
}

You might notice the Vector2f class. This is a very basic 2D vector class which currently holds the x and y coordinates. Nothing more. You can find it in the downloaded source.

Let’s build some chassis

The getDescription() method says what the chassis is like.

NoChassis.java – null object (see weapons)


public class NoChassis implements Chassis {

	@Override
	public void moveTo(int x, int y) {
		System.out.println("It's just a frame. Can't move.");
	}

	@Override
	public String getDescription() {
		return "It's just a frame.";
	}
}

SteelStand.java


public class SteelStand implements Chassis {

	@Override
	public void moveTo(int x, int y) {
		System.out.println("Can't move.");
	}

	@Override
	public String getDescription() {
		return "Unmovable reinforced steel stand ideal for turrets and defensive units.";
	}
}

Wheels.java

public class Wheels implements Chassis {

	@Override
	public void moveTo(int x, int y) {
		System.out.println("Speeding to " + x + "," + y + " on my wheels!");
	}

	@Override
	public String getDescription() {
		return "4 wheel drive, very fast on flat terrain but struggling through obstacles.";
	}
}

Track.java

public class Track implements Chassis {

	@Override
	public void moveTo(int x, int y) {
		System.out.println("Don't get in my way! Moving slowly to: " + x + "," + y + ".");
	}

	@Override
	public String getDescription() {
		return "Slow moving tracks but able to go through many obstacles.";
	}
}

Now we can assemble our droids

First let’s create a DecoyDroid. This droid will have no weapon and will be placed on a steel stand. It’s for our target practice, remember?

DecoyDroid.java

public class DecoyDroid extends Droid {

	public DecoyDroid() {
		id = "DCY-" + (++Droid.nextId); 
		weapon = new NoWeapon();
		chassis = new SteelStand();
	}
	
	@Override
	public void display() {
		System.out.println("+--------------------------------------------------------------------------------------------+");
		System.out.println("| I am a DECOY droid.");
		System.out.println("|\tID: " + id);
		System.out.println("|\tWeapon: " + weapon.getDescription());
		System.out.println("|\tChassis: " + chassis.getDescription());
		System.out.println("+--------------------------------------------------------------------------------------------+");
	}
}

Examine the default constructor. It creates an id and assigns an instance of NoWeapon and SteelStand to the droid.
The display() method is more elaborate than before but just to describe the droid better. It makes use of the components’ descriptions too.
If you instantiate a DecoyDroid and call its display method you will get a nice description of it.

+——————————————————————————————–+
| I am a DECOY droid.
| ID: DCY-3
| Weapon: Nothing
| Chassis: Unmovable reinforced steel stand ideal for turrets and defensive units.
+——————————————————————————————–+

Let’s build the rest of the types:

ScoutDroid.java

public class ScoutDroid extends Droid {

	public ScoutDroid() {
		id = "SCT-" + (++Droid.nextId); 
		weapon = new LightLaserCanon();
		chassis = new Wheels();
	}

	@Override
	public void display() {
		System.out.println("+--------------------------------------------------------------------------------------------+");
		System.out.println("| I am a SCOUT droid.");
		System.out.println("|\tID: " + id);
		System.out.println("|\tWeapon: " + weapon.getDescription());
		System.out.println("|\tChassis: " + chassis.getDescription());
		System.out.println("+--------------------------------------------------------------------------------------------+");
	}
}

AssaultDroid.java

public class AssaultDroid extends Droid {

	public AssaultDroid() {
		id = "ASS-" + (++Droid.nextId); 
		weapon = new HeavyLaserCanon();
		chassis = new Track();
	}
	
	@Override
	public void display() {
		System.out.println("+--------------------------------------------------------------------------------------------+");
		System.out.println("| I am an ASSAULT droid.");
		System.out.println("|\tID: " + id);
		System.out.println("|\tWeapon: " + weapon.getDescription());
		System.out.println("|\tChassis: " + chassis.getDescription());
		System.out.println("+--------------------------------------------------------------------------------------------+");
	}
}

You will notice that the only things needed to be implemented are the constructor – which adds the chassis and weapon – and the display() method.

The following diagram shows the new architecture:

Strategy Pattern

Let’s create a test script for it. We’ll simulate 5 turns in which each droid will use its weapon and move to a random location.
Check the behaviour of each weapon and you will notice that the heavy laser will fire once every 2 turns.
To make it interesting, in turn 4 we give a HeavyLaserCanon to DecoyDroid. Look at how it changes the droid’s behaviour and it starts firing. This is a hybrid droid created on the fly at runtime.

The simulator code (DroidSimulato.javar):

public class DroidSimulator {

	public static void main(String[] args) {
		// for generating random numbers
		Random rand = new Random();
		
		Droid scout = new ScoutDroid();
		Droid assailant = new AssaultDroid();
		Droid decoy = new DecoyDroid();
		
		scout.display();
		assailant.display();
		decoy.display();
		
		// shoot-out - each droid fires once per turn
		for (int i = 1; i <= 5; i++) {
			System.out.println("\n<=== BEGIN TURN " + i + " ===>");
			// in turn 3 decoy droid is given an assault canon
			if (i == 4) {
				decoy.setWeapon(new HeavyLaserCanon());
				System.out.println("* " + decoy.getId() + " acquired " + decoy.getWeapon().getDescription() + "\n");
			}
			scout.attackPosition(rand.nextInt(10), rand.nextInt(10));	// we assume this is an enemy position
			scout.moveToPosition(rand.nextInt(10), rand.nextInt(10));
			System.out.println();
			assailant.attackPosition(rand.nextInt(10), rand.nextInt(10));
			assailant.moveToPosition(rand.nextInt(10), rand.nextInt(10));
			System.out.println();
			decoy.attackPosition(rand.nextInt(10), rand.nextInt(10));
			decoy.moveToPosition(rand.nextInt(10), rand.nextInt(10));
			System.out.println("<=== END TURN " + i + " ===>");
		}
	}
}

The output:

+——————————————————————————————–+
| I am a SCOUT droid.
| ID: SCT-1
| Weapon: First generation laser canon. Street use only!
| Chassis: 4 wheel drive, very fast on flat terrain but struggling through obstacles.
+——————————————————————————————–+
+——————————————————————————————–+
| I am an ASSAULT droid.
| ID: ASS-2
| Weapon: DASS-5000 – The ultimate in siege weaponry provided by Obviam Enterprises.
| Chassis: Slow moving tracks but able to go through many obstacles.
+——————————————————————————————–+
+——————————————————————————————–+
| I am a DECOY droid.
| ID: DCY-3
| Weapon: Nothing
| Chassis: Unmovable reinforced steel stand ideal for turrets and defensive units.
+——————————————————————————————–+

<=== BEGIN TURN 1 ===>
SCT-1 > Shooting my laser canon to 0,3. Bang on! Done 0.5 damage.
SCT-1 > Speeding to 0,2 on my wheels!

ASS-2 > Eat this! Laser beam hit target (3,4) and dealt 1.5 damage.
ASS-2 > Don’t get in my way! Moving slowly to: 3,8.

DCY-3 > No weapon equipped!
DCY-3 > Can’t move.
<=== END TURN 1 ===>

<=== BEGIN TURN 2 ===>
SCT-1 > Shooting my laser canon to 4,0. Bang on! Done 0.5 damage.
SCT-1 > Speeding to 5,0 on my wheels!

ASS-2 > Darn! Out of ammo! Reloading…
ASS-2 > Don’t get in my way! Moving slowly to: 1,6.

DCY-3 > No weapon equipped!
DCY-3 > Can’t move.
<=== END TURN 2 ===>

<=== BEGIN TURN 3 ===>
SCT-1 > Shooting my laser canon to 3,0. Bang on! Done 0.5 damage.
SCT-1 > Speeding to 0,6 on my wheels!

ASS-2 > Eat this! Laser beam hit target (9,1) and dealt 1.5 damage.
ASS-2 > Don’t get in my way! Moving slowly to: 8,0.

DCY-3 > No weapon equipped!
DCY-3 > Can’t move.
<=== END TURN 3 ===>

<=== BEGIN TURN 4 ===>
* DCY-3 acquired DASS-5000 – The ultimate in siege weaponry provided by Obviam Enterprises.

SCT-1 > Shooting my laser canon to 8,6. Bang on! Done 0.5 damage.
SCT-1 > Speeding to 2,3 on my wheels!

ASS-2 > Darn! Out of ammo! Reloading…
ASS-2 > Don’t get in my way! Moving slowly to: 0,6.

DCY-3 > Eat this! Laser beam hit target (9,4) and dealt 1.5 damage.
DCY-3 > Can’t move.
<=== END TURN 4 ===>

<=== BEGIN TURN 5 ===>
SCT-1 > Shooting my laser canon to 1,7. Bang on! Done 0.5 damage.
SCT-1 > Speeding to 1,9 on my wheels!

ASS-2 > Eat this! Laser beam hit target (1,4) and dealt 1.5 damage.
ASS-2 > Don’t get in my way! Moving slowly to: 3,6.

DCY-3 > Darn! Out of ammo! Reloading…
DCY-3 > Can’t move.
<=== END TURN 5 ===>

Note in turn 4 how DecoyDroid got the new weapon and changed its behaviour (the yellow line). Now you should understand the null object pattern as well.

As it stands now, it is easy to create new weapons, chassis and droids by keeping the code to a minimum. Always favour composition over inheritance in these situations.
You can create a very elaborate droid, with shields, sensors, an array of weapons and also an AI component which decides what weapons to use according to the situation. If you have noticed, I used the term “use” instead of fire, because a weapon can be a melee one too and not necessarily a ranged weapon.

The downloadable project contains only the strategy pattern implementation. The simple inheritance approach is left out. Play with it and get the grips of this useful pattern as I will use it extensively and it is considered good design. It is a simple Java application, it is not Android enabled.

In the following parts I’ll try to add some AI capabilities and how to compose the final droid from images of its components.

LinkedInRedditTumblrDiggTechnorati FavoritesShare

13 Responses - Add Yours+

  1. Gamer says:

    Well-done Great tutorial for the beginners ………..
    Thanks and Keep it up……..

  2. J says:

    Love it.

    One thing I noticed, you never declare noWeapon/noChassis/etc at the top of Droid. Possibly due to showing off noWeapon in DecoyDroid. (and that was great for explaining) But I thought a cool follow up would be showing this.

    [Droid.java]
    protected Weapon weapon;

    If you forget to tell the actual droids down the line all the things they do not have when you create it, and it decides to use its ‘pretend’ whatever … Crash.

    But if it was this…

    [Droid.java]
    protected Weapon weapon = new noWeapon();

    It makes having lots of components easy, especially when your only using a few. Now you can tell the new ‘Cannon Droid’ it has a cannon and if you forget to make it mobile, and it tries to move, it will not crash. (If you changed chassis as well.)

  3. [...] to create more views without affecting the game engine. To read more on why is a good idea check this and [...]

  4. swirve says:

    What would be the best way to implement, multiple weapons onto a droid (say a super droid, firing all in unison), lasers of different strength types for say the assault laser.

    Also good tutorial :)

    • Impaler says:

      You can create a super weapon that has a list of weapons.
      When you fire the super weapon, you simply iterate through the list of weapons (contained in the super weapon) and fire them individually.
      This way you will have created just another weapon and made no changes to the design.
      It’s like a multiplexer.

  5. Jason says:

    Great tutorial for beginners to the concept of GOC. To expand upon this idea, you can create a single base for all types of game objects that has a list of components. When you want to create a new game object, you simply write a function in which creates a new instance of the base object, assigns it components and sets the data for each component, then returns it. The tricky part in my opinion, is deciding what components you need to create. For example, what if you wanted to use the above method to create weapons from a generic base class? What components should it have? Maybe a component that fires projectiles, another that deals with reloading, another that deals with handling ammo pickups.. but then, you could also as easily extend the base object and wrap this functionality into various base weapon classes and new weapons can be created by simply altering the data and or maybe changing the type of projectile it may fire, for example. Many ways to do this..I’m still struggling myself to find the approach I deem “best” for my needs.

  6. Nithin says:

    Great job. All your posts are very informative and simple to understand.

  7. Rakesh says:

    Nice Work, really very well explained!

  8. Adnan says:

    Very good article ……simple awesome i need it and i found it at the right time ……hard work need appreciation and u do a good job

  9. Trojborg says:

    Very well written. You’ve made an, imo, hard subject easy to understand.

    Your articles are much appriciated!

    Kind regards,

  10. Andrew says:

    I remember having a bash at game development on my old Sony Ericsson and not understansding the whole classes concept. The MIDP API that was currently being used for game development simplified alot, and I managed to get a walking jumping animation on the screen with no background. I gave up after that…

    3 years later and with a bit of PHP class knowledge under my belt, this has become alot easier to digest. Thank you for all these tutorials, I hope your next one is on input. Your the best site I have read on the web so far.

  11. Beton says:

    Amazing article. I have done a lot of on/off programming for the past year, but only at a basic level. Your explanations made understanding how to use interfaces and abstract classes easy and straightforward. Cant believe i haven’t used them before when they’re so convenient!

    Thanks, and keep up the good work! :)

  12. Kratos says:

    Very concise, props to you!

Leave a Reply

You must be logged in to post a comment.