As I mentioned in the first part of this series, in this part I will start developing a Pong clone. First I will explain how to prepare your external assets (sprites, images, sounds etc.), then we will create the project where we will develop the game, we will copy the compiled .xnb assets, we will create few classes and finally we will draw few objects on the screen. Without further ado, let’s start with the first step.

Preparing the External Assets

In the first part I mentioned that the Content Pipeline for the Windows 8 version of MonoGame is still not ready. Therefore, we will need XNA to compile the external assets and then use the compiled files in our MonoGame project.

First of all, download the .rar compressed file ‘Pong Assets’ from here. After you finish downloading, extract the files to a folder of your choice (e.g. Desktop). Launch Visual Studio 2012 Express for Windows Phone and create a new XNA Windows Phone Game (4.0) project. Change the name to PongContent and press OK.

 

After the project is created, right-click on the Content project that you can find on the right side then Add –> Existing Item…

Navigate to the folder where you previously extracted the files, select all of the files and click Add to add them to the project.

Our next step is to compile the project. Click on Build –> Build Solution or press CTRL+Shift+B on your keyboard.

After the Build process is complete, close Visual Studio 2012 Express for Windows Phone and launch Visual Studio 2012 Express for Windows 8.

Create a New Project, pick MonoGame Game, change the name to PongClone and click OK.

If you followed my instructions on the first part to set up MonoGame by cloning the Git repository, now you will need to repeat the steps that I wrote under ‘Testing MonoGame’. They were: removing the existing references, adding the MonoGame Windows 8 project and adding a reference in your project to the MonoGame Windows 8 project. If you do not remember how this was done, read the instructions again here (look at the end ‘Testing MonoGame’)

If you installed MonoGame via the installer, you do not have to do anything else to set it up. With the creation of the project, all the required references will be added automatically.

Press F5 or Debug –> Start Debugging to test whether MonoGame is functional before we continue. If you see a blue screen, everything is fine.

Right-click on the PongClone project Add –> New Folder. Name the new folder ‘Content’ (without quotation marks).

Right-click on the folder Add –> Existing Item… and navigate to:

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

Select all the .xnb files and click Add.

 

 

 

 

Next, select all the added files as shown on the picture on the left, under Properties change the Build Action from None to Content. (Click on the picture for bigger view)

 

 

 

 

 

 

This step completes the preparation of the external assets. There are other methods that might be slightly faster (adding Windows Phone library and Content projects), but for that you need Visual Studio 2012 Professional or above and they are slightly more complex.

Game Loop

MonoGame has all the XNA namespace, class, method etc. names. Open the Game1.cs file where the ‘Main’ of the application is located. In this same file, besides the constructor, you will notice 5 more methods: Initialize, LoadContent, UnloadContent, Update and Draw.

The first two are used to set up the initial values and loading external assets. UnloadContent is used when you want to dispose the loaded assets (e.g. closing the game). Update and Draw are the methods where the magic happens! These two methods constantly run in a loop which is called the Game Loop. The speed of the loop is measured in frames per second (FPS) and can be manually set.

In Update we put the game logic (movement, input, collision detection, physics etc.). After all the calculations, we move to Draw which is used for drawing objects in a given position.

 

GameObject, Player and Ball

For our Pong clone, we will create few classes. In this part of the series, our goal is to draw our objects on the screen. Before we begin with typing the classes for our objects, we will first type a few lines where we will hold the screen dimensions at any given time.

Open Game1.cs if you did not open it before and under the existing lines for _graphics and _spriteBatch, add two static int variables where we will hold the width and height of the screen.

GraphicsDeviceManager _graphics;
SpriteBatch _spriteBatch;

public static int ScreenWidth;
public static int ScreenHeight;

Scroll down a bit, in the Initialize method, initialize the two variables.

ScreenWidth = GraphicsDevice.Viewport.Width;
ScreenHeight = GraphicsDevice.Viewport.Height;

base.Initialize();

Now, in the Update method, add the same two lines as above.

ScreenWidth = GraphicsDevice.Viewport.Width;
ScreenHeight = GraphicsDevice.Viewport.Height;

base.Update(gameTime);

With these lines, we will have the screen dimensions at any given time, whenever the dimensions change, they will be updated (e.g. Snap View on Windows 8).

Now we can create the classes for our in-game objects. Because the players and the ball share several attributes, we will create a GameObject superclass and then Player and Ball will inherit from that class.

Right-click on the PongClone project and add a new Folder ‘Classes’ (without quotation marks). Right click on the ‘Classes’ folder and Add –> Class…

Change the name to GameObject and click Add.

Repeat the same thing to add the Player and Ball classes.

Open the GameObject.cs class and change it to the following:

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

