When I started game programming I had all the enthusiasm but lacked quality information on how to go about actually making a complete game. There is a definite lack of complete game programming tutorials. Much of my time was spent flicking from one webpage to another not finding anything particularly useful. So I’ve decided to write a tutorial for your benefit so by the end you will be able to have a complete game under your belt.
A perfect game to start off with, in my opinion, is Pong.
This project will use VC++ and OpenGL for the examples.
_
The main game loop
The main game loop of most games basically goes like this:
Handle input
Update movements
Check for collisions
Check game conditions
Render
Pong is no different. With these in mind we shall structure our Game_Main function around this.
Game States
The game will be in various states while running. We need to take care of these so we will have a global named gameState and define these at the beginning of our code. These are:
PLAYING
GAMEOVER
GETREADY
The GETREADY state will be a state when the player's have a chance to get ready when the ball is reset after a goal or a new game is started.
Game Objects
We will make use of the OO technology we should look at what objects the game will use. The advantages of using OO to encapsulate the objects will makes things a great deal more organised. Practicing these methods now will pay off when you have a large project, you wont have to wade through so much code to make modifications.
For a game such as Pong there aren't too many:-
Paddle
Ball
Wall
Goal
Board
Each of these we will create a class for and fill in as we progress.
Where do we start?
With most of my projects I like to get something happening on the screen so I can test things as I go. For this project I think a good place to start would be to get the board drawn on the screen. Just a simple rectangle will do for now. We can modify and add to it as we go.
We’ll create a new class CBoard to do this. This class will need to have attributes and functions added to operate in our game world.
Our class diagram for the board will be like this:-
CBoard
width
height
color[3]
Draw()
Pretty simple. The color array is just an RGB (red, green, blue) set for the board. We may add some attributes later, such as a texture for the board.
We’ll set the width/height and color attributes in the class constructor.
The class definition and implementation will look like this
Cboard.h
We need to include the class definition in main.cpp, and for such a simple game we will declare the objects as globals and refer to them in our main.cpp functions.
Adding a couple of lines to the Game_Main() function to call the board class' Draw() function and we get something happening.

