Pong - Tutorial

Tutorials on how to use and create games in XNA.
8 posts Page 1 of 1
Contributors
User avatar
reececlarke
VIP - Donator
VIP - Donator
Posts: 245
Joined: Tue Dec 08, 2009 6:47 pm

Pong - Tutorial
reececlarke
Image
In this tutorial i will be showing you how to make pong to start off with we will need the images we will be using for bat one and bat two so in this case we will be using two images personally bat one i made blue 10x400 and bat two i made the same size but red after this we will need a ball so i used a 50x50 ball. (I will be writing this tutorial in stages so i don't wear out my fingers lol)

for reference notes i have called player one's bat player1 and player two's bat player2 as well as this i have called the ball ball.

if you like this tutorial don't forget to drop a nice +rep =P

Player Class

To Start off with we will need to make the player class so to do this right click on the windows sign that has pong next to it and add a new class personally i named mine player once the class opens we will need to add the following under using systems.text;
Code: Select all
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
what this does is allows us to Xna stuff within the class now what we need to do is add the variables so under class player enter the following.
Code: Select all
        Texture2D texture;
        public Rectangle rectangle;
        KeyboardState kb = Keyboard.GetState();
        int hight, width;
these will be the variables that we will be using what you can also see here is that we have made one public this is so that later on we can tell where it is in order to make the ball bounce of it. As well as this we have also made a KeyboardState this is so that we can detect what people press on there keyboards.

what we will then do under that is type.
Code: Select all

        public player(Texture2D newtexture, int newhight,int newwidth)
        {
            texture = newtexture;
            hight = newhight;
            width = newwidth;
            rectangle = new Rectangle(5, 10, texture.Width/2, (texture.Height/4));

        }
this is what we will be using as the builder as our project loads we will use this in order to load anything that is needed for the player class to start off with you will see that we are using two int's newhight and newwidth what these stand for is the hight and width of the game that we will get from Game1 class later on.

you can also see here that texture = newtexture; what this does is the texture you enter in game1 when loading it will be dragged into the code here so it knows what texture the ball is.

and as well as this it also creates the rectangle for the player you can mess around with the height a little as you see i have it set to texture.Height/4 but you can also remove it and have it as the height or divide it by 3 for example.

what we will then do is create a public void in which we will update the class so enter the following
Code: Select all
 public void update()
        {

           
            //keyboard
            keyboard();
            //checks if out
            isout();

        }
what you can see here is that this code relates to some of the private void's we will be adding later as you see here that is the code for the keyboard controls we will be adding and checking if it's about to go off screen and preventing that from happening.

so what we will be doing now is adding the keyboard controls so after that enter the following
Code: Select all

 private void keyboard()
        {
            kb = Keyboard.GetState();
            if (kb.IsKeyDown(Keys.Down) == true)
            {
                rectangle.Y = rectangle.Y + 5;
            }
            if (kb.IsKeyDown(Keys.Up) == true)
            {
                rectangle.Y = rectangle.Y - 5;
            }
        }
as you see here it uses kb = Keyboard.GetState(); what this does is check what state the keyboard is currently in without this the keyboard would be locked in it's last known slate.

after this is checks if the down key is being pressed if it is it add's 5 onto the Y value of the rectangle because the top left is know as 0,0 adding 5 onto it would make it go down the screen.

what we check next is if the up key is being pressed if it is we -5 which will make it go up the screen.

because currently if it hits the edge of the screen it will just go though it with out a care what we need to do now is make it so that it will not so to do this we need to add the following
Code: Select all
private void isout()
        {
            if (rectangle.Y < 0)
            {
                rectangle.Y = 0;
            }
            if (rectangle.Y > hight -rectangle.Height)
            {
                rectangle.Y = hight -rectangle.Height;
            }
        }
what this does is check if the y is over the boarder or not and if it is will reset it to right next to it meaning that the player will be unable to leave the screen as you see we have done this for the top and bottom boarder but there is no need for the sides because there is no way for the player to get there.

what we also need to do is to draw it to the screen so under here add the following bit of code
Code: Select all
 public void Draw(SpriteBatch spritebatch)
        {
            spritebatch.Draw(texture, rectangle, Color.White);

        }
what this does is draws the image to the screen using the texture and location we have added and gives it a white tint.
if you have done this right player class should look like the following
Code: Select all
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Pong
{
    class player
    {
        Texture2D texture;
        public Rectangle rectangle;
        KeyboardState kb = Keyboard.GetState();
        int hight, width;
     

        public player(Texture2D newtexture, int newhight,int newwidth)
        {
            texture = newtexture;
            hight = newhight;
            width = newwidth;
            rectangle = new Rectangle(5, 10, texture.Width/2, (texture.Height/4));

        }
        public void update()
        {

           
            //keyboard
            keyboard();
            //checks if out
            isout();

        }
        public void Draw(SpriteBatch spritebatch)
        {
            spritebatch.Draw(texture, rectangle, Color.White);

        }
        private void keyboard()
        {
            kb = Keyboard.GetState();
            if (kb.IsKeyDown(Keys.Down) == true)
            {
                rectangle.Y = rectangle.Y + 5;
            }
            if (kb.IsKeyDown(Keys.Up) == true)
            {
                rectangle.Y = rectangle.Y - 5;
            }
        }
        private void isout()
        {
            if (rectangle.Y < 0)
            {
                rectangle.Y = 0;
            }
            if (rectangle.Y > hight -rectangle.Height)
            {
                rectangle.Y = hight -rectangle.Height;

            }
        }
      

    }
}

now what we need to do is to add this into game1 so to do this in the Game1 class under
public class Game1 : Microsoft.Xna.Framework.Game
{

add the following
Code: Select all
 player one;
like for example a string were you declare a new string variable we will need to do this for the player class so i have declared it as just one.

what we next need to do is to load it into game so under
protected override void LoadContent()
{
put the following
Code: Select all
 one = new player(Content.Load<Texture2D("player"),graphics.PreferredBackBufferHeight,graphics.PreferredBackBufferWidth);
as you see here what we have done is loaded the texture in from file as well as share with the player class the hight and width of the screen which is important for stopping it going out of the screen.
what we now need to do is to keep it updated so that when we press the down and up keys it will go down and up on our screen so to do this under the following
protected override void Update(GameTime gameTime)
{
enter
Code: Select all
   one.update();
what this does is run the public void in player class update
now what we need to do is to draw it to the screen so under GraphicsDevice.Clear(Color.Black); or in your case the colour would be blue but i have changed it to black enter the following
Code: Select all
 spriteBatch.Begin();

 one.Draw(spriteBatch);
 spriteBatch.End();
what this does is draw player one to the screen using the public void we used.
you should be able to run it at this point to see if it has worked or not.

Player Two / AI

Right now that we have made player one what we will want to do is make player two / computer AI so we will do now is make a new class like we did the first time this time i have called it AI but you can name it to what ever you like as long as you adapt the code to the name you have named it like the first time.

so what we will be wanting to do is add all of the XNA stuff at the top like we did the fist time so under
systems.text; add the following
Code: Select all
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
now that we got all of that done what we will want to is add our variables so under
class AI
{
add the following
Code: Select all
        Texture2D texture;
        public Rectangle rectangle,ball;
        int hight, width,speed;
as you see here unlike player one we have a speed what this does is basic make the AI as difficult or as easy as you like the higher the speed the harder it is as it can move to the ball faster and the lower the easier it is.

now below that what you will want to add is the following
Code: Select all
public AI(Texture2D newtexture,int newhight, int newwidth)
        {
            //start
            hight = newhight;
            width = newwidth;
            texture = newtexture;
            speed = 5;
            rectangle = new Rectangle((width - texture.Width +5), hight / 2, texture.Width/2, texture.Height / 4);

            //end

        }
what we are doing in this bit of code is first getting the texture the height and the width like we did the first time with player one and then we are updating the height,width and texture variables with there new values like we did for player one what we are then doing is making the rectangle unlike player one what we are doing this time is getting the width of the window and taking away the texture width so that it is on screen then taking away 5 from that so there is a small gap from the edge of the screen and then placing it in the middle of the screen to start off with and then making the texture the size i want tit in this case slightly smaller then what i had it at.

what we then want to do under that is add a new public void update so under this bit of code that we have just done add the following
Code: Select all
      public void Update(Rectangle newball)
        {
            //updates AI on ball location
            //checks if out
            isout();
            //Ai movement
            movement();


        }
as you see here unlike player one the AI needs to know were the ball is currently at to move it's pad down to the ball in order to move its pad down to there and whack the ball back as you see here. Just like player one what we are doing is also checking if it's out of bounds and we also have a movement class for what i have just talked about with the ball movement updates.

so what we now need to do is add a new private void for isout so under this bit of code add the following.
Code: Select all
private void isout()
        {

            if (rectangle.Y < 0)
            {
                rectangle.Y = 0;
            }
            if (rectangle.Y > hight - rectangle.Height)
            {
                rectangle.Y = hight - rectangle.Height;
            }

        }
i am not going to talk really much about this code as it is the same bit of code i used before to do the same function for playerone.

What we now need to do is make the private void for the movement so under this add the following.
Code: Select all
private void movement()
        {
            //start
            if (ball.Y > rectangle.Y)
            {
                rectangle.Y = rectangle.Y + speed;
            }
            if (ball.Y < rectangle.Y)
            {
                rectangle.Y = rectangle.Y - speed;
            }

            //end
        }
as you see here it checks were the ball is currently at and moves the pad up and down depending on were the ball is currently at you can also see that it takes away or add's the speed what this does is it moves the pad up and down and the speed we just set earlier what we could also do is as the game goes on increase the speed of the Ai if we wanted to but i will not do that for now.

what we also need to add is the public void for drawing player two so under that bit of code add the following
Code: Select all
 public void Draw(SpriteBatch spritebatch)
        {
            //start

            spritebatch.Draw(texture, rectangle, Color.White);

            //end
        }

what this bit of code does is draw our sprite(image) to the screen we will be using a white tint so that it will use the colours of the image rather then add a tint to it.

if you have done this right AI class should look like
Code: Select all
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Pong
{
    class AI
    {
        ///start
        Texture2D texture;
        public Rectangle rectangle,ball;
        int hight, width,speed;
        
        
        public AI(Texture2D newtexture,int newhight, int newwidth)
        {
            //start
            hight = newhight;
            width = newwidth;
            texture = newtexture;
            speed = 5;
            rectangle = new Rectangle((width - texture.Width +5), hight / 2, texture.Width/2, texture.Height / 4);

            //end

        }


        public void Update(Rectangle newball)
        {
            //updates AI on ball location
            ball = newball;
            //checks if out
            isout();
            //Ai movement
            movement();


        }
        public void Draw(SpriteBatch spritebatch)
        {
            //start

            spritebatch.Draw(texture, rectangle, Color.White);

            //end
        }
        private void isout()
        {
            //start
            if (rectangle.Y < 0)
            {
                rectangle.Y = 0;
            }
            if (rectangle.Y > hight - rectangle.Height)
            {
                rectangle.Y = hight - rectangle.Height;
            }
            //end
        }
        private void movement()
        {
            //start
            if (ball.Y > rectangle.Y)
            {
                rectangle.Y = rectangle.Y + speed;
            }
            if (ball.Y < rectangle.Y)
            {
                rectangle.Y = rectangle.Y - speed;
            }

            //end
        }


        ///end
       
    }
}

What we now need to do just like for player one is add it into the Game1 class so under where you have added player one;
add the following
Code: Select all
AI two;
now that we have added the AI variable we need to load it into game so under one = new player(Content.Load<Texture2D>("player"),graphics.PreferredBackBufferHeight,graphics.PreferredBackBufferWidth);
add the following
Code: Select all
 two = new AI(Content.Load<Texture2D("player2"),graphics.PreferredBackBufferHeight,graphics.PreferredBackBufferWidth);
As this code acts the same for player one there is not really a need to explain it because it does the same job as before.
now what we need to do is add the updates part so under one.update(); add the following
Code: Select all
   two.Update(ballone.rectangle);
unlike player one as you see here we have a ballone.rectangle this will be the public rectangle from the ball class that we will be adding next so if you want to currently test it what you will need to do is replace that with
Code: Select all
 one.rectangle
and what that will do is make it follow your player one's bat instead of the ball so that you can test it but remember to add the ballone.rectangle later so that it will follow the ball.

now what we need to do is to draw it so under where you have one.Draw(spriteBatch);
add the following
Code: Select all
  two.Draw(spriteBatch);
as before it does the same thing that one.Draw(spritebatch) does so there is no need for me to explain the same thing to you again as that would be pointless.

Ball

To start off with once more what we will be doing is creating a new class this time i will be calling it ball as before you can change the name of the class to anything you want as long as you adapt the code to what ever you have named it too.

so to start off with under systems.text; add the following
Code: Select all
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
now once we have added that under class ball
{
add the following variables
Code: Select all
 public Rectangle rectangle,one,two;
        Texture2D texture;
        int hight, width;
        public int scoreone,scoretwo;
        Vector2 speed;
as you see here we don't just have the rectangles for just the ball on its own but also player one and two this is used so that the ball can bounce off both of the pads just like player one and two we also have the height and width and this has the same purpose so that we can keep the ball within the boundary's of the screen. we also have a public int scoreone and scoretwo what this does is keep track of the scores of both players and lastly we have a vector2 for speed this sets the speed of the ball like the int speed did for the AI's movement but we will be using vector2 instead because both the X and the Y will have speeds of there own depending on what they hit and bounce off of.

what we will now need to do is add the following bit of code below
Code: Select all

public ball(Texture2D newtexture,int newhight,int newwidth)
        {
            texture = newtexture;
            hight = newhight;
            width = newwidth;
            speed.X = 4f;
            speed.Y = 4f;
            rectangle = new Rectangle(width / 2, hight / 2, texture.Width, texture.Height);
        }
just like player one and two this is what we will be using to load everything into the game but as you see here we also have speed.x and speed.y set to 4f this is currently the speed at which the ball will go at.

next we will add the following
Code: Select all
 public void Update(Rectangle newone, Rectangle newtwo)
        {
            //updates playerone and two's location
            one = newone;
            two = newtwo;
            //movement
            movement();
            //does it need to bouce?
            bounce();


        }
as you see here the ball get's the location of both player one and player two as well as have it's own movement class just like the AI does but unlike the AI it also has a bounce class. This is where it will bounce of the sides and off the players pads them self so to start off with we will be working on the private void for the movement.

so add the following.
Code: Select all
private void movement()
    {
            //start
        rectangle.X = rectangle.X + (int)speed.X;
        rectangle.Y = rectangle.Y + (int)speed.Y;
            //end

    }
what this does is add the value of speed to the value of x/y on the rectangle making it move in that direction a positive speed added to the rectangle will make it move in one direction while a negative speed will make it move in the other.

now that we have added that what we will be adding next is bounce feature so under this add the following
Code: Select all

private void bounce()
        {
            //start
            //pads
            if (rectangle.Intersects(one))
            {
                speed.X = -speed.X;
               
            }
            if (rectangle.Intersects(two))
            {
                speed.X = -speed.X;
            }
            //walls
            if (rectangle.X < 0)
            {
                score(2);

            }
            else if (rectangle.Y < 0)
            {

                speed.Y = -speed.Y;
                if (speed.X > 0)
                {
                    speed.X = speed.X + 1;
                }
                if (speed.X < 0)
                {
                    speed.X = speed.X - 1;
                }
            }
            else if (rectangle.X > width - texture.Width)
            {

                score(1);
            }
            else if (rectangle.Y > hight - texture.Height)
            {

                speed.Y = -speed.Y;
                if (speed.X > 0)
                {
                    speed.X = speed.X + 1;
                }
                if (speed.X < 0)
                {
                    speed.X = speed.X - 1;
                }

            };
          
            //end
        }
as you see unlike we added for if the ball goes out of the screen instead it just changes the value of speed making it look like it bounce of the edge of the screen and pads.

what we have also added is a line of code for that every time it hits the sides of the walls it adds one to the speed of the ball meaning that as the game goes on the ball will pick up speed making the game harder as it goes along until the ball is moving to past for a player to react in time.

as you see we have a private void score() that we use to show when a player scores so what we will be now doing is adding that private void so under enter the following
Code: Select all
 private void score(int player)
        {
            if (player == 1)
            {
                scoreone = scoreone + 1;
                resetball();
                
            }
            else if (player == 2)
            {
                scoretwo = scoretwo + 1;
                resetball();
            }

        }
what this does is get a int value of which player scored so if it was player one the value would be one and it would reset the ball and add one to that players score but just like this private void the resetball() is also a private void of it's own so under here we will be adding that so under this line of code add the following
Code: Select all
private void resetball()
        {
            rectangle = new Rectangle(width / 2, hight / 2, texture.Width, texture.Height);
            speed.X = 4;
            speed.Y = 4;
        }
what this bit of code does is that every time it is run it resets the rectangle of the ball and resets the speed to the speed it was before.

now that we have added that just like playerone and so on we will be needing to draw it to the screen so under here enter the following.
Code: Select all
  public void Draw(SpriteBatch spritebatch)
        {
            spritebatch.Draw(texture, rectangle, Color.White);


        }
once you have added this your code should look somewhat like the following
Code: Select all
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace Pong
{
    class ball
    {
        public Rectangle rectangle,one,two;
        Texture2D texture;
        int hight, width;
        public int scoreone,scoretwo;
        Vector2 speed;
        public ball(Texture2D newtexture,int newhight,int newwidth)
        {
            texture = newtexture;
            hight = newhight;
            width = newwidth;
            speed.X = 4f;
            speed.Y = 4f;
            rectangle = new Rectangle(width / 2, hight / 2, texture.Width, texture.Height);
        }
        public void Update(Rectangle newone, Rectangle newtwo)
        {
            //updates playerone and two's location
            one = newone;
            two = newtwo;
            //movement
            movement();
            //does it need to bouce?
            bounce();


        }
        public void Draw(SpriteBatch spritebatch)
        {
            spritebatch.Draw(texture, rectangle, Color.White);


        }
        private void movement()
    {
            //start
        rectangle.X = rectangle.X + (int)speed.X;
        rectangle.Y = rectangle.Y + (int)speed.Y;
            //end

    }
        private void bounce()
        {
            //start
            //pads
            if (rectangle.Intersects(one))
            {
                speed.X = -speed.X;
               
            }
            if (rectangle.Intersects(two))
            {
                speed.X = -speed.X;
            }
            //walls
            if (rectangle.X < 0)
            {
                score(2);

            }
            else if (rectangle.Y < 0)
            {

                speed.Y = -speed.Y;
                if (speed.X > 0)
                {
                    speed.X = speed.X + 1;
                }
                if (speed.X < 0)
                {
                    speed.X = speed.X - 1;
                }
            }
            else if (rectangle.X > width - texture.Width)
            {

                score(1);
            }
            else if (rectangle.Y > hight - texture.Height)
            {

                speed.Y = -speed.Y;
                if (speed.X > 0)
                {
                    speed.X = speed.X + 1;
                }
                if (speed.X < 0)
                {
                    speed.X = speed.X - 1;
                }

            };
          
            //end
        }
        private void score(int player)
        {
            if (player == 1)
            {
                scoreone = scoreone + 1;
                resetball();
                
            }
            else if (player == 2)
            {
                scoretwo = scoretwo + 1;
                resetball();
            }

        }
        private void resetball()
        {
            rectangle = new Rectangle(width / 2, hight / 2, texture.Width, texture.Height);
            speed.X = 4;
            speed.Y = 4;
        }
    }
}

now what we need to do is to add this into Game1 so below AI two; in the game1 class add the following
Code: Select all
ball ballone;
now what we need to do is to load our ball into the game so under
two = new AI(Content.Load<Texture2D>("bat/player2"), graphics.PreferredBackBufferHeight,graphics.PreferredBackBufferWidth);
add the following
Code: Select all
 ballone = new ball(Content.Load<Texture2D>("ball"),graphics.PreferredBackBufferHeight,graphics.PreferredBackBufferWidth);
now what we need to do is update it so that it can move around the screen and what not so under two.Update(ballone.rectangle);
add the following
Code: Select all
ballone.Update(one.rectangle, two.rectangle);
as you see here unlike two that only got the location of the ball this gets the location of both of the players.
now what we need to do is to draw it into game so under two.Draw(spriteBatch);
add the following
Code: Select all
 ballone.Draw(spriteBatch);
Score's Text - Displaying the players score's



Now that we have got the game it's self done what we need to do now is add the score board to it so to do this what we will do is make a class once more called text and inside there add the following under using System.Text;
Code: Select all
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

now that we have got that done under class text
{
add the following
Code: Select all
 string stringtext;
        Vector2 pos;
        SpriteFont font;
        Color stringcolor = Color.White;

as you see these are slightly different to the ones you seen before this time we will be using the color variable but we will set it to white by default as well as this we are using a vector2 for the positioning of the text and not a rectangle and we are using a sprite font instead of a texture2D because we are going to load text not a texture.

what we now need to do is right click the content in the side above references go over to add on the menu and click add new when a menu opens up add a new sprite front in this example i will be calling it SF but you are free to call it what you like and click add.

now that we have that done add this following bit of code below the variables.
Code: Select all
 public text(string newtext, Vector2 newpos, SpriteFont newfont)
        {
            stringtext = newtext;
            pos = newpos;
            font = newfont;

        }

as you see here we are getting the text of what the text will say were we want it to be placed and the sprite font we are going to use from Game1 when we load it into game.

now what we want to do is add the following bit of code below.
Code: Select all
   public void update(string newtext,int scoreone,int scoretwo)
        {
            stringtext = newtext;

            if (scoreone == scoretwo)
            {
                stringcolor = Color.White;
            }
            if (scoreone > scoretwo)
            {
                stringcolor = Color.Blue;
            }
            if (scoreone < scoretwo)
            {
                stringcolor = Color.Red;
            }
        }
as you see here we are using the update method to update our code in game however as you see here it gets both scores from game1 and as you see if one team gets higher then the other it will change colour to that teams bat by changing the color variable.

now that we have done that we need to add a draw method so under this bit of code enter the following.
Code: Select all
 public void Draw(SpriteBatch spritebatch)
        {
            spritebatch.DrawString(font, stringtext, pos, stringcolor);
        }
as you see like player one and so on it uses the spritebatch function but instead of draw it uses drawstring meaning that it will draw text instead of a sprite.

if you have made this class right what you should have is close to the following.
Code: Select all
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Pong
{
    class text
    {
        string stringtext;
        Vector2 pos;
        SpriteFont font;
        Color stringcolor = Color.White;
        public text(string newtext, Vector2 newpos, SpriteFont newfont)
        {
            stringtext = newtext;
            pos = newpos;
            font = newfont;

        }

        public void update(string newtext,int scoreone,int scoretwo)
        {
            stringtext = newtext;

            if (scoreone == scoretwo)
            {
                stringcolor = Color.White;
            }
            if (scoreone > scoretwo)
            {
                stringcolor = Color.Blue;
            }
            if (scoreone < scoretwo)
            {
                stringcolor = Color.Red;
            }
        }
        public void Draw(SpriteBatch spritebatch)
        {
            spritebatch.DrawString(font, stringtext, pos, stringcolor);
        }
    
    
    
    
    }


}

now that we have gotten this done what we need to do is to add it to game1 so under ball ballone; in the game1 class enter the following
Code: Select all
text score;
as this works just like the others there is no need to explain this as you should already know what this does now what we need to do is to add the loader so under ballone = new ball(Content.Load<Texture2D>("ball"),graphics.PreferredBackBufferHeight,graphics.PreferredBackBufferWidth); add the following
Code: Select all
score = new text((ballone.scoreone+" : "+ballone.scoretwo),new Vector2((graphics.PreferredBackBufferWidth/2)-5,10),Content.Load<SpriteFont>("sf"));
as you see here the text is just ball ones score for example 0 a : and ball two's score which for example could be 0 once more so that it would look like 0 : 0 in game.

now what we need to do is update this so under ballone.Update(one.rectangle, two.rectangle); add the following
Code: Select all
score.update(ballone.scoreone + " : " + ballone.scoretwo,ballone.scoreone,ballone.scoretwo);
what this does is update what the text says as well as telling the text ball one's and ball's two score so it can update its colours accordingly.

now that we have added this what we now need to do is too draw it in game so under ballone.Draw(spriteBatch); add the following
Code: Select all
score.Draw(spriteBatch);
and there we go you have a working scoreboard.

Flashing Point scored text
Now that we have added the score what we can do now is more of an optional thing but add's to the looks of the game so what we will do to start off with is create a new class called scoretext or what ever you would like to call it if you adapt the code.

what we will first do is add the reference's so under using System.Text; add the following
Code: Select all
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

now that we have got that done add the following variables under class scoretext
{
Code: Select all
SpriteFont sf;
        string txt;
        Vector2 location;
        Color color = Color.White;
        int one, two, scoretimer;
as you see here once more we have got the sprite fonts and text for the text as well as a vector2 location and colour but we also have the scores of the players and a score timer that we will use to count down how long the text will display in frames.
so under here enter the following
Code: Select all
 public scoretext(SpriteFont newsf, string newstring, Vector2 newlocation,int newplayerone, int newplayertwo)
        {
            sf = newsf;
            txt = newstring;
            location = newlocation;
            one = newplayerone;
            two = newplayertwo;
           

        }
as you see here this does almost the same thing as it does for the score text apart from get the scores of player one and player two. under here enter the following update method
Code: Select all

public void Update(int newplayerone, int newplayertwo)
        {
            if (newplayerone == one == false)
            {
                color = Color.Blue;
                scoretimer = 100;
            }
            if (newplayertwo == two == false)
            {
                color = Color.Red;
                scoretimer = 100;
            }
            one = newplayerone;
            two = newplayertwo;
            if (scoretimer > 0)
            {
                scoretimer = scoretimer - 1;
            }
        }
as you see here it compares the new scores to the old scores if one of them changes it would mean that that player had scored there for it changes the colour of the text to that player and increases the score time to 100 because of this the score timer then takes away 1 for every frame that goes by there for the score timer will go in that set amount of frames.
now what we need to do is to draw it into the game so under here enter the following
Code: Select all
 public void Draw(SpriteBatch spritebatch)

        {
            if (scoretimer > 0)
            {
                spritebatch.DrawString(sf, txt, location, color);
            }
        }
as you see here it also uses the score timer as long as the score timer is equal to more then 0 it will draw the sprite to the screen when it is not it will no longer draw the sprite to the screen.

if you have done this correctly the class should look like this:
Code: Select all
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Pong
{
    class scoretext
    {
        SpriteFont sf;
        string txt;
        Vector2 location;
        Color color = Color.White;
        int one, two, scoretimer;
        public scoretext(SpriteFont newsf, string newstring, Vector2 newlocation,int newplayerone, int newplayertwo)
        {
            sf = newsf;
            txt = newstring;
            location = newlocation;
            one = newplayerone;
            two = newplayertwo;
           

        }

        public void Update(int newplayerone, int newplayertwo)
        {
            if (newplayerone == one == false)
            {
                color = Color.Blue;
                scoretimer = 100;
            }
            if (newplayertwo == two == false)
            {
                color = Color.Red;
                scoretimer = 100;
            }
            one = newplayerone;
            two = newplayertwo;
            if (scoretimer > 0)
            {
                scoretimer = scoretimer - 1;
            }
        }
        public void Draw(SpriteBatch spritebatch)

        {
            if (scoretimer > 0)
            {
                spritebatch.DrawString(sf, txt, location, color);
            }
        }


    }


}

now that we have this done we need to add it into the game1 class so under text score; in the game1 class enter the following
Code: Select all
scoretext textscore;
now that we have that done we need to load it into game so under score = new text((ballone.scoreone+" : "+ballone.scoretwo),new Vector2((graphics.PreferredBackBufferWidth/2)-5,10),Content.Load<SpriteFont>("sf")); enter the following
Code: Select all
  textscore = new scoretext(Content.Load<SpriteFont>("sf"), ("Point Scored!"), new Vector2(graphics.PreferredBackBufferWidth / 2, graphics.PreferredBackBufferHeight / 2), ballone.scoreone, ballone.scoretwo);
as you see here we are using the same sprite fount to save time in creating a new one but you don't have to if you would want to use a different size sprite or font.
now what we need to do is update it so under score.update(ballone.scoreone + " : " + ballone.scoretwo,ballone.scoreone,ballone.scoretwo); enter the following
Code: Select all
    textscore.Update(ballone.scoreone,ballone.scoretwo);
as you see here it updates it on the score of pad one and pad two
now what we need to do is draw it into game so under score.Draw(spriteBatch); enter the following
Code: Select all
 textscore.Draw(spriteBatch);
if you have done this right game1 should look somewhat like this:
Code: Select all
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Pong
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        player one;
        AI two;
        ball ballone;
        text score;
        scoretext textscore;
      

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

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
            
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            ballone = new ball(Content.Load<Texture2D>("ball"),graphics.PreferredBackBufferHeight,graphics.PreferredBackBufferWidth);
            one = new player(Content.Load<Texture2D>("player"),graphics.PreferredBackBufferHeight,graphics.PreferredBackBufferWidth);
            two = new AI(Content.Load<Texture2D>("player2"), graphics.PreferredBackBufferHeight, graphics.PreferredBackBufferWidth);
            score = new text((ballone.scoreone+" : "+ballone.scoretwo),new Vector2((graphics.PreferredBackBufferWidth/2)-5,10),Content.Load<SpriteFont>("sf"));
            textscore = new scoretext(Content.Load<SpriteFont>("sf"), ("Point Scored!"), new Vector2(graphics.PreferredBackBufferWidth / 2, graphics.PreferredBackBufferHeight / 2), ballone.scoreone, ballone.scoretwo);
            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content. 
        ///
        /// </summary>
        
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            //Ball's logic
            ballone.Update(one.rectangle, two.rectangle);
            //Player one's logic
            one.update();
            //Player two logic
            two.Update(ballone.rectangle);
          
          
            //Menu

            //Score
            score.update(ballone.scoreone + " : " + ballone.scoretwo,ballone.scoreone,ballone.scoretwo);
            textscore.Update(ballone.scoreone,ballone.scoretwo);



            // TODO: Add your update logic here

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
            spriteBatch.Begin();
            // text
            score.Draw(spriteBatch);
            textscore.Draw(spriteBatch);

            //Draw one
            one.Draw(spriteBatch);
            //Draw Two
            two.Draw(spriteBatch);
            //Draw ball
            ballone.Draw(spriteBatch);

            spriteBatch.End();
            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }
    }
}

useful notes:
when creating a new class remember that you always need to add to references at the top of the class so that it can use XNA stuff.

when adding content you can put them into folders to put instead of ("player1") it would be ("folder/player1")

How to make this game work for xbox 360
Now that we have created the basic code for the pc making this game playable on the xbox 360 is simpler then you think to start off with just click the windows icon with your project name in the solution explorer and click "Create a copy of project for xbox 360" now what you will see is a mirror of your project but with a xbox 360 icon this will be the version of the game that will start up in xbox 360 (shocking i know!) but before we can run it we will have to make some slight changes to our controls as currently they only work with the keyboard.

so to start with open the player class remember were we pasted the keyboard code? now we are going to make a private void for the game pad as well but remember to keep the keyboard bit of code if you intend to be able to play it on the computer.

to start off with we will need to add a variable called GamePadState so under int hight, width; add the following
Code: Select all
GamePadState gamepad1;
now that we have done that under
private void keyboard()
{
kb = Keyboard.GetState();
if (kb.IsKeyDown(Keys.Down) == true)
{
rectangle.Y = rectangle.Y + 5;
}
if (kb.IsKeyDown(Keys.Up) == true)
{
rectangle.Y = rectangle.Y - 5;
}
}
enter the following
Code: Select all
  private void gamepad()
        {
            if (gamepad1.IsButtonDown(Buttons.DPadDown))
            {
                rectangle.Y = rectangle.Y + 5;
            }
            if (gamepad1.IsButtonDown(Buttons.DPadUp))
            {
                rectangle.Y = rectangle.Y - 5;
            }

            if (gamepad1.IsButtonDown(Buttons.LeftThumbstickDown))
            {
                rectangle.Y = rectangle.Y + 5;
            }
            if (gamepad1.IsButtonDown(Buttons.LeftThumbstickUp))
            {
                rectangle.Y = rectangle.Y - 5;
            }
        }
as you see here it works in quite a similar way the keyboard does in the way this works as you see if have done this not only with the D-Pad but also with the thumb stick so players can have a pick of what they want to use to control the game.

now what we need to do is add this to our update methods so under isout(); in public void update() add the following
Code: Select all
    gamepad();
now that we have done that let's go into the ball class and add some vibration feed back to the player!

so in the ball class what we first need to do is add our variables so under Vector2 speed; add the following
Code: Select all
GamePadState gamepad1 = GamePad.GetState(PlayerIndex.One);
 int vibrationtime = 0;
as you see I have also set it to get the game pad state of player one since this is a one player game at the moment this is completely fine to do although if you plan on adding more players you may want to make more then one game state now under
private void resetball()
{
rectangle = new Rectangle(width / 2, hight / 2, texture.Width, texture.Height);
speed.X = 4;
speed.Y = 4;
}
add the following
Code: Select all

 private void vibration()
        {

            if (gamepad1.IsConnected)
            {
                vibrationtime = 30;
            }
            if (vibrationtime > 0)
            {
                GamePad.SetVibration(PlayerIndex.One, 1.0f, 1.0f);
            }
            if (vibrationtime == 0)
            {
                GamePad.SetVibration(PlayerIndex.One, 0f, 0f);
            }
        }
as you see here this will only work if the game pad is connected so we have made sure that the code will only run if it is as you see here when vibration time is > 0 we set the pad off the time can be changed depending on your linking however remember that long periods of vibration after time will start to annoy your players.
now what we need to do is add this to the bounce part so delete
Code: Select all
    private void bounce()
        {
            //start
            //pads
            if (rectangle.Intersects(one))
            {
                speed.X = -speed.X;
               
            }
            if (rectangle.Intersects(two))
            {
                speed.X = -speed.X;
            }
            //walls
            if (rectangle.X < 0)
            {
                score(2);

            }
            else if (rectangle.Y < 0)
            {

                speed.Y = -speed.Y;
                if (speed.X > 0)
                {
                    speed.X = speed.X + 1;
                }
                if (speed.X < 0)
                {
                    speed.X = speed.X - 1;
                }
            }
            else if (rectangle.X > width - texture.Width)
            {

                score(1);
            }
            else if (rectangle.Y > hight - texture.Height)
            {

                speed.Y = -speed.Y;
                if (speed.X > 0 & speed.X < 12)
                {
                    
                    
                        speed.X = speed.X + 1;
                   
                  
                }
                if (speed.X < 0 & speed.X < 12)
                {
                 
         
                        speed.X = speed.X - 1;
                    
                }

            };
          
            //end
        }
and replace it with the following
Code: Select all
private void bounce()
        {
            //start
            //pads
            if (rectangle.Intersects(one))
            {
                speed.X = -speed.X;
                vibration();
               
            }
            if (rectangle.Intersects(two))
            {
                speed.X = -speed.X;
                vibration();
            }
            //walls
            if (rectangle.X < 0)
            {
                score(2);
                vibration();

            }
            else if (rectangle.Y < 0)
            {

                speed.Y = -speed.Y;
                if (speed.X > 0)
                {
                    speed.X = speed.X + 1;
                }
                if (speed.X < 0)
                {
                    speed.X = speed.X - 1;
                }
            }
            else if (rectangle.X > width - texture.Width)
            {

                score(1);
                vibration();
            }
            else if (rectangle.Y > hight - texture.Height)
            {

                speed.Y = -speed.Y;
                if (speed.X > 0 & speed.X < 12)
                {
                    
                    
                        speed.X = speed.X + 1;
                   
                  
                }
                if (speed.X < 0 & speed.X < 12)
                {
                 
         
                        speed.X = speed.X - 1;
                    
                }

            };
          
            //end
        }
and there we have it! it will now vibrate every time it hits the bats and the scoring wall!
Last edited by reececlarke on Mon Apr 29, 2013 8:39 pm, edited 31 times in total.
Image
User avatar
Shim
VIP - Donator
VIP - Donator
Posts: 882
Joined: Wed Dec 14, 2011 5:02 am

Re: Pong
Shim
i don't know about XNA but the tutorial seems interesting ! add some pictures to the thread that explains more than what words do ! +rep
Find my programs on Softpedia
User avatar
comathi
Coding God
Coding God
Posts: 1242
Joined: Fri Mar 26, 2010 1:59 pm

Re: Pong
comathi
Dang it lol. I was also making a Pong game... and planning to release a tut. It's in JavaScript though, so I might still post it :lol:

Very nice tutorial, though. But as mshimranpro said, it would be nice to have images. cooll;

+rep
User avatar
reececlarke
VIP - Donator
VIP - Donator
Posts: 245
Joined: Tue Dec 08, 2009 6:47 pm

Re: Pong
reececlarke
I will add the images after I have done the code and text and what not for the tutorials (also added AI and ball classes now as well)
Image
User avatar
smashapps
Coding Guru
Coding Guru
Posts: 961
Joined: Tue Apr 05, 2011 8:41 am

Re: Pong - Tutorial
smashapps
I've been waiting for someone to post an XNA tutorial here. You've done a very nice job on this.

Do you plan to make any other tutorials in XNA? +rep
My name is Tom | Visit my blog where I post new content every day! Tom's Daily Blog | MineCraft is awesome!
User avatar
reececlarke
VIP - Donator
VIP - Donator
Posts: 245
Joined: Tue Dec 08, 2009 6:47 pm

Re: Pong - Tutorial
reececlarke
Yes in the future I plan to add more XNA tutorials as i learn more about it =P
Image
User avatar
smashapps
Coding Guru
Coding Guru
Posts: 961
Joined: Tue Apr 05, 2011 8:41 am

Re: Pong - Tutorial
smashapps
You should provide Visual Basic code too or tutorials in vb xna. Only downfall with that is you have to have Windows Phone SDK installed :(
My name is Tom | Visit my blog where I post new content every day! Tom's Daily Blog | MineCraft is awesome!
User avatar
reececlarke
VIP - Donator
VIP - Donator
Posts: 245
Joined: Tue Dec 08, 2009 6:47 pm

Re: Pong - Tutorial
reececlarke
Now added new Xbox 360 section so that the game will work on the 360 as well as the computer =P
Image
8 posts Page 1 of 1
Return to “Tutorials”