You are on page 1of 10

XNA 4.

0 Break Out Tutorials

Part 1

Ball and Paddle

I'm writing these tutorials for the new XNA 4.0 framework. The tutorials will make more sense if they
are read in order. You can find the list of tutorials on the XNA 4.0 Tutorials page of my web site. I will
be making my version of the project available for download at the end of each tutorial. It will be
included on the page that links to the tutorials.

This is a beginner tutorial on creating a Break Out style game. I will be writing tutorials in the
future on creating the game using object-oriented programming principles. The tutorial is more to
introduce XNA with a more or less complete game. It won't go into state management but it will be a
functional brick breaking game.

To get started create a new XNA 4.0 game and call it BreakingOut. In the Break Out game there are
three different game objects. There is the ball, the paddle, and the bricks. I will start by adding the
paddle. The paddle is at the bottom of the screen. The object is to bounce the ball off the paddle and
break the bricks on the screen. When all of the bricks have been destroyed game play moves to the next
level. The paddle will be controlled by either the left and right arrow keys on the keyboard, the left
thumb stick on a game pad or the direction pad on a game pad. You need to make sure that the paddle
does not go off the left or right edges of the screen.

I will be using a class to control the paddle. C# is an object-oriented programming language and it is a
good idea to use object-oriented programming ideas when working on games. Right click the game in
the solution explorer, select Add and then Class. Name this class Paddle. The code for the Paddle
class follows next. If you've read any of my tutorials I usually explain code after you've had a chance to
read it.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace BreakingOut
{
class Paddle
{
Vector2 position;
Vector2 motion;
float paddleSpeed = 8f;

KeyboardState keyboardState;
GamePadState gamePadState;

Texture2D texture;
Rectangle screenBounds;
public Paddle(Texture2D texture, Rectangle screenBounds)
{
this.texture = texture;
this.screenBounds = screenBounds;
SetInStartPosition();
}

public void Update()


{
motion = Vector2.Zero;

keyboardState = Keyboard.GetState();
gamePadState = GamePad.GetState(PlayerIndex.One);

if (keyboardState.IsKeyDown(Keys.Left) ||
gamePadState.IsButtonDown(Buttons.LeftThumbstickLeft) ||
gamePadState.IsButtonDown(Buttons.DPadLeft))
motion.X = -1;

if (keyboardState.IsKeyDown(Keys.Right) ||
gamePadState.IsButtonDown(Buttons.LeftThumbstickRight) ||
gamePadState.IsButtonDown(Buttons.DPadRight))
motion.X = 1;

motion.X *= paddleSpeed;
position += motion;
LockPaddle();
}

private void LockPaddle()


{
if (position.X < 0)
position.X = 0;
if (position.X + texture.Width > screenBounds.Width)
position.X = screenBounds.Width - texture.Width;
}

public void SetInStartPosition()


{
position.X = (screenBounds.Width - texture.Width) / 2;
position.Y = screenBounds.Height - texture.Height - 5;
}

public void Draw(SpriteBatch spriteBatch)


{
spriteBatch.Draw(texture, position, Color.White);
}

public Rectangle GetBounds()


{
return new Rectangle(
(int)position.X,
(int)position.Y,
texture.Width,
texture.Height);
}
}
}

The Paddle class controls all aspects of the paddle. Where it is positioned, updating its position from
the player's input, and drawing the paddle. To do that I needed to add in a few using statements at the
start of the class. Using statements, in this context, allow you to reference items inside of a name space
with out including the name of the name space or bring them into scope is something you will read
often. For example, the using statement using System allows you to use Int32 instead of
System.Int32.
A Vector2 is a data type that has an X and Y property and can be used for a variety of purposes. The
Vector2 called position is the position of the paddle in 2D space. You can think of two dimensional
space as your computer screen. The X axis runs from left to right across your screen. The Y axis runs
from top to bottom down your screen. This is the opposite of math where as you move up the Y axis
values of Y increase and as you move down values of Y decrease. It was much simpler when computers
first started using screens to do it this way.

