Bricks

From TRCCompSci - AQA Computer Science
Revision as of 14:39, 25 February 2019 by Admin (talk | contribs) (Game1.cs Update)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Original Tutorial

the original tutorial can be found on the link below:

Creating a 2d bricks game

Create a new project

Using the MonoGame templates, create a MonoGame Windows Project.

Resources Required

All of the resources for this tutorial can be downloaded here. Extract these files into the Content folder for your project.

In Visual Studio, double click the Content.mgcb file in the solution explorer panel. This will run the content pipeline tool. In the content pipeline tool, click the add existing item icon. Now browse for the Content folder of your project, and select all of the png & wav files downloaded above.

Now build the pipeline, you should see zero errors and each of the 9 items should be successful.

Getting Started

Game1.cs Using References

At the very start of the Game1.cs file, you will find some using declarations. make sure the following are included:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

Game1.cs Declarations

Find the line of code which states 'SpriteBatch spriteBatch;', now press enter to go onto the next line.

This is where you can declare any variables within your game. We are going to declare some Texture2D for the sprites/graphics within this game and also some sound effects. The Vector2 variables are to control the position and movement of the paddle and ball. Add the following declarations:

public Texture2D imgBrick;
public Texture2D imgPaddle;
public Texture2D imgBall;
public Texture2D imgPixel;
public SoundEffect startSound;
public SoundEffect brickSound;
public SoundEffect paddleBounceSound;
public SoundEffect wallBounceSound;
public SoundEffect missSound;

public Vector2 paddlePosition;
public Vector2 ballMovement;
public Vector2 ballPosition;
public bool ballInMotion = false;
public int speed = 8;

Game1.cs Constructor

To set the size of your screen, enter the following commands in the constructor method. A constructor method is uses the name of the class, so look for 'public Game1()' This is run once when your game is created:

graphics.PreferredBackBufferHeight = 600;
graphics.PreferredBackBufferWidth = 400;
graphics.ApplyChanges();

Game1.cs LoadContent

Now find the LoadContent method of Game1.cs. This is the method to load all of your game assets into your game. We will use this to load your built resources and to assign them to the variables we have declared above.

So add the following code to the LoadContent method:

//load images
imgBall = Content.Load<Texture2D>("Ball");
imgPixel = Content.Load<Texture2D>("Pixel");
imgPaddle = Content.Load<Texture2D>("Paddle");
imgBrick = Content.Load<Texture2D>("Brick");
 
//load sounds
startSound = Content.Load<SoundEffect>("StartSound");
brickSound = Content.Load<SoundEffect>("BrickSound");
paddleBounceSound = Content.Load<SoundEffect>("PaddleBounceSound");
wallBounceSound = Content.Load<SoundEffect>("WallBounceSound");
missSound = Content.Load<SoundEffect>("MissSound");

paddlePosition = new Vector2((graphics.PreferredBackBufferWidth / 2) - imgPaddle.Width, 550);

Game1.cs Update

The update method is essentially the game loop and is continuously run for your game, it will be run before the draw method is called.

This method will be used to read the user input and move any of the sprite characters. So to move the paddle we can add the following code:

if (Keyboard.GetState().IsKeyDown(Keys.Z)
{
    if (paddlePosition.X < 0)
        paddlePosition.X = 0;
    else
        paddlePosition.X -= 2;
}

if (Keyboard.GetState().IsKeyDown(Keys.X)
{
    if (paddlePosition.X > (graphics.PreferredBackBufferWidth - imgPaddle.Width))
        paddlePosition.X = graphics.PreferredBackBufferWidth - imgPaddle.Width;
    else
        paddlePosition.X += 2;
}

Game1.cs Draw Method

This will always be run after the update method. So add the following code into the Draw method:

spriteBatch.Begin();
spriteBatch.Draw(imgPaddle, paddlePostion);
spriteBatch.End();

If you test the game you should be able to control the paddle on the screen, test if it can go off the screen.

The Ball

Set the starting position

The ball should normally start on the paddle so to calculate the starting position we can enter the following in the Game1.cs Update method:

if(!ballInMotion)
    ballPosition = new Vector2(paddlePosition.X + (imgPaddle.Width / 2) - (imgBall.Width / 2),
        paddlePosition.Y - imgBall.Height);
else
    ballPosition += ballMovement;

If ballInMotion is false this will position the ball on top of the paddle in the middle. If ball is in motion we can keep adding the ballMovement vector to the ballPosition.

Serving the ball

To serve the ball, we are going to use a key press. This will set ballInMotion to be true, and we will also set the ballMovement vector. So add the following after the code for your starting position:

if(Keyboard.GetState().IsKeyDown(Keys.Space))
{
   ballInMotion = true;
   ballMovement = new Vector2(-1, -(speed)); 
}

in the vector -1 represents the x axis, so this will go to the left by 1. Speed is set to 8, so this will move up the screen by 8. If we keep applying this vector the ball will travel in a straight line.

Bouncing the ball around the screen

Using a vector to control the movement of the ball will allow you to easily bounce the ball by manipulating the vector.

If the ball is currently on a vector of (4 , -8) it will be travelling up the screen and to the right. If this causes it to bounce off the right hand side of the screen we can simply minus the x value of the vector to make (-4 , -8).

The same is true for a bounce from the left of the screen, a original vector of (-4 , -8) will translate into a bounce of (4 , -8).

For the top or bottom of the screen you need to minus just the Y value of your vector. So a bounce off the top using a vector of (4 , -8) will create a bounce vector of (4 , 8).

A bounce off the bottom from a vector (4 , 8) will create a bounce of (4 , -8), and a vector of (-4 , 8) will create a bounce vector of (-4 , -8).

We can do this in code by creating this method, paste it within the Game1 class but not in any other method:

public Vector2 Bounce (Vector2 current, bool Vertical, SoundEffect sound)
{
    if (Vertical)
        current = new Vector2(current.X , -(current.Y));
    else
        current = new Vector2(-(current.X) , current.Y);

    sound.Play();

    return current;
}

Ball Paddle Collisions

To detect collisions we are going to use rectangular bounds collision. This will require declaration of the 2 Rectangle variables below. This should be in Game1.cs below the 'SpriteBatch spriteBatch;' line:

Rectangle paddleRectangle;
Rectangle ballRectangle;

Now in the update method, find the line 'ballPosition += ballMovement;' and add the following to create 2 rectangles. One is the ball bounds the other is the paddle bounds:

paddleRectangle = new Rectangle((int)paddlePosition.X, (int)paddlePosition.Y, imgPaddle.Width, imgPaddle.Height);
ballRectangle = new Rectangle((int)ballPosition.X, (int)ballPosition.Y, imgBall.Width, imgBall.Height);

Now to check if the ball rectangle intersects the paddle rectangle:

if (paddleRectangle.Intersects(ballRectangle))
{
   ballMovement = Bounce(ballMovement, true, paddleBounceSound);
}

If the ball intersects the paddle rectangle then a collision has occurred. We can use the Bounce method to bounce on the paddle, we should play the paddleBounceSound for this bounce. We are passing the true option because it is a vertical based bounce and not an horizontal one.

Bricks

Drawing Bricks

Within your Game1.cs file, add the code below to the declaration section of your game. These will be used to draw the bricks, also copy the method below into your Game1.cs also. SetBricks is used to initialise the brickMap 2D boolean array.

const int rows = 5;
const int cols = 8;
bool[,] brickMap = new bool[rows, cols];

public void SetBricks()
{
    for (int r = 0; r < rows; r++)
    {
        for (int c = 0; c < cols; c++)
        {
             brickMap[r, c] = true;
         }
     }
}

Now add the line below to the end of your LoadContent method:

SetBricks();

Now in the draw method, we need to add the code to draw a brick for each true entry in the brick map:

for (int r = 0; r < rows; r++)
{
   for (int c = 0; c < cols; c++)
   {
        if (brickMap[r, c])
            spriteBatch.Draw(imgBrick, new Rectangle(c * imgBrick.Width, r * imgBrick.Height, imgBrick.Width, imgBrick.Height),Color.Blue);
    }
}

The code above should go after the spriteBatch.Begin() line but before the code to draw the paddle or ball.

Brick Collisions

Finally we need to check if the ball hits any of the bricks, this also uses rectangular bounds collision. Add this code into the update method of Game1.cs:

//check for bricks
for (int r = 0; r < rows; r++)
{
    for (int c = 0; c < cols; c++)
    {
        if (brickMap[r, c] && ballRectangle.Intersects(new Rectangle(c * imgBrick.Width, r * imgBrick.Height, imgBrick.Width, imgBrick.Height)))
        {
             brickMap[r, c] = false;
             ballMovement = Bounce(ballMovement, true, brickSound);
         }
     }
}

It creates a rectangle for each brick and tests to see if this rectangle intersects the ball. If it does we set the brick location to false and bounce the ball.

Now try your game and it should now remove any bricks involved in a collision with the ball.