# Revew my pong clone: game and code!

## Recommended Posts

ISDCaptain01    1496

Well I've finally did it. Ive made my very first game, and it does look quite good! I am posting a pic of it, source code, and download link to the project. Tools used: C++, Allegro 4.2

Heres the picture

http://www.sendspace.com/file/nd9ncs

Heres the code:

#pragma once
#include <allegro.h>
#include <iostream>
using namespace std;

//color macros
#define WHITE (255, 255, 255)
#define BLUE (5, 209, 255)

//Sprite Variables
BITMAP *background;
BITMAP *buffer;

//Player scores
int player1 = 0; //LEFT
int player2 = 0; //RIGHT

//Sounds
SAMPLE *maintheme;
SAMPLE *impact;

{
public:
int x, y;
int width, height;

};

class Star
{
public:
int x, y;
int dirx;
int diry;
int width, height;
float angle;
BITMAP *starSprite;
};

//Create a star ball
Star starball;

//Gives the star a rotation effect
void rotateStar(Star &star)
{

//draw star to screen
rotate_sprite(buffer, star.starSprite, star.x, star.y, star.angle);

//rotate star in 256 angles
if(star.angle > 256)
{
star.angle = 0;
}
else
{
star.angle += 1;
rotate_sprite(buffer, star.starSprite, star.x, star.y, itofix(star.angle));
}

}

{
//update star x postion
star.x += star.dirx;

//Hits the left side of the screen
if(star.x < 0)
{
star.x = 1;
star.dirx = rand()%2 + 6;

//decrement score for player 2
if(player2 < 0)
{
player2 = 0;
}
else
{
player2--;
}

}

//Hits the right side of the screen
if(star.x > SCREEN_W - star.width - 1)
{
star.x = SCREEN_W - star.width - 1;
star.dirx = rand()%2 - 6;

//decrement score for player 1
if(player1 < 0 )
{
player1 = 0;
}
else
{
player1--;
}
}

//update star y position
star.y += star.diry;

//Hits the top of the screen
if(star.y < 0)
{
star.y = 2;
star.diry = rand()%2 + 6;
}
//Hits the bottom of the screen
if(star.y > SCREEN_H - star.height - 2)
{
star.y = SCREEN_H - star.height - 2;
star.diry = rand()%2 - 6;
}

{
play_sample(impact, 128, 128, 1000, FALSE);
player1++;
star.x = paddle1.x - star.height - 1;
star.dirx = rand() % 2 - 6;

}

{
play_sample(impact, 128, 128, 1000, FALSE);
player2++;
star.x = paddle2.x + star.height + 1;
star.dirx = rand() % 2 + 6;
}
}

{
{
}
}

{
{
}
}

//Checks for key presses
void getinput()
{
if(key[KEY_DOWN])
{
}

if(key[KEY_UP])
{
}

if(key[KEY_W])
{
}

if(key[KEY_S])
{
}
}

{
}

//Draws the court line
void drawborder(BITMAP *dest)
{
int n;
int y1 = 1;
int y2 = 4;

for(n = 0; y2 < SCREEN_H; n++)
{
rectfill(dest, (SCREEN_W/2)-2, y1, (SCREEN_W/2)+2, y2, BLUE);
y1 += 5;
y2 += 5;
}
}

{

//Set up paddles for drawing time

}

void setupstar()
{
starball.x =  SCREEN_W/2;
starball.y =  SCREEN_H/2;
starball.dirx = 1;
starball.diry = 2;
starball.angle = 0;
starball.width = starball.starSprite->w;
starball.height = starball.starSprite->h;
}



main.cpp

#include "functions.h"

int main()
{
//Initialize Allegro
allegro_init();

//Install subsystems
install_keyboard();
install_timer();
srand(time(NULL));

//Set graphics bit mode
set_color_depth(24);

//set the screen
int ret = set_gfx_mode(GFX_SAFE, 800, 600, 0, 0);
//failure check
if(ret != 0)
{
allegro_message(allegro_error);
return 1;
}

//Set up the sound system
if((install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, "") != 0))
{
allegro_message("Failed to Initialize Sound System!");
return 1;
}

