To start with, we will be creating a new class called "Enemy.cs", this will be a base class for all our enemy's, whether they are bosses or fast units or just plain cannon fodder.
So to start with add a new class called "Enemy.cs", then add the following using statements :
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
From now on these 2 namespaces will need to be added to nearly every class, so I am just going to assume that you will remember to add these.
The first thing that we need to do is make our new class inherit from the "Sprite" class. To do this replace this line :
public class Enemy
with this :
public class Enemy : Sprite
Now we can access all of the methods and fields that we exposed in the Sprite class last time.
Every enemy is going to share some basic properties, so we will add these first, add these lines of code to the top of Entity.cs :
protected float startHealth;
protected float currentHealth;
protected bool alive = true;
protected float speed = 0.5f;
protected int bountyGiven;
These fields should be pretty self explanatory so I won't insult you by explaining them to you, however one thing to notice is these fields are marked as "protected", this means that any class that inherits from this class will be able to access them.
Next we will add some properties to expose some of these feilds, so that other classes will be able "check up" on our enemy's. Add these just under the feilds we just added :
public float CurrentHealth
{
get { return currentHealth; }
set { currentHealth = value; }
}
public bool IsDead
{
get { return currentHealth <= 0; }
}
public int BountyGiven
{
get { return bountyGiven; }
}
Now it's time to add a constructor to the class :
public Enemy(Texture2D texture, Vector2 position, float health, int bountyGiven, float speed)
: base(texture, position)
{
this.startHealth = health;
this.currentHealth = startHealth;
this.bountyGiven = bountyGiven;
this.speed = speed;
}
We now have the basic outline of our enemy class, so lets get drawing us some cannon fodder. Go back into "Game1.cs" and at the top, just under where we defined our level add the following :
Enemy enemy1;
Now before we can initialize our enemy, we need to add in a new sprite for the to use, so add the following image to the content project :
Note : This texture should be called "enemy.png"
With that added, we can move onto initializing and drawing our enemy!
So in the "LoadContent()" Method, add the following :
Texture2D enemyTexture = Content.Load<Texture2D>("enemy");
enemy1 = new Enemy(enemyTexture, Vector2.Zero, 100, 10, 0.5f);
This code loads in the texture for the enemy, and then passes it to our "Enemy" in the enemy's constructor. The enemy will be created in the top left corner (0, 0) with 100 health, 10 gold in his pocket, and with a slow walk.
Now to draw our enemy, add the following code in the draw method after level.Draw(spriteBatch) but before SpriteBatch.End() :
enemy1.Draw(spriteBatch);
Now Run the project, and you should see our level, with a little white circle in the top left corner, and their we have a very simple enemy class.
Before we move onto the next tutorial, we just need to add in a couple more things to the "Enemy" class. So go to the enemy class and add in the following code :
public override void Update(GameTime gameTime)
Before we move onto the next tutorial, we just need to add in a couple more things to the "Enemy" class. So go to the enemy class and add in the following code :
public override void Update(GameTime gameTime)
{
base.Update(gameTime);
if (currentHealth <= 0)
alive = false;
}
This code overrides the Sprites "Update()" method. The first line just tell the Sprite base class to update itself, then in the last two lines we just check if the enemy is dead.
In the next method, we are going to override the Sprites "Draw()" method, so that we can draw our enemy a little bit differently. But first we must add a new method to "Sprite.cs". Go to "Spirte.cs" and add the following method :
public virtual void Draw(SpriteBatch spriteBatch, Color color)
{
spriteBatch.Draw(texture, center, null, color, rotation,
origin, 1.0f, SpriteEffects.None, 0);
}
This overload method allows us to "tint" a sprite with a certain colour.
Now, back to "Enemy.cs", add the following code just underneath the Update() method :
public override void Draw(SpriteBatch spriteBatch)
{
}
Hopefully there is no explanation needed here. First we are going to check if our enemy is still alive :
if (alive)
{
Next we are going to work out what percentage of health our enemy has lost :
float healthPercentage = (float)currentHealth / (float)startHealth;
Then we will create a colour based off this information, so that our player can see how much damage he had done to his enemy :
Color color = new Color(new Vector3(1 - healthPercentage,
1 - healthPercentage, 1 - healthPercentage));
base.Draw(spriteBatch, color);
And that's it for our enemy class. Your draw method should now look like this :
public override void Draw(SpriteBatch spriteBatch)
{
if (alive)
{
float healthPercentage = (float)currentHealth / (float)startHealth;
Color color = new Color(new Vector3(1 - healthPercentage,
1 - healthPercentage, 1 - healthPercentage));
base.Draw(spriteBatch, color);
}
}
So let's see if what we just did made any difference to our enemy ;). Go to "Game1.cs" and in the Update() method add the following :
enemy1.CurrentHealth -= 1;
enemy1.Update(gameTime);
This will knock off one health point from our enemy each frame. If you run the game now, you should see the enemy start off black, the gradually get whiter, and eventually disappears (He disappears because he is dead), and their we have it, our completed enemy class.
Here is the working code for this tutorial.
I think the line
ReplyDeleteTexture2D enemyTexture = Content.Load("enemy");
needs to be
Texture2D enemyTexture = Content.Load("enemy");
also since the file name when you download it is apckuo perhaps it should be...
Texture2D enemyTexture = Content.Load("apckuo");
Also, the instructions should say to go back to the Enemy class before you add this code...
ReplyDeletepublic override void Draw(SpriteBatch spriteBatch)
{
}
Thanks for pointing that out - Fixed :)
ReplyDeleteJust wanted to say that these tutorials are great! one problem though. You do not need to override the Draw method as you are overloading the actual method and this provides a seperate method signature and will yield an error if it does not find a method with that exact same signature. better to do public void Draw and call Draw(spriteBatch, color) in the method.
ReplyDeleteThanks for the kind words! I'm not sure I understand your suggestion though, the Draw method simply overrides one of the Sprite classes draw methods :).
ReplyDeletehey i get error: 'Tower_Defence.Enemy.Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch)': no suitable method found to override
ReplyDeletedont know whats wrong..
Hey,
ReplyDeleteAre you sure that your Enemy class is inheriting from the sprite class (see the start of this tutorial) and if so are you sure you added all the correct methods to the sprite class? (See previous tutorial).
I think the confusion with the 'Tower_Defence.Enemy.Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch)': no suitable method found to override' error is from editing the sprite draw method.
ReplyDeleteThis tutorial does not edit the Sprite Draw method from the previous tutorial, it adds a second one. When finished with this tutorial, their should be one draw method in the Enemy class and two in the Sprite class.
ok i got it, now working
ReplyDeleteHi,
ReplyDeletethere is an error in the texture loading.
game1 -> LoadContent() ->
Texture2D enemyTexture = Content.Load("enemy");
has to be:
Texture2D enemyTexture = Content.Load("enemy");
If you want to fade your enemy from green to red:
Color color = new Color(new Vector3(1 - healthPercentage, healthPercentage, 0));
anyway nice tutorials :D
The Comments delete spiky brackets...
ReplyDeleteContent.Load
(spiky bracket here) <
Texture2D
> (spiky bracket here)
("enemy");
Hey thanks for pointing that out, it turns out that you are not allowed to use the Inequality signs :S I have fixed it though.
ReplyDeleteThere isn't a enemy texture in your tutorial :S
ReplyDeleteAgreed. Where's my ugly creep texture!?
ReplyDeleteIt is there, it is just really hard to see, it is just above the line in italic.
ReplyDeleteI draw my enemy but he doesnt move anywhere, think you know what the problem is? feels like i dont give him any direction to move in.
ReplyDeleteThe name 'enemy1' does not exist in the current context
ReplyDeleteNot sure what to fix... Thanks
Error 1 Inconsistent accessibility: base class 'Tower_Defence_game.Sprite' is less accessible than class 'Tower_Defence_game.Enemy' C:\Users\Lewis\Documents\Visual Studio 2010\Projects\Tower Defence game\Tower Defence game\Tower Defence game\Enemy.cs 10 18 Tower Defence game
ReplyDeleteIt keeps saying this?
You need to make sure each class has the word public in front of it e.g :
ReplyDeletepublic class Enemy
{
}
public class Sprite
{
}
when i try to change the enemy texture all i get is a black box. is there some speciel conditions the images has to meet?
ReplyDeleteex. transparancy, .png. speciel size for them to be drawn?
Give please link to enemy.png It's broken
ReplyDeleteHi Roman,
ReplyDeleteI will try to upload it later, but for now you can get it from the zip file linked to at the bottom of the tutorial!
Very thank to you for useful tutorial!!!
ReplyDelete