In the final part of this series we will polish our game. First we will type few lines to add ball spin. Then, we will add a SpriteFont which is used for drawing text on screen. We will use that to draw player scores. Next, we will add a line in the middle of the screen to separate player one’s field from player two’s field. Then we will add sounds for the collisions, and finish with adding a splash screen and tiles.

Ball Spin

Open the Game1.cs class and add a new constant:

const float SPIN = 2.5f;

Next, in the Update method, right after the lines for moving the players via Touch, add the following if-tests:

player1.Move(player1TouchVelocity);
player2.Move(player2TouchVelocity);

if (player1TouchVelocity.Y > 0f)
{
	player1Velocity = player1TouchVelocity;
}
if (player2TouchVelocity.Y > 0f)
{
	player2Velocity = player2TouchVelocity;
}

if (player1Velocity.Y != 0)
{
	player1Velocity.Normalize();
}
if(player2Velocity.Y != 0)
{
	player2Velocity.Normalize();
}

In our case, if the players use touch input, you will notice that the velocity of the players is not strictly limited. The paddles will move with the same speed as the players’ drag speed. With keyboard on the other hand, there is a strict speed value defined in the constant KEYBOARD_PADDLE_SPEED. We do not want to allow the players using touch to have more or less ball spin when they hit the ball. That is why we normalize their velocities, so we can only take their movement direction.

So, first we check whether there is touch input. If true, we save that value and then normalize it.

In the same Update method, in the if-tests that check whether there is collision between the paddles and the ball, add the lines like shown below:

if (GameObject.CheckPaddleBallCollision(player1, ball))
{
	ball.Velocity.X = Math.Abs(ball.Velocity.X);
	ball.Velocity += player1Velocity * SPIN;
}

if (GameObject.CheckPaddleBallCollision(player2, ball))
{
	ball.Velocity.X = -Math.Abs(ball.Velocity.X);
	ball.Velocity += player2Velocity*SPIN;
}

 

After we change the direction of the ball, we add spin to the ball in the direction of player movement.

Press F5 or Debug –> Start Debugging to test. You will notice that when you hit the ball while you are moving a paddle, the ball’s velocity decreases or increases.

Feel free to experiment with the values given to the constants to alter gameplay. You can change the initial speed of the ball, add more or less spin etc.

Score Indicators

First, download and install the 8Bit Wonder font from here.

Now you will need to repeat the steps for compiling external assets as shown in part two so we can add a SpriteFont to our game.

Launch Visual Studio 2012 Express for Windows Phone and open the PongContent project. Right click on the Content project and Add –> New Item.

 

On the left side pick Visual C#, and then choose SpriteFont. Change the name to RetroFont and click Add.

After you click Add, the SpriteFont file will automatically open in Visual Studio. You can see different parameters that can be changed like font name, size, style etc.

Make the following changes:

<FontName>8Bit Wonder</FontName>

<Size>32</Size>

<Style>Bold</Style>

After you change the values, compile the project by pressing Build –> Build Solution. When the project successfully builds, close Visual Studio 2012 Express for Windows Phone.

Return to the PongClone project, right-click on the ‘Content’ folder and Add –> Existing Item…

Navigate to:

…\Documents\Visual Studio 2012\Projects\PongContent\PongContent\PongContent\bin\Windows Phone\Debug\Content

Select RetroFont.xnb and click Add.

Now select RetroFont and change its Build Action from None to Content.

Open the Player.cs class and add the following field:

public int Score;

Open the the Game1.cs class and declare a new SpriteFont variable after the declaration of the players and the ball:

Player player1;
Player player2;
Ball ball;

SpriteFont retroFont;

In the LoadContent method, add the following line to load the SpriteFont:

retroFont = Content.Load<SpriteFont>("RetroFont");

 

In the Update method, change the if-tests for launching the ball when it leaves the screen to the following:

if (ball.Position.X + ball.Texture.Width < 0)
{
	ball.Launch(BALL_START_SPEED);
	player2.Score++;
}

if (ball.Position.X > ScreenWidth)
{
	ball.Launch(BALL_START_SPEED);
	player1.Score++;
}

So, if the ball leaves the screen from the left side, player 2 gets 1 point. If the ball leaves the screen from the right side, player 1 gets 1 point.

In the Draw method, between _spriteBatch.Begin() and player1.Draw(_spriteBatch), add a line for drawing the scores:

_spriteBatch.Begin();
_spriteBatch.DrawString(retroFont, player1.Score + "        " + player2.Score,new Vector2(ScreenWidth / 2 -retroFont.MeasureString(player1.Score + "        " + player2.Score).X / 2,0), Color.Cyan);
player1.Draw(_spriteBatch);