The Vector2 called motion has a different meaning. This Vector2 holds the direction the player is
trying to move the paddle. The paddle can only move in one dimension, left and right, to the Y property
of motion will be ignored. Using a Vector2 for the motion of the paddle will make controlling the
paddle easier.

The float field is the number of pixels the paddle moves left or right if the left or right key is down or
the left thumb stick on the game pad is pressed to the left or the right. Having this defined like this in
the class makes it easier to change the speed of the paddle. You should never use magic numbers in
your code. Always have fields that you can change to easily change their values.

The fields keyboardState and gamePadState are fields that pixels the paddle moves left or right if the
left or right key is down or the left thumb stick on the game pad is pressed to the left or the right.
Having this defined like this in the class makes it easier to change the speed of the paddle. You should
never use magic numbers in your code. Always have fields that you can change to easily change their
values.

The last two fields are texture which is of type Texture2D and screenBounds which is a Rectangle.
To draw a two dimensional object, often referred to as a sprite, you use the Texture2D class for the
object to be drawn. The other field is a Rectangle that represents the surface the game is taking place
on. You will frequently use a Rectangle in 2D game programming, especially when it comes to
checking if two objects collide or not, like the ball and the paddle or the ball and a brick.

The constructor for the class takes two parameters. The first one, texture, is the image I used for the
paddle. I will get to add the image in a moment. The other is screenBounds, the rectangle that
describes the area the paddle operates in. Constructors are used to create instances, or objects, of a
class. You will create an instance of the Paddle class in the Game1 class.

The Update method is where the paddle is updated. It checks for input from the player to see if the
paddle should be moved. I first reset the motion field to Vector2.Zero. That returns the X and Y
properties of motion to zero. I then capture the state of the keyboard and the game pad referenced by
PlayerIndex.One. The reason is that there can be more than one controller on the Xbox 360 and you
can use XNA to make games for the Xbox 360. Ideally you shouldn't force the player to a game pad
that is the first one but I'm not going to get into that.

KeyboardState has a method called IsKeyDown that returns true if the key passed in is currently
down. Similarly, GamePadState has a method called IsButtonDown that returns true if a button on
the game pad is currently down. I lumped checking for moving the paddle left or right into one if
statement. I use a logical or to check if the paddle should be moved. A logical or means that if any of
the conditions is true then the whole expression is true. One nice thing about C# is that as it checks the
values if one is found to be true the rest of the expressions won't be checked. So, if the left arrow key is
down then the checks for the left thumb stick left or direction left aren't evaluated. If the player is
trying to move the paddle left. If any of the left conditions are true I set the X property of motion to -1
because as you move left across the screen the value of X decreases. There is a similar if statement to
check to see if the paddle should be moved right. If that is true the X property of motion is set to 1.

Now that I have the motion vector, which describes what way the player wants to move the paddle, I
multiply it by the speed of the paddle. I then add this motion to the paddle's position and call the
method LockPaddle that makes sure the paddle stays on the screen.

Like I just mentioned, the LockPaddle method makes sure the paddle doesn't go off the screen. To
make sure it doesn't go off the left hand side of the screen you make sure that its X value is never less
than zero. Making sure it doesn't go off the right side of the screen is a little more complex. If you just
check to see if its X value is less than the width of the screen it will disappear off the right side of the
screen. You need to check its position plus its width. The Texture2D class has a property called Width
that holds the width of the texture. It also has a property Height that holds the height of the texture. If
the position of the paddle, plus its width, is greater than the width of the screen, I set the position of the
paddle to with width of the screen minus the width of the paddle.

The next method in the class is the SetInStartPosition method. This method will return the paddle to
where it starts. To center the paddle horizontally you take the width of the screen, subtract the width of
the paddle and then divide that value by 2. To place the paddle at the bottom of the screen you take the
height of the screen and subtract the height of the paddle. I also removed 5 pixels so that the paddle
will be a little off the bottom of the screen.

