DEFCOM1  
 

 

XNA Level 2 Lesson 4

Object Oriented Programming

  1. Create a new class called CSprite
  2. Create an Instance of that class
  3. Update the initialise function
  4. Update the update function
  5. Update the draw function

 

What are Objects?

Object Oriented Programming (OOP) can be a little tricky to head around, but once you start coding in this style you won’t go back.

Using Objects allows us to wrap up (encapsulate) variables and functions together. I shall explain more as we go along.

At the moment if wanted to create another tank we would have to duplicate all the variables

So instead of this (what we currently doing)

protected Vector2 position;
protected float rotation;


protected Vector2 shellPos;
protected float shellRot;
protected int fireState;
 

we would now have this (DO NOT COPY)

protected Vector2 position1;
protected Vector2 position2;
protected float rotation1;
protected float rotation2;

protected Vector2 shellPos1;
protected Vector2 shellPos2;
protected float shellRot1;
protected float shellRot2;
protected int fireState1;
protected int fireState2;
 

 

What if we needed 3 tanks, 4 tanks or even 10 tanks? a hundred tanks???

It would soon get out of hand.

We are going to create a class to hold all the variables together

 

Create a new class called CSprite

CSprite will hold information about where a texture should be drawn on screen, later we will create a tank class

Click on the Project menu and select 'Add Class'

Call it CSprite press 'Add'

 

You should now have a nice new class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Level2_Lesson04
{
    class CSprite
    {
    }
}
 

 

We are now going to create the variables within our class.

class CSprite
{
    //all variable currently public, we will change this later!
    public Vector2 position = new Vector2();
    public float rotation;
    public Rectangle sourceRect; //which part of the image are we drawing
    public Vector2 handlePosition; //which part of the image does it rotate around

}
 

 

Now switch back to your Game1.cs file (your main code)

Delete the following 2 lines from your global variable, warning this will create a lot of errors, but do not worry.

protected Vector2 position;
protected float rotation;

 

Now in its place we create and 'instance' of our new class

CSprite tank1;

 

We now need to edit the initialise function

protected override void Initialize()
{
    // TODO: Add your initialization logic here
    tank1 = new CSprite();

    tank1.rotation= 0;

    tank1.position.X = 200;
    tank1.position.Y = 200;
    tank1.sourceRect = new Rectangle(128, 0, 128, 128);
    tank1.handlePosition = new Vector2(64, 64);

Now the not to easy bit, you need to go through your code where ever it is underlined in red change it from position or rotation to tank1.position and tank1.rotation

Finally we need to change the draw command to

 

spriteBatch.Begin();

spriteBatch.Draw(SpriteSheet, tank1.position, tank1.sourceRect, 
    Color.White, tank1.rotation, tank1.handlePosition, 1.0f, SpriteEffects.None, 1);

 

Congratulations you have created and used your first object.

Your next challenge is to covert the shell to an object instead

 

<<Complete Listings>>

public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    //Global Variables
    protected Texture2D SpriteSheet;

    CSprite tank1;

    protected Vector2 shellPos;
    protected float shellRot;
    protected int fireState;



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


    protected override void Initialize()
    {
        // TODO: Add your initialization logic here
        tank1 = new CSprite();

        tank1.rotation= 0;

        tank1.position.X = 200;
        tank1.position.Y = 200;
        tank1.sourceRect = new Rectangle(128, 0, 128, 128);
        tank1.handlePosition = new Vector2(64, 64);


        shellPos = new Vector2();
        shellRot = 0;
        fireState = 0;


        base.Initialize();

    }


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

        // TODO: use this.Content to load your game content here

        SpriteSheet = Content.Load<Texture2D>("TankSpriteSheet");
    }


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


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

        // TODO: Add your update logic here

        KeyboardState key = Keyboard.GetState();
        float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;


        if (key.IsKeyDown(Keys.Left))
        {
            tank1.rotation -= 1.0f * elapsed;
        }
        if (key.IsKeyDown(Keys.Right))
        {
            tank1.rotation += 1.0f * elapsed;
        }
        if (key.IsKeyDown(Keys.Up))
        {
            float x, y;

            x = (100 * elapsed) * (float)Math.Cos(tank1.rotation);
            y = (100 * elapsed) * (float)Math.Sin(tank1.rotation);

            tank1.position.X += x;
            tank1.position.Y += y;
        }

        if (key.IsKeyDown(Keys.Down))
        {
            float x, y;

            x = (-100 * elapsed) * (float)Math.Cos(tank1.rotation);
            y = (-100 * elapsed) * (float)Math.Sin(tank1.rotation);

            tank1.position.X += x;
            tank1.position.Y += y;
        }

        if (key.IsKeyDown(Keys.Space) && fireState == 0)
        {

            //fire
            //position shell to barrel
            float sx, sy;

            //start 70 pixels from centre of the tank (horizontal not vertical)
            sx = (70 * (float)Math.Cos(tank1.rotation)) - (0 * (float)Math.Sin(tank1.rotation));
            sy = (70 * (float)Math.Sin(tank1.rotation)) + (0 * (float)Math.Cos(tank1.rotation));

            //set shell position
            shellPos.X = tank1.position.X + sx;
            shellPos.Y = tank1.position.Y + sy;

            //set rotation of shell to angle of tank
            shellRot = tank1.rotation;

            //FIRE!!!
            fireState = 1;

        }

        if (fireState == 1) //IF Firing
        {
            //move shell position
            float x, y;

            x = (500 * elapsed) * (float)Math.Cos(shellRot);    //500 is speed of shell
            y = (500 * elapsed) * (float)Math.Sin(shellRot);

            shellPos.X += x;
            shellPos.Y += y;

            //if out of screen bounds
            if (shellPos.X < 0 || shellPos.X > 1280 || shellPos.Y < 0 || shellPos.Y > 720) 
            {
                fireState = 0;//reset shell
            }
        }


        base.Update(gameTime);
    }


    protected override void Draw(GameTime gameTime)
    {

        GraphicsDevice.Clear(Color.SeaGreen);

        spriteBatch.Begin();

        spriteBatch.Draw(SpriteSheet, tank1.position, tank1.sourceRect, 
            Color.White, tank1.rotation, tank1.handlePosition, 1.0f, SpriteEffects.None, 1);

        if (fireState == 1)
        {
            spriteBatch.Draw(SpriteSheet, shellPos, new Rectangle(512, 0, 128, 128), 
                    Color.White, shellRot, new Vector2(64, 64), 1.0f, SpriteEffects.None, 1);

        }

        spriteBatch.End();

        base.Draw(gameTime);
    }
}