# How can I specify which enemies to spawn for each round in a tower defense?

I am making a TD game in Unity, and I would like to know the most common approach to spawning enemies each round. I have more than 200 rounds per map, just like Fieldrunners.

Is it some kind of hardcoding, say for 25 rounds and then repeat the same waves with harder enemies, or maybe logic/algorithm based on rounds, where it'll give number of enemies and type of enemies which will spawn in that round.

I have 8 type of enemies. I want to implement a function/equation which inputs round number and outputs "number of enemies" and "enemy type" keeping the difficulty level which is round numbers.

for e.g if input: 50th round, output: enemy type1, large no. of enemies, if the input: 2nd round, output: enemy type 1, less number of enemies

• a balanced TD game is always hard coded. you will realize after playing top TD games. – Noob Game Developer Jul 25 '12 at 13:47

Well, it depends on your choice of the game dynamics. You can opt to hard-code whatever sequence/level of enemies you want to dish out to the player, or you could have an adaptive controller that uses its AI to take the game to a challenging level, no matter how expert you are. Say, player A completes the first (perhaps hard-coded) level in 2 minutes, taking no damage. Your AI takes the time used to clear up the level, and the damage taken in the level (make up a simple formula using these two or perhaps other game variables) and then take the result to set the subsequent level enemy's health, armor etc.

Say, number of enemies in round n = ((n * 50)/time taken to complete level[n-1]) - (30 * damage taken)

So, our great player A completes the level in 2 minutes, no damage taken: no. of enemies for level two: ((2 *50)/2) - (30 *0) = 50 enemies

You can use a similar scheme for health, armor, speed etc.

As far as the types of enemies is concerned, I'll answer that later, I have a class scheduled to begin in 20 minutes :D

Here is how I do it:

I have a method named setupWave which initiates a round or wave:

- (void) setupWave {
// remainingCount is the number of enemies that will be spawned in the current wave
remainingCount              =   (int)((((waveCount + 1)/2.0) + ((gameDifficulty + 1)/1.5)) * 3);
// dieCount is used to find when the wave ends
dieCount                    =   remainingCount;

[self                           stepAI];
}


this method stepAI creates an enemy and calls itself after a delay till the remainingCount != 0

- (void) stepAI {

// code to initialize the enemy object goes here

// you can adjust the enemy parameters like health, range, etc., based on current wave as below:
tmpAttacker.maxHealth       =   BASEHP + (BASEHP / 10.0) * waveCount;

remainingCount--;

// calls the stepAI again after some delay to spawn next enemy, until remainingCount reaches 0
if (remainingCount > 0) {
[self runAction:[CCSequence actions:
[CCDelayTime actionWithDuration:TIMEBETWEENUNITS], //for delay
[CCCallFunc actionWithTarget:self selector:@selector(stepAI)], //calls itself again
nil]];
}
}


this method gets invoked when the enemy dies:

- (void) attacker:(id)sender diedWhile:(AttackerState)tState {
dieCount--;

// if the die count reaches 0, that is after all the enemies in current wave are dead,
// initiate the next wave after some delay
if (dieCount == 0) {
waveCount++;
[self runAction:[CCSequence actions:
[CCDelayTime actionWithDuration:TIMEBETWEENWAVES], // for delay
[CCCallFunc actionWithTarget:self selector:@selector(setupWave)],
nil]];
}


All the coding is in Objective-C, I will change into pseudo code, if this is harder to understand.

There are different approaches to this. The one where you (as the game-designer) have most control, would be to define the exact types and amount of enemies for each round.

Of course you can also make this range based (to save you from defining each round separately), so basically:

• round 01 - 10: Spawn 10 x enemyA and 5 x enemyB
• round 11 - 20: Spawn 10 x enemyB and 5 x enemyC
• etc.

However, this type of ranged-based spawning won't provide much variation. Another approach would be based on probabilities (or weights). Something like:

• enemyA (ground) has weight 1.0 at round 1, 0.5 at round 10 and 0.0 at round 20
• enemyB (flyer) has weight 0.0 up to round 11, 1.0 at round 12 and 0.0 at round 13

Then you interpolate the weight given the current round. So with the above definition, enemyA has a weight of 0.75 at round 5.

Given the amount of enemies to spawn per round (you might want to ramp this up for later rounds) you can determine the unit mix by the given weights. As you can see, you can also make enemies appear only in one round (as shown with enemyB). If you design this carefully, you should be able to control the distribution of enemies nicely (and with good variations) without having to hard-code each round.

• I like the interpolation method. – David Gouveia Dec 13 '11 at 16:29