The next method is the Draw method. This method draws the paddle. To draw a Texture2D you need a
SpriteBatch object, that is why there is parameter. The Draw method of the SpriteBatch class has
several overloads. The one that I used takes as parameters, the Texture2D to be drawn, a Vector2 for
the position to draw the object, and tint Color. You can use the last parameter to tint your sprites. If you
use white there will be no tinting. If you use black the sprite will be drawn black.

The last method in this class is the GetBounds method. This method returns a Rectangle that describes
the paddle. It will be used for detecting collisions between the paddle and the ball. I will get more into
that a little later. To create the Rectangle I cast the X and Y values of position to integers because they
are float values. I also use the height and width of the texture of the paddle.

Let's add the paddle to the game. The first thing that you are going to need is a graphic for the paddle
and for the ball in the game. It would be better if you used the same ones that I used. You can download
them from my web site at the following link: http://xnagpa.net/Downloads/breakingout1.zip

After you have unzipped the graphics, you need to add the paddle to the game so it can be loaded. In
your game solution there is a special project called BreakingOutContent. This project holds all of the
assets, or content, for you game such as images and audio. Right click the BreakingOurContent
project and select the Add existing item option. Navigate to where you unzipped the graphics and
select the paddle.png file. This adds the image to your game and you will be able to load it using the
Content Pipeline.

The Content Pipeline is what XNA uses to load content into your game. XNA compiles your resources
into a protected format that would not be as easy to modify as raw images and other data. This protects
your assets from being modified or copied, a pretty good idea. The Content Pipeline has many built in
processors for important images, audio, 3D models, and other items. If you need to you can extend the
Content Pipeline to work on custom content. That is well beyond the scope of this tutorial though.
Now that you have the paddle image we can continue adding the paddle to the game. The first thing
you will need to do is add two fields to the Game1 class. Open the code for the Game1 class. At the
top of the class there is a SpriteBatch field and a GraphicsDeviceManager field. Just below those,
add the following two fields.
Paddle paddle;
Rectangle screenRectangle;

The first field is for your Paddle object. The second field is a Rectangle that describes the playing area
of the game. The field for the bounds of the screen needs to be initialized. That will be done in the
constructor of the Game1 class. Change to constructor to the following.
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";

screenRectangle = new Rectangle(


0,
0,
graphics.PreferredBackBufferWidth,
graphics.PreferredBackBufferHeight);
}

The new code in the constructor creates a new Rectangle that has the width and the height of the
window the game is in. The GraphicsDeviceManager class has two properties that hold the size of the
window the game runs in. The first, PreferredBackBufferWidth, holds the width of the window and
the second, PreferredBackBufferHeight, holds the height. When your games are drawing they draw
to a back buffer and the back buffer is flipped to the window all at once. This stops what is called
flicker.

XNA games have a special method called LoadContent where you should load the content for your
game. Since the Paddle class needs the Texture2D for the paddle I created the instance of the paddle in
the LoadContent method. Change the LoadContent method to the following.
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);

Texture2D tempTexture = Content.Load<Texture2D>("paddle");


paddle = new Paddle(tempTexture, screenRectangle);
}

Content is a variable of type ContentManager and is available in your Game1 class to load in your
content using the Content Pipeline. You use the Load method and place the type of content you want
to load between < and >. This is a form of generics and I'm not going to get into how generics work.
For the item you want to load you use the name of the file with out the extension. I mentioned earlier
that your content will be compiled to an encrypted format, typically an XNB file. That is why you do
not need the extension of the object. I then create an instance of the Paddle class using the texture I just
loaded and the screen bounds.

XNA games have two other methods that you will use in your games. The first is the Update method
and the second is the Draw method. Your game will try to call these methods 60 times per second.
Each time these methods are called is referred to a frame of the game. The Update method is where
you will preform the logic of your game and the Draw method is where you will draw the objects in
your game.

In the Update method, you will need to call the Update method of your paddle. This will allow your
paddle to receive its input and move across the screen. Change the Update method to the following.
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();

