DEFCOM1  
 

 

XNA Level 1 Lesson 10

Firing!!!

  1. Add laser sprite
  2. Create new variables
  3. Load sprite
  4. Edit the update function
    • Remove score from the asteroid loop
    • Add new switch case options
  5. Edit the draw function

 

Adding Firing to the game

Adding the ability to fire to our game isn't that difficult.

  • We add a picture of a laser
  • When we press fire we align the laser to the centre of the ufo
  • Move the laser up the screen
  • Check to see if the laser has hit any of the asteroids
  • Check to see if the laser has gone off of the screen

 

Add the laser sprite

Right Click on your project content menu and add the laser image to the project

(Check lesson 3 and 9 if you have forgotten how to do this)

 

Create new variables for the laser

In the global variables section, just before 'public Game1()'

Vector2 laserPos = new Vector2();
int fireState = 0; //0 = not firing, 1 = firing
Texture2D laserTex;

laserPos stores the coordinates of the laser

fireState stores the status of the laser, is it firing?

laserTex store the image of the laser

 

Load the laser image (sprite)

Go to the LoadContent function and add the following code

laserTex = Content.Load<Texture2D>("laser");

 

Edit the updateGame function

In the loop that checks if an asteroid has gone off of the screen, remove score+=10. We will only get points if we shoot an asteroid

//update all asteroid positions
for (int i = 0; i < numberOfAsteroids; i++)
{
    asteroid[i].Y += 5;
    if (asteroid[i].Y > screenHeight)
    {
        Random rand = new Random();
        asteroid[i].X = rand.Next(screenWidth - asteroidTex.Width);
        asteroid[i].Y = 0 - (numberOfAsteroids * (250 - score / 10)) - 128;  //put to top
        score += 10; //remove this line!
    }
}

 

The next section may look quite long, but it isn't anything you have not seen before. We are going to use a Switch Select Statement

 

if fireState is 0 then position laser under ufo

if fireState is 1 then fire

 

We check to see if the laser has hit any asteroids using almost the same code as checking if the ufo has hit any of the asteroids

If you have hit one, the asteroid is reset and your score goes up!

Re-visit lesson 6 if you need a refresher

Warning. This code must go after we have finished getting the keyboard input for the ufo

if (key.IsKeyDown(Keys.Space))
{
    fireState = 1;
}


//update laser
switch (fireState)
{
    case 0:
        //Position laser under ufo
        laserPos.X = x-(laserTex.Width/2);
        laserPos.Y = y-20;
        break;

    case 1:
        //Update position
        laserPos.Y -= 10;
        if (laserPos.Y < 0)
        {
            fireState = 0;
        }

        //check each asteroid
                    
        //Get Midpoint of ufo
        int lx = (int)laserPos.X + (laserTex.Width / 2);
        int ly = (int)laserPos.Y + (laserTex.Height / 2);

        //check if midpoint is inside each asteroid 
        for (int i = 0; i < numberOfAsteroids; i++)
        {
            if (lx > asteroid[i].X && lx < asteroid[i].X + asteroidTex.Width)
            {
                if (ly > asteroid[i].Y && ly < asteroid[i].Y + asteroidTex.Height)
                {
                    //reset asteroid position
                    Random rand = new Random();
                    asteroid[i].X = rand.Next(screenWidth - asteroidTex.Width);
                    asteroid[i].Y = 0 - (numberOfAsteroids * (250 - score / 10)) - 128;  //put to top
                                
                    //update score
                    score += 10;
                                                                
                    //reset laser
                    fireState = 0;
                                
                }
            }
        }


        break;


    default:
        //error//
        break;

}

 

Edit the draw function

We can now simply draw our laser

After Sprite.Begin, but before we draw our UFO add the following line

spriteBatch.Draw(laserTex, laserPos, Color.White);

 

Complete Listings

public class Game1 : Microsoft.Xna.Framework.Game
{

    //----
    //Global Variables
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    //screen size
    public int screenHeight;
    public int screenWidth;

    public int gameState = 0;

    // This is a texture we can render.
    Texture2D ufoTex;
    Texture2D asteroidTex;

    SpriteFont font;

    // Set the coordinates to draw the sprite at.
    Vector2 ufoPos = Vector2.Zero;

    //create an array of 10 asteroid coordinates (we will use the same image for each one)
    static int numberOfAsteroids = 25;
    Vector2[] asteroid = new Vector2[numberOfAsteroids];

    Random rand = new Random();

    int score = 0;

    int ufoSpriteNum = 0;
    int ufoWidth = 128;