//create the buffer
buffer = create_bitmap(SCREEN_W, SCREEN_H);

//set up the starball
setupstar();

play_sample(maintheme, 128, 128, 1000, TRUE);

//Main game loop
while(!key[KEY_ESC])
{

//Erase the entire screen really fast by blitting the
//entire background onto it
blit(background, buffer, 0, 0, 0, 0, background->w, background->h);

//Show scores
textprintf_ex(buffer, font, 30, 590, BLUE, -1, "Player 2 Score: %d", player2);
textprintf_ex(buffer, font, 640, 590, BLUE, -1, "Player 1 Score: %d", player1);

//Draw a border between players
drawborder(buffer);

//Draw the rotating star
rotateStar(starball);

//move the star

//check for control inputs
if(keypressed())
{
getinput();
}

//Lock screen
acquire_screen();

//draw the screen
blit(buffer, screen, 0, 0, 0, 0, buffer->w, buffer->h);

//unlock screen
release_screen();

rest(10);
}

destroy_bitmap(background);
destroy_bitmap(buffer);
destroy_bitmap(starball.starSprite);

remove_sound();

allegro_exit();
return 0;
}
END_OF_MAIN()



http://www.sendspace.com/file/qs6w0b

The game is fully functional, although the paddle collision is somewhat buggy.  But I Tried my best for my first game. Please critique my code and game.

Edited by ISDCaptain01

##### Share on other sites
BLM768    325

This code's not bad for a first project; it's organized reasonably well and is pretty easy to read. As far as structure goes, you'd need only a few tweaks to make it more solid:

The functions that manipulate the ball and paddles could be moved into the classes as methods, like so:

class Paddle
{
public:
int x, y;
int width, height;

void moveUp() {
y-=5;
if(y < 0)
{
y = 0;
}
}

void moveDown() { /* ... */ }
void draw() { /* ... */ }
};


You could also take advantage of the similarities between the paddles and the ball. They are both game entities with coordinates, width, height, and an image, so you can pull those similarities into a base class:

class Entity
{
int x, y;
int width, height;
BITMAP* sprite;

void draw()
{
blit(sprite, buffer, 0, 0, x, y, width, height);
}
}

//Has all the fields from Entity plus whatever we add here:
//moveUp(), moveDown, etc.
}

class Star: Entity {
void rotate() { /* ... */ }

//etc., etc.
}


I can think of a few more things you might want to tweak, but I'll leave you with that for now because it's getting late, and this post will probably take a little while to "digest" if you're not already familiar with methods and inheritance.

##### Share on other sites
ISDCaptain01    1496

Thank you for the feedback. I will definitely try to implement such techniques in my next project.

##### Share on other sites
Pink Horror    2459

I'm trying to figure out why you even have a header. Headers are for what you want to share between cpp files. With only one cpp file, there isn't really any point.

If you want to practice, put publicly available data structures into headers, with simple inline functions and function prototypes for more complex functions. Keep normal functions in cpp files. I generally start out by coding every function as a static function in a cpp file and then promote them into member functions or global functions as necessary, but most people are less extreme about static function use in c++ as I am, and probably make more private member functions instead. Whatever works for you is fine.

You definitely do not want global variables in your header. Each global variable should only live in one compilation unit.

You should work on removing the global variables. They should really be the last resort. Learn to program without them. Start with the easiest ones. For example, your background sprite is only referenced within your main function, it's loaded, blitted, and destroyed all in the same function, so it can be local to main.

Also, I notice that your text color macro is BLUE, but the screenshot has red text. You should probably just delete those macros, which do not make very much sense, and use whatever color function is in your API to create the proper color int. Macros are best as a last resort.

Anyway, congratulations on making a pong game.

##### Share on other sites

Things to put in a header:

Macros (Only if you really need a macro, and it needs to go in a header. Conditional compilation switches/include guards are ok).

Extern globals (minimise globals though)

Type definitions (class/struct) which need to be seen from other files. This is mainly what you should use headers for.

Global function prototypes which are called from other files.

Const globals if they need to be shared between compilation units.

Inline functions/template classes. They need to be visible to every compilation unit which uses them.

Things not to put in a header:

everything else

I think that covers it?