paddle.Update();

base.Update(gameTime);
}

The Draw needs to call the Draw method of your paddle. When I gave you the code for paddle, it took
a SpriteBatch object as a parameter. The Draw method of the SpriteBatch object must take place
between calls to Begin and End. Change the Draw method of the Game1 class to the following.

protected override void Draw(GameTime gameTime)


{
GraphicsDevice.Clear(Color.CornflowerBlue);

spriteBatch.Begin();

paddle.Draw(spriteBatch);

spriteBatch.End();

base.Draw(gameTime);
}

If you compile and run the game, the paddle should be at the bottom of the screen and you should be
able to move it left and right but not off the edge of the window. Now I will add a ball to the game.
Like the paddle, I will make a class for the ball. Right click your project in the Solution Explorer,
select Add and then Class. Name the class Ball. I will explain the code for the Ball class after you have
read it.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace BreakingOut
{
class Ball
{
Vector2 motion;
Vector2 position;
float ballSpeed = 4;

Texture2D texture;
Rectangle screenBounds;

public Ball(Texture2D texture, Rectangle screenBounds)


{
this.texture = texture;
this.screenBounds = screenBounds;
}

public void Update()


{
position += motion * ballSpeed;
CheckWallCollision();
}

private void CheckWallCollision()


{
if (position.X < 0)
{
position.X = 0;
motion.X *= -1;
}
if (position.X + texture.Width > screenBounds.Width)
{
position.X = screenBounds.Width - texture.Width;
motion.X *= -1;
}
if (position.Y < 0)
{
position.Y = 0;
motion.Y *= -1;
}
}

public void SetInStartPosition(Rectangle paddleLocation)


{
motion = new Vector2(1, -1);
position.Y = paddleLocation.Y - texture.Height;
position.X = paddleLocation.X + (paddleLocation.Width - texture.Width) / 2;
}

public bool OffBottom()


{
if (position.Y > screenBounds.Height)
return true;
return false;
}

public void PaddleCollision(Rectangle paddleLocation)


{
Rectangle ballLocation = new Rectangle(
(int)position.X,
(int)position.Y,
texture.Width,
texture.Height);

if (paddleLocation.Intersects(ballLocation))
{
position.Y = paddleLocation.Y - texture.Height;
motion.Y *= -1;
}
}

public void Draw(SpriteBatch spriteBatch)


{
spriteBatch.Draw(texture, position, Color.White);
}
}
}

The Ball class is similar to the Paddle class. There are using statements to bring a couple of the XNA
framework classes into scope. There is a field, motion, that is a Vector2 that describes the motion of
the ball. There is another Vector2, position, the is the position of the ball. The field ballSpeed is the
speed of the ball. The texture field is for the image of the ball and the screenBounds is the bounds that
the game takes place on.

The constructor for the class takes two parameters. The first one, texture, is the image I used for the
paddle. I will get to add the image in a moment. The other is screenBounds, the rectangle that
describes the area the ball operates in. It then sets the fields with the parameters passed in.

The Update method will be called to update the ball's position. What I do is add the motion of the ball
times the speed of to the ball's position and call the CheckWallCollision method to make sure the ball
doesn't go off the screen the left, right or top of the screen area.

The CheckWallCollision method first checks to see if the ball has moved off the left side of the screen
by checking if the X coordinate of the ball's position is less than zero. If it is, it sets the X coordinate to
0 and multiplies the X value of the ball's velocity by -1 which change the direction from moving left to
moving right. It then checks to see if the X coordinate of the ball, plus the ball's width, is greater than
the width of the screen, like checking to see if the paddle moved of the right side of the screen. If if its,
it set's the X coordinate to the width of the screen minus the width of the ball and multiplies the X
value of the ball's velocity by -1 again changing it's direction. It also checks to make sure the ball will
not travel off the top of the screen by checking that the Y coordinate of the ball is less than zero. If it is,
I set the Y coordinate of the ball to zero and multiply the Y value of the ball by -1 which changes the
vertical direction the ball is travelling.