    Vector2 laserPos = new Vector2();
    int fireState = 0; //0 = not firing, 1 = firing
    Texture2D laserTex;


    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }


    protected override void Initialize()
    {
        //set Screen size
        screenWidth = 800;
        screenHeight = 600;

        graphics.PreferredBackBufferWidth = screenWidth;
        graphics.PreferredBackBufferHeight = screenHeight;

        graphics.IsFullScreen = false;
        graphics.ApplyChanges();

        resetGame();

        base.Initialize();
    }

    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);

        //load our graphic
        ufoTex = Content.Load<Texture2D>("ufoSpriteSheet");
        asteroidTex = Content.Load<Texture2D>("asteroid");
        font = Content.Load<SpriteFont>("mainFont");
        laserTex = Content.Load<Texture2D>("laser");



    }


    protected override void UnloadContent()
    {
        // TODO: Unload any non ContentManager content here
    }

    public void resetGame()
    {
        //reset game
        gameState = 0;
        score = 0;

        //ufo starting position
        ufoPos.Y = screenHeight - 128;    //height of screen - hieght of ufo


        //Starting Position of all asteroids
        for (int i = 0; i < numberOfAsteroids; i++)
        {
            asteroid[i].X = rand.Next(800 - 128); //position within screen width - ufo width
            asteroid[i].Y = 0 - ((i * 250) + 128);
            float y = asteroid[i].Y;
        }
    }

    protected override void Update(GameTime gameTime)
    {

        //gameState Menu
        switch (gameState)
        {
            case 0:
                UpdateMenu(gameTime);   //intro screen
                break;

            case 1:
                UpdateGame(gameTime);   //main game
                break;

            case 2:
                UpdateGameOver(gameTime); //End OF Game
                break;

            default:
                /*error*/
                break;
        };


        base.Update(gameTime);
    }

    public void UpdateMenu(GameTime gameTime)
    {

        KeyboardState key = Keyboard.GetState();

        if (key.IsKeyDown(Keys.Space))
        {
            gameState = 1;
        }
    }

    public void UpdateGame(GameTime gameTime)
    {
        // Allows the game to exit
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();

        // TODO: Add your update logic here



        //update all asteroid positions
        for (int i = 0; i < numberOfAsteroids; i++)
        {
            asteroid[i].Y += 5;
            if (asteroid[i].Y > screenHeight)
            {
                Random rand = new Random();
                asteroid[i].X = rand.Next(screenWidth - asteroidTex.Width);
                asteroid[i].Y = 0 - (numberOfAsteroids * (250 - score / 10)) - 128;  //put to top
                //score += 10;
            }
        }


        //Get Midpoint of ufo
        int x = (int)ufoPos.X + (ufoWidth / 2);
        int y = (int)ufoPos.Y + (ufoTex.Height / 2);

        //check if midpoint is inside each asteroid 
        for (int i = 0; i < numberOfAsteroids; i++)
        {
            if (x > asteroid[i].X && x < asteroid[i].X + asteroidTex.Width)
            {
                if (y > asteroid[i].Y && y < asteroid[i].Y + asteroidTex.Height)
                {
                    gameState = 2;//game over

                }
            }
        }



        //update ufo
        KeyboardState key = Keyboard.GetState();

        ufoSpriteNum = 0;
        if (key.IsKeyDown(Keys.Left) && ufoPos.X > 0)
        {
            ufoPos.X -= 5;
            ufoSpriteNum = 1;
        }
        if (key.IsKeyDown(Keys.Right) && ufoPos.X < 800 - ufoWidth)
        {
            ufoPos.X += 5;
            ufoSpriteNum = 2;
        }
        if (key.IsKeyDown(Keys.Up) && ufoPos.Y > 0)
        {
            ufoPos.Y -= 5;
        }
        if (key.IsKeyDown(Keys.Down) && ufoPos.Y < 600 - ufoTex.Height)
        {
            ufoPos.Y += 5;
        }
        if (key.IsKeyDown(Keys.Space))
        {
            fireState = 1;
        }


        //update laser
        switch (fireState)
        {
            case 0:
                //Position laser under ufo
                laserPos.X = x-(laserTex.Width/2);
                laserPos.Y = y-20;
                break;

            case 1:
                //Update position
                laserPos.Y -= 10;
                if (laserPos.Y < 0)
                {
                    fireState = 0;
                }

                //check each asteroid
                    
                //Get Midpoint of ufo
                int lx = (int)laserPos.X + (laserTex.Width / 2);
                int ly = (int)laserPos.Y + (laserTex.Height / 2);

                //check if midpoint is inside each asteroid 
                for (int i = 0; i < numberOfAsteroids; i++)
                {
                    if (lx > asteroid[i].X && lx < asteroid[i].X + asteroidTex.Width)
                    {
                        if (ly > asteroid[i].Y && ly < asteroid[i].Y + asteroidTex.Height)
                        {
                            //reset asteroid position
                            Random rand = new Random();
                            asteroid[i].X = rand.Next(screenWidth - asteroidTex.Width);
                            asteroid[i].Y = 0 - (numberOfAsteroids * 
                                   (250 - score / 10)) - 128;  //put to top
                                
                            //update score
                            score += 10;
                                                                
                            //reset laser
                            fireState = 0;
                                
                        }
                    }
                }


                break;


            default:
                //error//
                break;

        }


    }

    public void UpdateGameOver(GameTime gameTime)
    {
        KeyboardState key = Keyboard.GetState();

        if (key.IsKeyDown(Keys.Enter))
        {
            resetGame();
        }
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.Black);


        switch (gameState)
        {
            // Draw Menu
            case 0:
                spriteBatch.Begin();
                spriteBatch.DrawString(font, "Asteroid Field\nArrows to Move\nPress Space to Play ", 
                                          new Vector2(100, 10), Color.White);
                spriteBatch.End();
                break;


            // Draw Main Game
            case 1:

                spriteBatch.Begin();

                spriteBatch.Draw(laserTex, laserPos, Color.White);

                spriteBatch.Draw(ufoTex, ufoPos, 
                             new Rectangle(ufoSpriteNum * ufoWidth, 0, 128, 128), Color.White);

                //draw all asteroids
                for (int i = 0; i < numberOfAsteroids; i++)
                {
                    spriteBatch.Draw(asteroidTex, asteroid[i], Color.White);
                }
                                        

                spriteBatch.DrawString(font, "Score: " + score, new Vector2(20, 10), Color.White);

                spriteBatch.End();
                break;



            // Draw END OF GAME
            case 2:

                spriteBatch.Begin();

                spriteBatch.DrawString(font, "Asteroid Field\nFinal Score: " + score, 
                                         new Vector2(100, 10), Color.White);
                spriteBatch.DrawString(font, "Press Enter to Continue ", 
                                         new Vector2(100, 60), Color.White);
                spriteBatch.End();
                break;
        }
        base.Draw(gameTime);
    }
}