The DrawString method takes the SpriteFont object, the string we want to draw, position of the string (in our case the position depends on the length of the screen which is measured with the MeasureString method), and text color.

Press F5 or Debug –> Start Debugging to test. You will notice each player’s score on the top of the screen.

Now we can also add a line in the middle to divide the player fields.

In Game1.cs right after declaring SpriteFont retroFont; add a new texture:

SpriteFont retroFont;
Texture2D middleTexture;

In LoadContent, add the following line:

middleTexture = Content.Load<Texture2D>("Middle");

In the Draw method, after _spriteBatch.Begin() add the line for drawing the texture:

_spriteBatch.Draw(middleTexture,new Rectangle(ScreenWidth / 2 - middleTexture.Width / 2, 0, middleTexture.Width,ScreenHeight), null, Color.White);

You will notice that we are using a different overload for the Draw method. Because the Middle texture has a width of 4 pixels and a height of 1 pixel (4×1), with the help of a Rectangle we can stretch it however we want. When you use a Rectangle for drawing objects on screen, the texture size does not matter. The texture is stretched or shrinked to fit inside the defined Rectangle.

Press F5 or Debug –> Start Debugging to see the new texture.

Sound Effects

Because we already compiled the sound effects when adding our external assets in part two, we can immediately start using them.

For managing sound effects we will create a new static class, ‘SoundManager’.

Right-click on the ‘Classes’ folder, Add –> Class… Change the name to ‘SoundManager’ (without quotation marks) and click Add.

Change the code in SoundManager.cs to the following:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;

namespace PongClone
{
    public static class SoundManager
    {
        public static SoundEffect BallWallCollisionSoundEffect;
        public static SoundEffect PaddleBallCollisionSoundEffect;

        public static void LoadSounds(ContentManager Content)
        {
            BallWallCollisionSoundEffect = Content.Load<SoundEffect>("BallWallCollision");
            PaddleBallCollisionSoundEffect = Content.Load<SoundEffect>("PaddleBallCollision");
        }
    }
}

You will notice that we have two fields for holding the collision sounds between the ‘walls’ and ball, and between the players and the ball. Then we have a static method that takes a ContentManager object which is used for loading the sound effects.

Open the Game1.cs class and in the LoadContent method add the following line:

SoundManager.LoadSounds(Content);

Then in the Update method, change the if-tests for collision between the balls and the player to the following:

if (GameObject.CheckPaddleBallCollision(player1, ball))
{
	ball.Velocity.X = Math.Abs(ball.Velocity.X);
	ball.Velocity += player1Velocity * SPIN;
	SoundManager.PaddleBallCollisionSoundEffect.Play();
}

if (GameObject.CheckPaddleBallCollision(player2, ball))
{
	ball.Velocity.X = -Math.Abs(ball.Velocity.X);
	ball.Velocity += player2Velocity*SPIN;
	SoundManager.PaddleBallCollisionSoundEffect.Play();
}

So, as soon as the ball and a player collides, we play the sound effect.

Open the Ball.cs class and change the CheckWallCollision method to the following:

public void CheckWallCollision()
{
	if (Position.Y < 0)
	{
		Position.Y = 0;
		Velocity.Y *= -1;
		SoundManager.BallWallCollisionSoundEffect.Play();
	}
	if (Position.Y + Texture.Height > Game1.ScreenHeight)
	{
		Position.Y = Game1.ScreenHeight - Texture.Height;
		Velocity.Y *= -1;
		SoundManager.BallWallCollisionSoundEffect.Play();
	}
}

The same thing happens here. As soon as we detect collision between a ‘wall’ and the ball, we play the sound effect.

Press F5 or Debug –> Start Debugging to test the latest changes.

Splash Screen and Tiles

Download a .rar file containing the images from here. Extract the images to the following folder:

…\Documents\Visual Studio 2012\Projects\PongClone\PongClone\Assets

When you are asked, overwrite the existing files.

In Visual Studio 2012, open the Package.appxmanifest file (shown on the screen below).

A new window will open that contains options for the name of the game, ability to change logos and icons, etc. Click on the Splash Screen tab and type ‘blac’ (without quotation marks) in the Background Color field.

Press F5 or Debug –> Start Debugging to test. You will see that you now have a shiny new Splash Screen.

Also in your Windows 8 Start Screen you will notice a new small tile for your game.

Congratulations, you completed your first Windows 8 game using MonoGame!

You can download my Solution from here.

Note: You will need to set up the correct references to the MonoGame project in order to test my Solution.

I hope you liked this mini series. If you have any questions, feel free to leave a comment below. I would like to thank the folks over at 3D Buzz, because more than a year ago when I was learning the XNA Framework, one of their assignments was to create a Pong game.

Advertisements