Friday, January 25, 2013

XNA Tutorial:2D Shooting Part 2

A while ago I created a tutorial for shooting bullets out of a rocket in nay direction. The method used, while functional, is not very re-usable. In this tutorial we are going to re-factor the previous shooting tutorial. It is recommended that you finish this previous tutorial as we will be using that project.

Firstly you need to create a new game component. Call it ProjectileManager. This will be the place where we will manage our bullets. You need to ensure that instead of just inheriting from Microsoft.Xna.Framework.GameComponent change it to DrawableGameComponent as this will allow us to add a draw method to this game component.

You must then add a draw method to the game component just like the following. In here we will draw our bullets.

Next we will add a few variables and instantiate them in the constructor. As you can see, the list of bullets and the texture are both static. This is because we will be referencing them later is a static method. I'll explain further later.

Now we need to add an enum for bullet types. Enums are types that allow you to assign names to integer values. Add the following line to Bullet.cs file. Add is so that it is outside the bullet class. Next we will need to add a new property to the bullet class. This will be of type BulletType. We will need this if at some point in the future we create enemies that are capable of shooting back at the player. With this new property we will need to modify the constructor for the bullet class. We need to add a new parameter for the bullet type. Modify the constructor so it looks like this: Go back to the ProjectileManager. The next thing we need to do is add a public static method to add a new bullet to the bullet list. A public static method allows us to be able to access this method anywhere in the code. In this case by just typing ProjectileManager.AddBullet(methodParameters). Create a new method and make sure it looks like the following code. Next we need to be able to update the bullets in the projectile manager. We have pretty much already written this code in the rocket class all you really need to do is cut and paste the bullet update loop code over to the update loop of the projectile manager. Within the update for the projectile manager you should have to following code. Make sure you have also removed this code from the rocket class.

The exact same needs to be done for the drawing loop. Cut and paste the bullet drawing loop from the rocket class to the projectile manager draw method. The following code should now be in your draw method for the projectile manager. Before we continue make sure you no longer have code in the rocket class for updating and drawing bullets. You may also remove the list of bullets and bulletTex from the rocket class. You must also remove the bulletTex parameter from the rocket constructor and any other bulletTex code from the constructor. The constructor should now look like the following. next we need to use the new method we created in the ProjectileManager class. The rocket update method should now look like this: You may have notices that if you build your project you are still getting a few errors. We will work on fixing these next.

Go to the Game1 class. Go to the load content method to where we are instantiating the rocket. Remove the parameter for the bullet texture. It should now look like this. Next just above this line of code, still within the load content method, Create a new instance of the projectile manager. Now go down to the draw method in the Game1 class and move the spritebatch.end so that is appears after the base.Draw(). We do this to allow our projectile manager to draw with the same spritebatch. The base.Draw() updated the draw method of all the game components.

You should now be able to run the game. You may have noticed that the bullets are being drawn on top of the rocket. To fix this go back to your code. We must change the draw order. Go to the bullet class and to the draw method. change the last parameter to be less that 1.0f. I put it to 0.8f. Then go to the Game1 draw method and modify the spritebatch.begin method to look like the following. Now run the game and it should work perfectly.

Now the code is set up in such a way as to allow us to add enemies at some stage in the future. If you see any typos or mistakes please let me know.

Here is the source for the finished project.