The ball is probally the most complex object we will have in our game, it is also the most interesting!
Our ball will need a few attributes. We need to keep track of it's position which we'll use x,y,z for. It also has a radius and a color similar to the board.
The ball has a speed vector [xi, yi, zi] which represents the relative movement of the ball. It will be used to update the ball position and direction. We shall talk more about this later.
To draw the ball in OpenGL we’ll get tricky and use a quadric. It sounds pretty in depth but it's just an easy way to draw a 3D sphere. The line attribute GLUquadricObj *sphere is a pointer to the quadric that we'll use to create and draw it. It’s pretty simple to use, check out the NeHe tut on quadrics if you want to know more.
We also have a function Reset() for when we want to return the ball to the start position whenever a goal is scored or a new game starts.
The Update() function will use the speed vector to update the ball position every game cycle. We will implement this later, and for now just get the ball to appear on screen.
The Draw() function will need to set the color a little differently for the ball since it is a 3D object. A simple call to set the material attributes in OpenGL does this.
Our class diagram for the ball:
CBall
x, y, z (Center of the ball)
xi, yi, zi (This is our speed vector)
radius
color[3]
GLUquadricObj *sphere
Draw()
Reset()
Update()
We implement this in CBall.h and CBall.cpp and add a couple of lines to the rendering section and see the result:
Cball.cpp
CBall.h
The Walls
The class diagram:
CWall
x, y (Top left coordinates)
width
height
color[3]
Draw()
* We’ll assume the width runs along X-axis and height along the Y-axis.
These are just rectangles that we can position at the top and bottom of the board. We will use these to bounce the ball off when we do some collision detection.
We add lines to the Game_Init() function that position the walls and as with the other objects we need to draw we add a Draw() command to the rendering section.
Here is the code:-
CWall.h
CWall.cpp
Class diagram:
CPaddle
x, y (Top left coordinates)
width
height
speed
color[3]
score
Draw()
Reset()
:Paddles aren’t much different from wall, except we will give them a movement speed and a player score. We also initialise their positions in Game_Init().
The Reset() function will be called when a new game starts, it will just reset the player's score back to zero.
CPaddle.h
CPaddle.cpp
Since the wall and goal are so similar, we can use a wall object to represent the goal. We don't need to see the goal so we'll just leave out the command for drawing it.
When checking we have positioned the goal in the right spot we can just do a call to the Draw() function and see it on screen.
Note: The objects share a lot of attributes which we could use to make an abstract base class to derive them from, but since this is a beginners project and there’s not too many objects we shall leave it be. If you don’t know what I mean, don’t worry it’s just a more advanced OO technique that can be learnt later.
clicke game2 for picture
Looks like we have all the basic bits and pieces on the screen. I hope you don’t think it was very hard, the next section will get the game actually doing something.
Moving the paddle
The paddle movement is going to require input from the keyboard.
We will use the keys ‘A’ and ‘Z’ for player 1 and the up and down cursors for player 2.
To check if a key is pressed with this code framework is pretty easy. We just need to check each key using the function KEY_DOWN() in the Game_Main() loop.
For the ‘A’ key we just check KEY_DOWN(DIK_A).
Our code will be:
if (KEY_DOWN(DIK_A))
move player 1 paddle up
Too easy, the others work exactly the same. To move the player’s paddle we just update their position according to the paddle speed attribute of the class:
player1.y += speed;
does the trick.
Okay, it's not too good if the paddles can fly off the screen so we'll be adding some collision detection with the walls to stop that.
To detect the collision we check if the edge of the paddle will move past the edge of the wall. When this happens we'll have to let the computer know what we'll want to happen, which in this case, the paddle stops next to the wall.
click collision Diagram to see the picture
By looking at the diagram we can see the edges we need to check. For the top wall we check:
if (Paddle.y > (topWall.y - topWall.height))
and the bottom wall:
if ((Paddle.y - Paddle.height) < bottomWall.y)
When the collision occurs, we set the Paddle.y position to that edge of the wall. This is done every game loop for both player1 and 2 in the collision section of Game_Main().
The most complex object of the game is the ball. As we mentioned before, the ball has a vector which tells us direction the ball is travelling.
If you don't know about vectors, a basic physics/science book will go into depth explaining it. The vector contains information describing how far to move on each axis.
For example: A vector where xi = 1 and yi = -2, would mean we would move 1 unit right on the x-axis and 2 units down on the y-axis.
So having a vector for a ball, we can easily make the ball go whatever direction we want just by changing the values of each component.
I have decided to add another attribute to the ball class. It will have a speed attribute which will allow us to alter the ball speed easily as the game progresses making it faster so there's a challenge. Again change it's value in the constructor if it is too slow/fast for your system. In combination with the ball vector we can write the Update() function:
x += xi * speed;
y += yi * speed;
z += zi * speed;
We will update the ball's current position every game loop in Game_Main() by calling the Update() function in the ball class.
Making these changes to the code we can now see the ball fly straight off the screen. Looks like we'll need to add some collision detection, that's next!
cball update
Testing for this type of collision is exactly the same as we did for the paddles. The only difference is when the collision occurs we want the ball to bounce off and go the other direction.
To make the ball go in the opposite direction the y vector component is just inverted. Therefore if we are travelling towards the top wall yi is positive, to go down we make it negative. The bottom wall is the same.
ball.yi = -ball.yi
This line acheives it for both scenarios.
Check out that collision test doing it's wonders:
More collisions! If you mastered the last section this collision isn't much different.
Instead of working with ball.yi we work on ball.xi. We only need to check the front edge of the paddle (we can do the side edges of the paddle but it's not crucial).
We have to have an extra check in this collision. First we have the same as the wall only on the x-axis, then we have to check ball's y position is in position to hit the paddle.
It looks tough, but it is just the same as the other collisions with an extra check.
click game 3 to look at it
Checking if a goal is scored should be easy if you've been following. The question is what do we do when a goal is scored?
First the player who scored needs to gain a point, we just add 1 to their score attribute.
player.score++
Secondly the ball needs to be reset and the player's should be given a little time to get ready. This is where our gameState variable will come in handy. We'll set it to GETREADY that was defined earlier for this purpose.
So we can test when to change from GETREADY back to PLAYING we need to use a timer which will be handled with a new global name gameStateTimer. The system function timeGetTime() is used to set it to the current time in milliseconds and add a delay for the time when we change states. 2000 milliseconds (2 seconds) for the delay should be fine.
When the game state is GETREADY I've displayed some text so the player's know what's going on.
In Game_Main() we check for the game state being GETREADY and test whether it is time to change back to PLAYING by comparing the timer with the current time.
One more thing is make sure the ball only moves when the game state is PLAYING
click game4 to view it
Okay this is the home stretch. You will have a complete game after this!
There are a few loose ends that need to be tidied up.
First, we'll display the player's score in the top corners, a few lines in the text output section of Game_Main() and we're in buisness.
We will also check if the GAMEOVER condition occurs. When either of the player's score 7 points we'll end it.
Then, we'll make the game state start with GAMEOVER when we initialize the game and display "GAME OVER" the same as was done for "GET READY!".
Also we'll allow a new game to be started when we are in the GAMEOVER state and the space bar is pressed. We need to reset the player scores here, and change the game state to GETREADY.
Letting the players know the keys is a good idea when the game is in GAMEOVER state.
A perfect game to start off with, in my opinion, is Pong.
This project will use VC++ and OpenGL for the examples.
_
The main game loop
The main game loop of most games basically goes like this:
Handle input
Update movements
Check for collisions
Check game conditions
Render
Pong is no different. With these in mind we shall structure our Game_Main function around this.
Game States
The game will be in various states while running. We need to take care of these so we will have a global named gameState and define these at the beginning of our code. These are:
PLAYING
GAMEOVER
GETREADY
The GETREADY state will be a state when the player's have a chance to get ready when the ball is reset after a goal or a new game is started.
Game Objects
We will make use of the OO technology we should look at what objects the game will use. The advantages of using OO to encapsulate the objects will makes things a great deal more organised. Practicing these methods now will pay off when you have a large project, you wont have to wade through so much code to make modifications.
For a game such as Pong there aren't too many:-
Paddle
Ball
Wall
Goal
Board
Each of these we will create a class for and fill in as we progress.
Where do we start?
With most of my projects I like to get something happening on the screen so I can test things as I go. For this project I think a good place to start would be to get the board drawn on the screen. Just a simple rectangle will do for now. We can modify and add to it as we go.
We’ll create a new class CBoard to do this. This class will need to have attributes and functions added to operate in our game world.
Our class diagram for the board will be like this:-
CBoard
width
height
color[3]
Draw()
Pretty simple. The color array is just an RGB (red, green, blue) set for the board. We may add some attributes later, such as a texture for the board.
We’ll set the width/height and color attributes in the class constructor.
The class definition and implementation will look like this
Cboard.h
Code:
// CBoard.h //
// Author: william palmer=me //
// Forgotten Realms //
#include #include
// For OpenGL calls
class CBoard
{
public: CBoard(); // Constructor
~CBoard(); // Destructor
float width, height; // Actual playing field size
float color[3]; // RGB color set
Draw(); // Draw to opengl screen
};
Code:
#include "CBoard.h"
// Class declaration
////////////////////////////////////////////////////////////////////
// Constructor
CBoard::CBoard(): width(13.0f), // Initialize width and height
height(10.0f)
{
color[0] = 0; // Set the board color to blue
color[1] = 0;
color[2] = 1;
}
////////////////////////////////////////////////////////////////////
// Destructor
CBoard::~CBoard() { }
////////////////////////////////////////////////////////////////////
// Draw to opengl screen
CBoard::Draw()
{
glColor3fv(color); // Set the color using the rgb color set
glBegin(GL_QUADS); // Draw the board with center at (0,0)
glVertex3f(-width/2, -height/2, 0.0f);
glVertex3f(-width/2, height/2, 0.0f);
glVertex3f( width/2, height/2, 0.0f);
glVertex3f( width/2, -height/2, 0.0f);
glEnd();
}
Adding a couple of lines to the Game_Main() function to call the board class' Draw() function and we get something happening.

THE BALL
The ball is probally the most complex object we will have in our game, it is also the most interesting!
Our ball will need a few attributes. We need to keep track of it's position which we'll use x,y,z for. It also has a radius and a color similar to the board.
The ball has a speed vector [xi, yi, zi] which represents the relative movement of the ball. It will be used to update the ball position and direction. We shall talk more about this later.
To draw the ball in OpenGL we’ll get tricky and use a quadric. It sounds pretty in depth but it's just an easy way to draw a 3D sphere. The line attribute GLUquadricObj *sphere is a pointer to the quadric that we'll use to create and draw it. It’s pretty simple to use, check out the NeHe tut on quadrics if you want to know more.
We also have a function Reset() for when we want to return the ball to the start position whenever a goal is scored or a new game starts.
The Update() function will use the speed vector to update the ball position every game cycle. We will implement this later, and for now just get the ball to appear on screen.
The Draw() function will need to set the color a little differently for the ball since it is a 3D object. A simple call to set the material attributes in OpenGL does this.
Our class diagram for the ball:
CBall
x, y, z (Center of the ball)
xi, yi, zi (This is our speed vector)
radius
color[3]
GLUquadricObj *sphere
Draw()
Reset()
Update()
We implement this in CBall.h and CBall.cpp and add a couple of lines to the rendering section and see the result:
Cball.cpp
Code:
#include "CBall.h" // Class declaration
////////////////////////////////////////////////////////////////////
// Constructor
CBall::CBall():
x(0.0f),
y(0.0f),
z(0.0f),
xi(0.5f),
yi(0.5f),
zi(0.0f),
radius(0.5f)
{
color[0] = 1; // Set the ball color
color[1] = 1;
color[2] = 0;
sphere = gluNewQuadric(); // Create a pointer to a quadric object
gluQuadricNormals(sphere, GLU_SMOOTH); // Create smooth normals
gluQuadricTexture(sphere, GL_TRUE); // Create texture coords
}
////////////////////////////////////////////////////////////////////
// Destructor
CBall::~CBall()
{
gluDeleteQuadric(sphere); // Remove the quadric from memory
}
////////////////////////////////////////////////////////////////////
// Draw to opengl screen
CBall::Draw()
{
float mat_diff[] = { color[0], color[1], color[2], 1.0 }; // We have to set material properties when dealing with quadrics
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diff);
glPushMatrix(); // Save current matrix, so translation doesnt affect rest of program
glTranslatef(x+radius/2, y-radius/2, z+radius/2); // Translate sphere so it is centered around x,y,z
gluSphere(sphere, radius/2, 10, 10); // Draw sphere
glPopMatrix(); // Restore matrix
}
////////////////////////////////////////////////////////////////////
// Reset the ball position and vector
CBall::Reset()
{
x = y = z = 0;
xi = 0.5f;
yi = 0.5f;
zi = 0;
}
////////////////////////////////////////////////////////////////////
CBall::Update()
{
// Implement this later
}
Code:
#include <windows.h>
#include <gl\gl.h> // Header File For The OpenGL32 Library
#include <gl\glu.h> // Glu32 header for quadrics
class CBall {
public:
float x, y, z; // Top-left position on screen
float xi, yi, zi; // Movement vector
float radius;
float color[3];
CBall(); // constructor
~CBall(); // destructor
Draw(); // Draw to opengl screen
Reset(); // Reset ball position and vector
Update(); // Update ball's position with vector
private:
GLUquadricObj *sphere; // Storage for quadratic object
};
The other objects
The Walls
The class diagram:
CWall
x, y (Top left coordinates)
width
height
color[3]
Draw()
* We’ll assume the width runs along X-axis and height along the Y-axis.
These are just rectangles that we can position at the top and bottom of the board. We will use these to bounce the ball off when we do some collision detection.
We add lines to the Game_Init() function that position the walls and as with the other objects we need to draw we add a Draw() command to the rendering section.
Here is the code:-
CWall.h
Code:
// CWall.h
#include <windows.h>
#include <gl/gl.h> // For OpenGL calls
class CWall {
public:
float x, y; // Top left coordinates
float width, height; // Actual playing field size
float color[3]; // RGB color set
CWall(); // Constructor
~CWall(); // Destructor
Draw(); // Draw to opengl screen
};
Code:
// CWall implementation
#include "CWall.h" // Class declaration
////////////////////////////////////////////////////////////////////
// Constructor
CWall::CWall():
width(13.0f), // Initialize width and height
height(0.5f)
{
color[0] = 1; // Set the wall color
color[1] = 0;
color[2] = 0;
}
////////////////////////////////////////////////////////////////////
// Destructor
CWall::~CWall()
{ }
////////////////////////////////////////////////////////////////////
// Draw to opengl screen
CWall::Draw()
{
glColor3fv(color); // Set the color using the rgb color set
glPushMatrix(); // Store the matrix so we can do the translation
glTranslatef(x, y, 0); // Position wall at x,y
glBegin(GL_QUADS); // Draw the board with center at (0,0)
glVertex3f(0, 0, 0);
glVertex3f(0, -height, 0);
glVertex3f(width, -height, 0);
glVertex3f(width, 0, 0);
glEnd();
glPopMatrix(); // Restore previous matrix
}
The paddles
Class diagram:
CPaddle
x, y (Top left coordinates)
width
height
speed
color[3]
score
Draw()
Reset()
:Paddles aren’t much different from wall, except we will give them a movement speed and a player score. We also initialise their positions in Game_Init().
The Reset() function will be called when a new game starts, it will just reset the player's score back to zero.
CPaddle.h
Code:
// CPaddle.h
#include <windows.h>
#include <gl\gl.h> // Header File For The OpenGL32 Library
class CPaddle {
public:
float width, height; // Paddle dimensions
float x, y; // Top-left position on screen
float speed; // Movement speed
float color[3]; // RGB color of the paddle
int score; // Player's score
CPaddle(); // Constructor
~CPaddle(); // Destructor
Draw(); // Draw to opengl screen
Reset();
};
Code:
// CPaddle implementation
#include "CPaddle.h" // Class declaration
////////////////////////////////////////////////////////////////////
// Constructor
CPaddle::CPaddle():
x(0.0f),
y(0.0f),
width(0.5f),
height(3.0f),
speed(0.3f),
score(0)
{
color[0] = 0;
color[1] = 1;
color[2] = 0;
}
////////////////////////////////////////////////////////////////////
// Destructor
CPaddle::~CPaddle()
{ }
////////////////////////////////////////////////////////////////////
// Draw to opengl screen
CPaddle::Draw()
{
glColor3fv(color);
glBegin(GL_QUADS);
glVertex3f(x, y , 0.0f);
glVertex3f(x, y - height, 0.0f);
glVertex3f(x + width, y - height, 0.0f);
glVertex3f(x + width, y , 0.0f);
glEnd();
}
////////////////////////////////////////////////////////////////////
// Reset paddle for new game
CPaddle::Reset()
{
score = 0;
}
The goal
Since the wall and goal are so similar, we can use a wall object to represent the goal. We don't need to see the goal so we'll just leave out the command for drawing it.
When checking we have positioned the goal in the right spot we can just do a call to the Draw() function and see it on screen.
Note: The objects share a lot of attributes which we could use to make an abstract base class to derive them from, but since this is a beginners project and there’s not too many objects we shall leave it be. If you don’t know what I mean, don’t worry it’s just a more advanced OO technique that can be learnt later.
clicke game2 for picture
Paddle movement
Looks like we have all the basic bits and pieces on the screen. I hope you don’t think it was very hard, the next section will get the game actually doing something.
Moving the paddle
The paddle movement is going to require input from the keyboard.
We will use the keys ‘A’ and ‘Z’ for player 1 and the up and down cursors for player 2.
To check if a key is pressed with this code framework is pretty easy. We just need to check each key using the function KEY_DOWN() in the Game_Main() loop.
For the ‘A’ key we just check KEY_DOWN(DIK_A).
Our code will be:
if (KEY_DOWN(DIK_A))
move player 1 paddle up
Too easy, the others work exactly the same. To move the player’s paddle we just update their position according to the paddle speed attribute of the class:
player1.y += speed;
does the trick.
Paddle/wall collisions
Okay, it's not too good if the paddles can fly off the screen so we'll be adding some collision detection with the walls to stop that.
To detect the collision we check if the edge of the paddle will move past the edge of the wall. When this happens we'll have to let the computer know what we'll want to happen, which in this case, the paddle stops next to the wall.
click collision Diagram to see the picture
By looking at the diagram we can see the edges we need to check. For the top wall we check:
if (Paddle.y > (topWall.y - topWall.height))
and the bottom wall:
if ((Paddle.y - Paddle.height) < bottomWall.y)
When the collision occurs, we set the Paddle.y position to that edge of the wall. This is done every game loop for both player1 and 2 in the collision section of Game_Main().
Ball movement
The most complex object of the game is the ball. As we mentioned before, the ball has a vector which tells us direction the ball is travelling.
If you don't know about vectors, a basic physics/science book will go into depth explaining it. The vector contains information describing how far to move on each axis.
For example: A vector where xi = 1 and yi = -2, would mean we would move 1 unit right on the x-axis and 2 units down on the y-axis.
So having a vector for a ball, we can easily make the ball go whatever direction we want just by changing the values of each component.
I have decided to add another attribute to the ball class. It will have a speed attribute which will allow us to alter the ball speed easily as the game progresses making it faster so there's a challenge. Again change it's value in the constructor if it is too slow/fast for your system. In combination with the ball vector we can write the Update() function:
x += xi * speed;
y += yi * speed;
z += zi * speed;
We will update the ball's current position every game loop in Game_Main() by calling the Update() function in the ball class.
Making these changes to the code we can now see the ball fly straight off the screen. Looks like we'll need to add some collision detection, that's next!
cball update
Code:
// CBall implementation
#include "CBall.h" // Class declaration
////////////////////////////////////////////////////////////////////
// Constructor
CBall::CBall():
x(0.0f),
y(0.0f),
z(0.0f),
xi(0.5f),
yi(0.5f),
zi(0.0f),
radius(0.25f),
speed(0.15f)
{
color[0] = 1; // Set the ball color
color[1] = 1;
color[2] = 0;
sphere = gluNewQuadric(); // Create a pointer to a quadric object
gluQuadricNormals(sphere, GLU_SMOOTH); // Create smooth normals
gluQuadricTexture(sphere, GL_TRUE); // Create texture coords
}
////////////////////////////////////////////////////////////////////
// Destructor
CBall::~CBall()
{
gluDeleteQuadric(sphere); // Remove the quadric from memory
}
////////////////////////////////////////////////////////////////////
// Draw to opengl screen
CBall::Draw()
{
float mat_diff[] = { color[0], color[1], color[2], 1.0 }; // We have to set material properties when dealing with quadrics
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diff);
glPushMatrix(); // Save current matrix, so translation doesnt affect rest of program
glTranslatef(x, y, z); // Translate ball position
gluSphere(sphere, radius, 10, 10); // Draw sphere
glPopMatrix(); // Restore matrix
}
////////////////////////////////////////////////////////////////////
// Reset the ball position and vector
CBall::Reset()
{
x = y = z = 0;
xi = 0.5f;
yi = 0.5f;
zi = 0;
speed = 0.15f;
}
////////////////////////////////////////////////////////////////////
CBall::Update()
{
x += xi * speed; // Update ball position according to vector
y += yi * speed;
z += zi * speed;
}
Ball/Wall collisions
Testing for this type of collision is exactly the same as we did for the paddles. The only difference is when the collision occurs we want the ball to bounce off and go the other direction.
To make the ball go in the opposite direction the y vector component is just inverted. Therefore if we are travelling towards the top wall yi is positive, to go down we make it negative. The bottom wall is the same.
ball.yi = -ball.yi
This line acheives it for both scenarios.
Check out that collision test doing it's wonders:
Ball/paddle collisions
More collisions! If you mastered the last section this collision isn't much different.
Instead of working with ball.yi we work on ball.xi. We only need to check the front edge of the paddle (we can do the side edges of the paddle but it's not crucial).
We have to have an extra check in this collision. First we have the same as the wall only on the x-axis, then we have to check ball's y position is in position to hit the paddle.
Code:
if ((ball.x - ball.radius < player1.x + player1.width) && (ball.y < player1.y) && (ball.y > player1.y - player1.height)) ball.xi = -ball.xi; if ((ball.x + ball.radius > player2.x) && (ball.y < player2.y) && (ball.y > player2.y - player1.height)) ball.xi = -ball.xi;
click game 3 to look at it
Scoring goals
Checking if a goal is scored should be easy if you've been following. The question is what do we do when a goal is scored?
First the player who scored needs to gain a point, we just add 1 to their score attribute.
player.score++
Secondly the ball needs to be reset and the player's should be given a little time to get ready. This is where our gameState variable will come in handy. We'll set it to GETREADY that was defined earlier for this purpose.
So we can test when to change from GETREADY back to PLAYING we need to use a timer which will be handled with a new global name gameStateTimer. The system function timeGetTime() is used to set it to the current time in milliseconds and add a delay for the time when we change states. 2000 milliseconds (2 seconds) for the delay should be fine.
When the game state is GETREADY I've displayed some text so the player's know what's going on.
In Game_Main() we check for the game state being GETREADY and test whether it is time to change back to PLAYING by comparing the timer with the current time.
One more thing is make sure the ball only moves when the game state is PLAYING
click game4 to view it
Nearly done!
Okay this is the home stretch. You will have a complete game after this!
There are a few loose ends that need to be tidied up.
First, we'll display the player's score in the top corners, a few lines in the text output section of Game_Main() and we're in buisness.
We will also check if the GAMEOVER condition occurs. When either of the player's score 7 points we'll end it.
Then, we'll make the game state start with GAMEOVER when we initialize the game and display "GAME OVER" the same as was done for "GET READY!".
Also we'll allow a new game to be started when we are in the GAMEOVER state and the space bar is pressed. We need to reset the player scores here, and change the game state to GETREADY.
Letting the players know the keys is a good idea when the game is in GAMEOVER state.
ManzZup
likes this

