Friday 21 January 2011

Tutorial 13 : Adding the Slow Tower

As a few of you have requested, I will write another tutorial on creating a custom tower type. In this tutorial I will show you how to create a tower the makes the enemies move slower when they are hit with a bullet, and hopefully by the end of this tutorial you will see how easy it is to extend the tower class to make all sorts of different towers!

For simplicities sake, I am only going to show you the changes needed to create the new tower class and not include any details about adding a new button or changing the player AddTower method (If you need help on this see Tutorial 12). However I will provide some placeholder textures that you can use for the slow tower :

slow towerslow buttonslow hoverslow pressed

So let’s begin, the first thing we are going to do is add a few new fields and properties to the Enemy class :

private float speedModifier;

private float modifierDuration;
private float modiferCurrentTime;

/// <summary>
/// Alters the speed of the enemy.
/// </summary>
public float SpeedModifier
{
get { return speedModifier; }
set { speedModifier = value; }
}
/// <summary>
/// Defines how long the speed modification will last.
/// </summary>
public float ModifierDuration
{
get { return modifierDuration; }
set
{
modifierDuration = value;
modiferCurrentTime = 0;
}
}

We will use these fields to alter the movement of the enemies. We will use these fields to alter the velocity of the enemy. So go to the Enemy Update method and find where we multiply the enemies velocity by it’s speed, and replace it with this :

Vector2 direction = waypoints.Peek() - position;
direction.Normalize();

// Store the original speed.
float temporarySpeed = speed;

// If the modifier has finished,
if (modiferCurrentTime > modifierDuration)
{
// reset the modifier.
speedModifier = 0;
modiferCurrentTime = 0;
}

if (speedModifier != 0 && modiferCurrentTime <= modifierDuration)
{
// Modify the speed of the enemy.
temporarySpeed *= speedModifier;
// Update the modifier timer.
modiferCurrentTime += (float)gameTime.ElapsedGameTime.TotalSeconds;
}

velocity = Vector2.Multiply(direction, temporarySpeed);

position += velocity;

Most of what we are doing here is the same as before, however now we are checking if the enemy has any speed modifier applied to it, and if it has, we alter it’s velocity. Also this code keeps track of how long the speed modifier has lasted and removes this modifier when it wears off.

Right, now that is out of the way, let’s create our new tower! The great thing about the slow tower is that it is basically just an Arrow Tower, only it applies a speed modifier to the enemy it is shooting.

So we can cheat a little bit here by finding “ArrowTower.cs” in the solution explorer and cloning it. You will need to rename the copy something like “SlowTower.cs”, and also you will need to go into the new file and replace wherever it says ArrowTower with SlowTower.

So now most of the work is done for us, all that is left to do is to add a few fields to keep track of the speed modifications, and to update the bullet intersection code, so let’s start by adding the follow fields to SlowTower :

// Defines how fast an enemy will move when hit.
private float speedModifier;
// Defines how long this effect will last.
private float modifierDuration;

We also need to initialize these fields in the SlowTower constructor :

this.speedModifier = 0.6f;
this.modifierDuration = 2.0f;

Next go down to the SlowTower’s Update method and find where we check if a bullet has hit the target :

if (target != null && Vector2.Distance(bullet.Center, target.Center) < 12)

And just under what is inside the if statement, add this :

// Apply our speed modifier if it is better than
// the one currently affecting the target :
if (target.SpeedModifier <= speedModifier)
{
target.SpeedModifier = speedModifier;
target.ModifierDuration = modifierDuration;
}

We will only allow an enemy to have one speed modifier acting on it – the modifier will only be applied to the enemy if it is better than the current one.

And voilĂ , we have a new type of tower, it really is that simple! There is a lot more that you could change / add to this tower :

  • This tower costs exactly the same as the arrow tower and does the same damage.

  • Maybe you think the enemy should move even slower when hit by this tower or maybe it should move slow for longer?

  • What if when an enemy is hit by this tower it is tinted a different colour to show that it has been slowed?

  • Maybe this tower should only target enemies that are moving at normal speed for maximum efficiency?

  • Or perhaps it could target more than one enemy at a time, or have a kind of “Splash” effect!

Maybe you could see how many of the above you could add to the tower to test your skills? If you have some trouble creating a button for this class, I will upload working source that shows you how to do this.

Here is the source code for this tutorial.

8 comments:

  1. Very nice tutorial again !

    Thank you very much !

    ReplyDelete
  2. I can't seem to get it to add money and take lives depending on you killing the enemy or the enemy running through the end... It won't let me create a reference of the Player class to use player.Lives or player.Money, I've created the set{} variables on each though :P

    Any ideas?

    VERY NICE TUTORIAL btw

    ReplyDelete
  3. Hey, I plan on writing a short tutorial soon on this. This was something I overlooked when creating the player class... xD

    ReplyDelete
  4. You need to do a tutorial for the game ending. And maybe a menu screen.

    ReplyDelete
  5. I was wondering, with the slow tower, you might get some enemies pass other enemies, or, if you eventually have enemies that are faster than others in the same wave.

    How can you set up the towers to target whichever enemy is closest to the end?

    ReplyDelete
  6. Hi Sean, you will need to override the GetClosestEnemy method in the SlowTower class, something like this would probably work :

    public override void GetClosestEnemy(List enemies)
    {
    target = null;

    float smallestRange = float.MaxValue;

    foreach (Enemy enemy in enemies)
    {
    if (IsInRange(enemy.Center) == false)
    {
    continue;
    }

    float distance = enemy.WaypointCount + (enemy.DistanceToDestination / 32.0f);

    if (distance < smallestRange)
    {
    smallestRange = distance;
    target = enemy;
    }
    }
    }

    ReplyDelete
  7. I have a question about the slow tower you have the code:

    // Apply our speed modifier if it is better than
    // the one currently affecting the target :
    if (target.SpeedModifier <= speedModifier){
    target.SpeedModifier = speedModifier;
    }

    Shouldn't this be the other way around, because the modifier is a factor, the smaller the better. I read this as a .6 modifier being replaced by a .9

    ReplyDelete
  8. Hey FireFly,

    I follow all of your tutos'. They're awesome. I was looking for something like this. So a big thank you ;)

    And why don't you implement the slowing effect with a Buff list ?
    Well I did it with a buff list, and this is great ;p

    Do you think you'll have the time to make more tutos? I hope so. Especially on the network multiplayer system, or how to manage titlescreen, gamescreen, and others screen ( like victory screen, etc.. ).

    Hope you'll see this comment, you didn't post since a long time..

    J.

    ReplyDelete