Now that we have something to shoot at, I think it is about time that we start adding in the “Tower” part of our Tower Defence. We will start off by creating a simple base class for the tower and getting it drawn, then we will move on to making it aim at our enemy. I will be leaving shooting, and placement of towers till next time. So, lets begin!
Start off by adding a new class to the project called “Tower.cs”, and make it inherit from the Sprite class :
public class Tower : Sprite
{
}
protected int cost; // How much will the tower cost to make
protected int damage; // The damage done to enemy's
protected float radius; // How far the tower can shoot
public int Cost
{
get { return cost; }
}
public int Damage
{
get { return damage; }
}
public float Radius
{
get { return radius; }
}
public Tower(Texture2D texture, Vector2 position)
: base(texture, position)
{
}
And that’s the basics done, go back into Game1.cs and add the following field :
Tower tower;
Texture2D towerTexture = Content.Load<Texture2D>("arrow tower");
tower = new Tower(towerTexture, Vector2.Zero);
All this code does is create a shiny new tower in the top left corner of our screen, using the texture we just added.
tower.Draw(spriteBatch);
Now if you run the project you should see something like this :
Now we have our tower drawn, we can move on to something slightly more interesting, making the tower aim,
To start with we are going to give our a bigger range just for testing purposes, so go into Tower.cs and in the constructor add the following :
radius = 1000;
public bool IsInRange(Vector2 position)
{
if (Vector2.Distance(center, position) <= radius)
return true;
return false;
}
Before we add that we need one more field and property to store the enemy we are targeting. Add this to the top of Tower.cs :
protected Enemy target;
public Enemy Target
{
get { return target; }
}
public void GetClosestEnemy(List<Enemy> enemies)
{
target = null;
float smallestRange = radius;
foreach (Enemy enemy in enemies)
{
if (Vector2.Distance(center, enemy.Center) < smallestRange)
{
smallestRange = Vector2.Distance(center, enemy.Center);
target = enemy;
}
}
}
Right, onto the aiming method, what we do here is find the direction from the tower to the target, and find out what that direction is by using some trigonometry.
For more information about finding an angle from a direction check out Riemers Tutorial.
Without for ado, here is the method :
protected void FaceTarget()
{
Vector2 direction = center - target.Center;
direction.Normalize();
rotation = (float)Math.Atan2(-direction.X, direction.Y);
}
public override void Update(GameTime gameTime)
{
base.Update(gameTime);
if (target != null)
FaceTarget();
}
And that’s our tower class finished for now! Go back to Game1.cs and in the Update method, just after we Update the enemy, add the following :
if (tower.Target == null)
{
List<Enemy> enemies = new List<Enemy>();
enemies.Add(enemy1);
tower.GetClosestEnemy(enemies);
}
tower.Update(gameTime);
Here, we just check if the tower has a target, and if it doesn’t we give it one using the method we added earlier.
And that’s it for now, if you run the project you should see your black dot following the path, with our shiny new tower following his every move!
Here is the source code for this tutorial.
In the IsInRange method, should the if statement be:
ReplyDeleteif (Vector2.Distance(center, position) <= radius)
and not
if (Vector2.Distance(center, position) <= range)
Yes it should, thanks for pointing that out!
ReplyDeleteMy code and the source code download you give have the exact same everything. Gone over about 20 times, but for some reason, yours will Debug, mine won't because mine gets errors.
ReplyDeleteI can't really help without knowing which errors you are getting, if you post your errors here I will try and help.
ReplyDeleteAwesome tutorial! It's my 3th tut and yours is really easy to follow up till now, maybe you should point out to the people who can't get it to work to learn some basic C# and XNA.
ReplyDeleteJust not sure about:
public Tower(Texture2D texture, Vector2 position)
: base(texture, position)
Does it mean it gets it's texture and position from it's parent class?
Also, shouldn't there be an else in between those returns as now it returns true and false if it's within it's radius. If the distance isn't greater then the turrets radius? Not tested it though.
ReplyDeletepublic bool IsInRange(Vector2 position)
{
if (Vector2.Distance(center, position) <= radius) return true;
return false;
}
Hey Madmenyo, I'm glad you like my tutorials!
ReplyDeleteThis line :
base(texture, position)
is just calling the inherited sprite classes constructor, you might want to check this link out : http://www.dotnetperls.com/base
An else statement isn't required there, this is because as soon a you call "return", the method gets exited so if the distance is less than the radius,
return false; will never be reached. You may want to look at this : http://msdn.microsoft.com/en-us/library/1h3swy84(v=vs.71).aspx
Let me know if that helps!
Well i'm still trying to understand inheritance to it's fullest but that link certainly helps. Thanks for the 2 links!
ReplyDeleteI think i wasn't to far off with my statement. It loading it's base contructor and runs that first "to feed the texture and position" then it adds the radius to the tower object.
In your full version at the bottem you didn't add the IsInRange method. It's not called yet (as yours works) but people might get into trouble if they use it and continue.
I have towers that I don't want to rotate. How would I modify this code to be able to shoot at the enemies without my tower turning to face them?
ReplyDeleteHey, have you looked at this tutorial : http://xnatd.blogspot.com/2011/01/tutorial-12-adding-new-tower-type.html
ReplyDeleteI am moving houses for the first time (as a teen) i need tips and help for the move !?
ReplyDeletemoving packers toronto
Looking for a house moving company? Any Suggestion...?
ReplyDeletelocal moving nyc
What do real estate developers do?
ReplyDeletehttps://www.youtube.com/watch?v=ZfmDwgWvkC4
Really!!! I am very impressed after reading this blog. thanks for providing deep information for
ReplyDeleteMoving companies In New York
Truly superb blog, I don’t have actual words to praise in regards for this
ReplyDeletemovers michigan
I like your post & I will always be coming frequently to read more of your post. Thank you very much for your post once more.
ReplyDeletelocal moving companies houston tx
Another helpful post. This is a very nice blog that I will definitively come back to several more times this year!
ReplyDeletemoving
This is easier and surely gives comfort to internet users. Thanks for sharing. Post like this offers great benefit. Thank you!
ReplyDeletelow rates