Josh-CO Dev

Solving the worlds problems one line of code at a time.

XNA – Add bullets to our overhead game

Leave a comment


This tutorial is a continuation from https://joshcodev.wordpress.com/2012/10/25/xna-lets-break-down-our-simple-overhead-game-and-start-making-classes/ . If you have not yet completed this tutorial, you will need to follow it before following this one as we further use our custom classes. If you are just here to learn about shooting bullets, then you do not need the previous tutorial.

Before we can start this tutorial, we need a bullet. Here is a cheesy one you can download or you can create your own. For the sake of this tutorial, just make sure it is a 16×16 image unless you are comfortable enough modifying this code.

Now that we have our bullet, let’s get to the coding.
-Start by adding a new class to your project and name it Bullet.cs
-Add in our normal namespaces

using System;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

-In your class declaration, be sure you inherit from Sprite

class Bullet : Sprite

-We only have two global variables. One for the direction that the bullet is traveling, and another for the speed to move the bullet

        private Vector2 Direction;
        private float Speed = 1.5f;

-Now let’s code our constructor, this should all be pretty familiar by now

        public Bullet(ContentManager content, Vector2 startingPosition, Vector2 movement, float angle)
            : base(content)
        {
            //this.Content = content;
            Texture = Content.Load<Texture2D>("bullet1");

            spriteWidth = 16;
            spriteHeight = 16;
            
            Position = startingPosition;
            Origin = new Vector2(spriteWidth / 2, spriteHeight / 2);

            Direction = movement;

            if(movement != Vector2.Zero)
                Direction.Normalize();

            //debugging
            Angle = angle;
        }

-Nothing too off the wall here. Notice that we added the :base(content) just like we did in our player class to call our sprite constructor first. We are passing in a content manager, a starting position, a movement vector, and the angle of our bullet. As you’ll see later, this will all be called from our player class.
-The first thing we are doing here is loading our texture. If you created your own bullet, just replace bullet1 with your own name. We set the width and height to 16. If you made a bigger or smaller bullet, you just need to adjust these two variables. We set our initial position to the starting position and then create our origin for rotation. Direction is equal to our movement and we’ll see how this is passed in later. Next, we normalize our vector to ensure that our bullet will fly in a straight path, and finally we set the angle of our bullet.

-Next, we need to write our update method

        public override void Update(GameTime gt)
        {
            Position += Direction * Speed * (float)gt.ElapsedGameTime.TotalMilliseconds;

            base.Update(gt);
        }

-Pretty simple here. All we need to do is update where the bullet is. To do this we add the direction and multiply it by the speed that we set up top. You can adjust the speed to slow down or speed up your bullet movement. Then multiply that by the elapsed milliseconds since the last update call. This ensures that the speed will be the same across all devices regardless of processor speed.

-Lastly, we need our draw method. This is the same draw method that we use in our player class and we just need to call the base.draw

        public override void Draw(SpriteBatch sb)
        {
            base.Draw(sb);
        }

That’s it for our bullet class! Pretty simple, right?

Now, we need to go back to our player.cs class and make the changes for our bullets to work.

-Since we are using .NET, I am a fan of using lists. So start by adding a using statement for our generic collections

using System.Collections.Generic;

-Now, we need to create a bullet list to hold all of our bullets

        //create a list of bullets
        List<Bullet> Bullets = new List<Bullet>();

-Now we need to change our update class to handle the bullets. Go to the section where you handle your keyboard input and add this:

            if (currMouse.LeftButton == ButtonState.Pressed && prevMouseState.LeftButton != ButtonState.Pressed)
            {
                //fire a bullet
                Bullet bullet = new Bullet(this.Content, this.Position, direction, this.Angle);
                Bullets.Add(bullet);
            }

-There is a little bit of voodoo here, but nothing too much. We are firing a bullet when the left mouse button is clicked. If all we add is the LeftButton == Buttonstate.Pressed, then if someone holds in the mouse button, it will keep rapid firing bullets. This is not what I want. So we make sure that the mouse button was not pressed on the previous update call. Now if they hold the mouse button, only one bullet will fire. All we have to do is create a new bullet object, pass in our conetent manager, give it the position of our sprite which is the center of our player, pass in the direction of travel, and pass in the angle. This is all logic that we created earlier to figure out how to rotate our player, the same thing works for the bullet. The last statement adds the newly created bullet to our list of bullets. We’ll use this next to handle our bullet updates and draws.

-At the bottom of your update method under and before your base.Update call, add this code:

            foreach (Bullet b in Bullets)
            {
                b.Update(gt);

                if (b.Position.X < 0 - b.Origin.X)
                {
                    Bullets.Remove(b);
                    return;
                }
                else if (b.Position.X >= screenSize.X + b.Origin.X)
                {
                    Bullets.Remove(b);
                    return;
                }
                else if (b.Position.Y < 0 - b.Origin.Y)
                {
                    Bullets.Remove(b);
                    return;
                }
                else if (Position.Y >= screenSize.Y + b.Origin.Y)
                {
                    Bullets.Remove(b);
                    return;
                }
            }

-This is simpler than is looks. All we are doing is looping through all of the bullets in our bullet list and calling the update method for that bullet. All this does is move them in their initial set direction. Then we need to check each bullet to see if it is outside of the screen. If it is, we remove it from the list to keep it from updating and drawing. If you do not do this, your bullet will continue to fly forever until the execution is stopped or it crashes. Obviously, this could cause performance issues later.

-Now, go to your draw method and add this code before the base.draw call:

            foreach (Bullet b in Bullets)
                b.Draw(sb);

-Simple! We are doing a foreach call just like we did in our update statement, only now we call the draw method of the bullet and draw each one to the scren.

That’s it! If you run the solution you should now have a player that will move around the screen and point towards your mouse. If you click the mouse button, you will fire a bullet. Play around with the bullet speed variable and set it to a speed that you like.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s