namespace PongClone
{
    public class GameObject
    {
        public Vector2 Position;
        public Texture2D Texture;
    }
}

You will notice in lines 6 and 7, we added two libraries that containt the Vector2 and Texture2D classes that are used in lines 13 and 14. Also, in line 9 we removed .Classes in order to have access to the GameObject class without writing Classes.GameObject.

In line 11, we added the public keyword in order to have access to the class from other classes. In line 13, we declared a two-dimensional vector to store a position that contains X and Y coordinates. In line 14, we declared a variable that will hold the texture of the object.

Note: In our game I will avoid using other keywords like private, protected etc. for simplicity.

Next, we need to add a method for drawing. Add the following method in the GameObject class:

public void Draw(SpriteBatch spriteBatch)
{
	spriteBatch.Draw(Texture, Position, Color.White);
}

 

This method uses a SpriteBatch object to draw 2D objects on screen. spriteBatch.Draw(…) has several overloads, I will use the fourth overload that takes Texture2D, Vector2 and Color parameters. This line draws a given texture called Texture on a given position called Position. The last parameter is used for tinting the color of the texture. Color.White is used if you do not want to apply any tinting and use the original color of the texture.

Open the Player.cs class and change it to the following:

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

namespace PongClone
{
    public class Player : GameObject
    {
    }
}

In line 7, we removed .Classes. In line 9, we added the public keyword and : GameObject to inherit from the GameObject class.

Open the Ball.cs class in change it to the following:

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

namespace PongClone
{
    public class Ball : GameObject
    {
    }
}

The same changes are also done to the Ball class.

Drawing the Players and the Ball

Open the Game1.cs class and create variables for the players and ball. Also, we will create an integer constant to set a player paddle offset used to offset the players from the left and right edges of the screen.

const int PADDLE_OFFSET = 70;

Player player1;
Player player2;
Ball ball;

The value 70 represents 70 pixels offset. In our case we will offset from the left and right edges of the screen.

Change the Initialize method to the following:

protected override void Initialize()
{
	// TODO: Add your initialization logic here

	ScreenWidth = GraphicsDevice.Viewport.Width;
	ScreenHeight = GraphicsDevice.Viewport.Height;

	player1 = new Player();
	player2 = new Player();
	ball = new Ball();
            
	base.Initialize();
}

In lines 8, 9 and 10 we created the objects for the players and the ball. Next, we will need to load the textures and set the initial positions of these three objects.

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);

	// TODO: use this.Content to load your game content here
	player1.Texture = Content.Load<Texture2D>("Paddle");
	player2.Texture = Content.Load<Texture2D>("Paddle");

	player1.Position = new Vector2(PADDLE_OFFSET, ScreenHeight / 2 - player1.Texture.Height / 2);
	player2.Position = new Vector2(ScreenWidth - player2.Texture.Width - PADDLE_OFFSET, ScreenHeight / 2 - player2.Texture.Height / 2);

	ball.Texture = Content.Load<Texture2D>("Ball");
	ball.Position = new Vector2(ScreenWidth / 2 - ball.Texture.Width / 2, ScreenHeight / 2 - ball.Texture.Height / 2);
}

In lines 7 and 8 we load the same texture for each of the players. The texture i s located in the Content folder that we previously created. After that, we set the positions of the players. In line 10, for the X coordinate, we use the paddle offset of 70 pixels. For the Y coordinate, we use the screen height and the height of the player texture to correctly position it on the center of the Y axis.

In line 11, we take into account the complete screen width in order to position the second player on the right side.

In lines 13 and 14, we load the texture for the ball and set its initial position.

Note: (0,0) on the screen is the top-left corner. Look at the image here.

Finally we reached the last step, drawing the objects. Change the Draw method to the following:

protected override void Draw(GameTime gameTime)
{
	GraphicsDevice.Clear(Color.Black);

	// TODO: Add your drawing code here
	_spriteBatch.Begin();
	player1.Draw(_spriteBatch);
	player2.Draw(_spriteBatch);
	ball.Draw(_spriteBatch);
	_spriteBatch.End();
	base.Draw(gameTime);
}

 

In line 3, we changed the color of the background from CornflowerBlue to Black. Then to begin drawing, the method _spriteBatch.Begin() is fired. In lines 7, 8 and 9 we use the method that we previously typed in the GameObject class to draw the elements. After we finish drawing, we stop the SpriteBatch object by firing _spriteBatch.End().

Press F5 or Debug –> Start Debugging. If you do not have any syntax errors, you should see the following:

The complete solution until this point can be found here.

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

If you have any problems, leave a comment below.

In part three, we will implement input, movement and collision detection.

Advertisements