The SetInStartPosition method takes a Rectangle parameter that describes the paddle's location. It
sets the Y coordinate of the ball to be the Y coordinate of the paddle minus the height of the ball so the
ball starts just above the paddle. To center the ball horizontally on the paddle you take the X coordinate
of the paddle and add the width of the paddle minus the width of the ball divided by two.

The OffBottom method checks to see if the ball has fallen off the bottom of the screen. To do this it
checks to see if the Y coordinate of the ball is greater than the height of the screen. If it is, the method
will return true. Otherwise, the method returns false.

The next method, PaddleCollision, checks to see if the ball collides with the paddle. It takes a
Rectangle that describes the location of the paddle. The method first makes a rectangle that describes
the location of the ball by taking its X and Y coordinates and the width and height of the texture. The
Rectangle class has a method called Intersects that will return true of the rectangle and the rectangle
specified by argument intersect. This is the easiest way to tell if two objects on the screen collide. If the
ball and the paddle collide, I set the Y coordinate of the ball's position to be the Y position of the paddle
minus the height of the ball, like in the SetInStartPosition method. I also change the direction the ball
is travelling by multiplying the Y value of its velocity by -1.

The last method in the class is the Draw method. The Draw method takes as a parameter a
SpriteBatch object. It then draws the ball like I drew the paddle.

Now I can add a ball to the game. Right click the BreakingOutContent project, select Add and then
Existing Item. Navigate to where you unzipped the images I used for the game and add the ball.png
image.

Now, switch to the code for the Game1 class. Up at the top of the Game1 class just below where you
added the field for the paddle add a field for the ball as follows with the paddle field.
Ball ball;

The next thing to do is to create the ball object. Like I did for the paddle, I did it in the LoadContent
method. I also added a call to a method StartGame that I haven't written yet. The code for the
LoadContent and StartGame methods follows next.
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);

Texture2D tempTexture = Content.Load<Texture2D>("paddle");


paddle = new Paddle(tempTexture, screenRectangle);

tempTexture = Content.Load<Texture2D>("ball");
ball = new Ball(tempTexture, screenRectangle);

StartGame();
}

private void StartGame()


{
paddle.SetInStartPosition();
ball.SetInStartPosition(paddle.GetBounds());
}

What the StartGame method does is reset the paddle to its starting position. It then resets the ball to
start with the paddle. It is important for the paddle to be positioned before the ball or the ball won't start
in the right position.

The next thing to do is in the Update method. There are now two objects in the game, the paddle and
the ball. You need to update both objects. You also need to check if the ball falls off the bottom of the
screen and goes out of play and if the paddle and the ball collide. Change the Update method as
follows.
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();

paddle.Update();
ball.Update();

ball.PaddleCollision(paddle.GetBounds());

if (ball.OffBottom())
StartGame();

base.Update(gameTime);
}

After calling the Update method of the paddle, I call the Update method of the ball. I update the ball
after the paddle to give the player the chance to get over to the ball before it falls of the screen. I then
call the OffBottom method of the ball in an if statement. If the ball is off the bottom of the screen it is
out of play and I call the StartGame method to set all of the objects back in their starting position. I
then call the PaddleCollision method of the ball passing in the rectangle that describes the paddle.
The last thing to do is to draw the ball. You do that in the Draw method. Just after drawing the paddle, I
call the Draw method of the ball passing in the SpriteBatch object. The code for the Draw method
follows.
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);

spriteBatch.Begin();

paddle.Draw(spriteBatch);
ball.Draw(spriteBatch);

spriteBatch.End();

base.Draw(gameTime);
}

I'm going to end this tutorial here. The plan was to get the paddle and the ball updating, checking for
collisions, and rendering. In the next part of the tutorial I plan on adding in bricks. I encourage you to
visit the news page of my site, XNA Game Programming Adventures, for the latest news on my
tutorials.

Good luck in your game programming adventures!

Jamie McMahon

You might also like