The Allegro Wiki is migrating to github at

Breakout Game From Scratch

From Allegro Wiki
Jump to: navigation, search

This tutorial is a detailed view of all the source code of a game done from scratch, with C++ and Allegro, with gameplay very similar to classics such as Arkanoid, Gigas, or Breakout.

Original written by Kronoman - "In loving memory of my father"


<tasks> [1] Make sure the upload of the zip file with the project and the source code is OK. [2] Read the whole article and make sure everything was translated OK from the original tutorial. [x] Add the png screenshoots [3] Break the text into smaller < 30 kb sections. [3] Maybe fix the redaction. </tasks> TODO - remove this task list when everything is done.


This tutorial is aimed at showing how to develop a simple game using the Allegro Game Libray, but is not aimed at teaching how to code from scratch.

I assume that you can code reasonably well in C++, and you have knowledge about object oriented programming, and computer use in general.

The whole source code is in a zip file that comes with this tutorial. Here I will only show and discuss fragments of code that are of academic interest to the educative goal.


Here you can download the whole source code for the project.

Or here, a direct link to the file


In this tutorial, I'm going to make a simple game, that I like to call Kronoide. To make the game, I use the C++ programming language, together with Allegro as the game libray.


This game is going to take the basic gameplay from Arkanoid, an arcade game developed by Taito in 1986. It is a simplified clone of Sega's earlier arcade game Gigas and Gigas Mark 2 which were in turn based upon Atari's Breakout games of the 1970s.

The player controls a small pad, which prevents a ball from falling from the playing field, attempting to bounce it against a number of bricks. The ball striking a brick causes the brick to disappear. When all the bricks are gone, the player goes to the next level, where another pattern of bricks appear.


The game has a brick zone in the upper part of the screen, and the player moves a paddle in the bottom, from left to right, using the mouse.


Project structure

Well, I'm going to start to write the source code, so I need to set up a space on my computer to store all the files that I will produce. I choose to use this directory tree, and I created it on my hard drive in a special place that I have reserved for my development projects (i.e "C:\My programs\" or "~/my_programs/" )

+- kronoide.1.0.0
+--- bin
+--- include
+--- obj
+--- src

I took this directory tree from my project, AlMake, that is a generic Allegro build system and template project tree.

AlMake is a group of scripts and files that helps the developer and end-user to configure, update, and build Allegro and AllegroGL projects, on many platforms, and with different compilers.

You may want to use it too, because it has a simple makefile to help you compile the source code.

Now, I will let you know what I put on each directory.

In kronoide.1.0.0 (the root), I have the makefile that came with AlMake, as well as the README, INSTALL, LICENSE, etc files.

If you plan to distribute your game, you should write at least a README file.

I encourage you to open the makefile with a text editor, and fine tune it until you are satisfied. Or better yet, write your own makefile, just to learn how to do it. Just remember to don't convert tabs to spaces on a makefile, I know why I say it.

In bin, will go the binary file (executable file), and the data files produced after compiling all sprites+sound+etc using the grabber, or, if you want to say it other way, the binary files needed to play the game.

In include, I will put all the header *.h files that I will write for this project.

In obj goes all the intermediate object files that the compiler makes while compiling the source code to a binary form.

In src, I will put all the C++ code, *.cpp files that I will write for this project.

The game loop

Almost any game needs a animation framework, this is the core that allows the game to have good game play across various OSes and hardware platforms.

The animation is managed by a loop which ensures that it progresses at a consistent rate, as independent of the hardware and OS as possible.

The rate is measured in terms of frames per second (FPS), where a frame corresponds to a single rendering of the application (game) to the screen.

My animation framework will implement double buffering drawing, a technique were the operations required for rendering are not applied directly to the screen, but to a secondary image.

When the secondary image is ready, it is displayed on screen. In that way, we don't see flicker or other artifacts.

The game loop will consist of

  1. Update logic of the game.
  2. Update graphics of the game.
  3. Render the graphics to screen.

Also, the game itself is a simple state machine, that means that the game can be only in a unique certain state in a given time (i.e playing, dying, game over, etc)

So well, the game main animation framework will live in kernel.cpp and kernel.h


In main.cpp, there is the program entry point, a start point from were the program starts running.

There, it parses the command line parameters (if any), and then start the hardware (graphics mode, sound, etc), and then start the game main loop.

The code in main is a little simple, and boring, but is really needed in order to get into a proper graphics mode and run gracefully.


Inside kernel.h, lies the Kernel class declaration, that goes like this (please refer to kernel.h, in the project zip file, for the whole text)

<highlightSyntax language="cpp"> class Kernel { public: // Operations Kernel(); // constructor ~Kernel(); // destructor

void init(); // inits the game void play(); // plays the main game loop void shutdown(); // ends the game

// Attributes

 		BITMAP *double_buffer; // the double buffer bitmap

Paddle paddle; // the player paddle Ball ball; // the game ball GameField game_field; // the game field

private: void init_game(); // this inits the game without resetting the kernel or the level, is used for when you start a new level, lose a life, etc int update(); // updates game logic void render(); // updates graphics of the game }; </highlightSyntax>

I have all the attributes public for ease of use (for us), I know that they break the encapsulation, but I aren't doing enterprise software or something, so I can take some "creative licenses" here.

The public operations of Kernel are used in the main() function (check main.cpp). After main() initializes Allegro, and the needed hardware, I just create a new game Kernel, and run it. The source code in main() (main.cpp) related to the kernel is:

<highlightSyntax language="cpp"> // run game Kernel *kernel; kernel = new(Kernel); kernel->init(); kernel->play(); kernel->shutdown(); delete(kernel); </highlightSyntax>


In kernel.cpp I implement all the functionality of the Kernel.

I will discuss first the public operations, then the private ones.

Kernel::init() is called first, and does the initialization of the game, currently it involves creating the double buffer bitmap.

<highlightSyntax language="cpp"> void Kernel::init() { double_buffer = create_bitmap(SCREEN_W,SCREEN_H); if (!double_buffer) raise_error("Kernel::init() - can't create double buffer!"); clear_bitmap(double_buffer); } </highlightSyntax>

The Kernel::shutdown() is called when I exit the game, so I leave everything nice and cleaned. I currently release the double buffer bitmap.

<highlightSyntax language="cpp"> void Kernel::shutdown() { if (double_buffer) destroy_bitmap(double_buffer); double_buffer = NULL; } </highlightSyntax>

The Kernel::play() is called to actually start playing the game itself.

It contains the main loop, together with some game logic to respond to changing logic states.

Currently, this version is a little messed up, and needs cleaning, was written in a hurry, and is really bare bones. Should be easy to understand what is doing, and works really well.

Note As you may notice below, I included a cheat code to test the levels. You should remove it later.

<highlightSyntax language="cpp"> void Kernel::play() { int ret = KERNEL_UDP_OK; // current game state, all OK int level = 1 ; // current level of the game

_start_global_timer(); // we start a global timer, check mtimer.cpp

time_counter = speed_counter = fps_counter = fps_real = 0; // we reset the global timer parameters


init_game(); // initialize a game run

game_field.do_new_random_level(3,2,1); // create a level

show_mouse(NULL); // hide mouse

// This is the main loop of the game, were all the action actually happens while (ret != KERNEL_UDP_EXIT && ret != KERNEL_UDP_QUIT) // DEBUG , ESC key should be enabled ??? maybe... maybe not { if (speed_counter > 0) // while we still have logic frames to do { ret = update(); // update game logic and see which state we are

if (ret == KERNEL_UDP_LOST_LIFE) // lost a life! { init_game(); // DEBUG - we should show a message and take down a life }

if (ret == KERNEL_UDP_NEXT_LEVEL || key[KEY_SPACE]) // DEBUG -- REMOVE THE CHEAT, the KEY_SPACE thing!! { // next level // DEBUG -- WE MUST SHOW A MESSAGE

level++; // next level :)

// pick new level parameters int l = level; int w = 3 + rand()%level + level; int h = 3 + rand()%level ; if (level > 5) l = 5; // max life of bricks if (w > GAMEFIELD_MAX_W-2) w = GAMEFIELD_MAX_W-2; // oh crap, the guy can play :o if (h > GAMEFIELD_MAX_H-2) h = GAMEFIELD_MAX_H-2; // oh crap, the guy can play :o

game_field.do_new_random_level(w,h,l); // new level init_game(); }

speed_counter--; // decrease logic frames to do } else { render(); // draw the game fps_counter++; // count frames per second (FPS) (check mtimer.cpp, this aren't the real FPS, fps_real has the real FPS } }

clear_keybuf(); _stop_global_timer(); // stop the global timer time_counter = speed_counter = fps_counter = fps_real = 0; // leave everything nice, just to be sure } </highlightSyntax>

From here, I discuss the private stuff of the Kernel class, this is the inner working of the class.

The Kernel::update() does the logic update of the game, at a constant timed rate (it is called from Kernel::play() loop), it updates everything that is needed, and returns the current state of the game in a integer code, so the loop in Kernel::play() knows what to do in the next loop iteration. <highlightSyntax language="cpp"> int Kernel::update() { int ret = KERNEL_UDP_OK; // by default, everything is OK

paddle.update(); // update the paddle logic

if (ball.update(paddle, game_field)) ret = KERNEL_UDP_LOST_LIFE; // player lost life :(

if (game_field.update()) ret = KERNEL_UDP_NEXT_LEVEL; // gamefield clear, go to next level \\o o//

if (key[KEY_ESC]) // exit game -- DEBUG , WE MUST CONFIRM THIS!! ret = KERNEL_UDP_EXIT;

return ret; } </highlightSyntax>

Now, I move to the graphics system, the Kernel::render(), that does all the needed drawing of the game to show it to screen.

<highlightSyntax language="cpp"> void Kernel::render() { clear_bitmap(double_buffer); // debug - here we should/could blit the background

// first, everything gets drawed to the double buffer bitmap game_field.render(double_buffer); // render the game field (the bricks) paddle.render(double_buffer); // render the paddle ball.render(double_buffer); // render the ball

// after that, we blit (draw) the double buffer to screen blit(double_buffer, screen, 0,0,0,0,SCREEN_W, SCREEN_H);

} </highlightSyntax>

Finally, I have this useful function, Kernel::init_game(), his purpose is to reset the level, without resetting the game main state. What it does is basically re-position the paddle, the ball, and the mouse, and is called when I lose a ball for example. (check Kernel::play() to see it working)

<highlightSyntax language="cpp"> // Kernel::init_game() // this inits the game without resetting the kernel or the level // is used for when you start a game , lose a life, etc void Kernel::init_game() { paddle.init(); // init the paddle

ball.init(); // init the ball

ball.sticky_time = BPS_OF_TIMER_MANAGER * 3; // 3 secs before launch of ball =)

position_mouse((int)paddle.x , (int)paddle.y ); // put the mouse cursor in paddle

clear_keybuf(); // clear keyboard buffer } </highlightSyntax>

The gamefield


As is shown in the screen shoot, the gamefield is composed of bricks, that are destroyed by hits of the ball.


Here I can see the structure of the Gamefield class.

<highlightSyntax language="cpp"> class GameField { public: // Operations GameField(); ~GameField();

void do_new_random_level(int w, int h, int max_life); // creates a new level size w*h, with 1..max life for bricks

bool update(); void render(BITMAP *bmp);

bool ball_hit_brick(int x_px , int y_px); // this is used by the ball to hit the bricks, returns true if a brick was hit

// Attributes

Brick bricks[GAMEFIELD_MAX_W][GAMEFIELD_MAX_H]; int w, h; // current width and height in bricks, must be < GAMEFIELD_MAX_* int bc; // brick count, when bc==0, next level }; </highlightSyntax>

I took a really easy approach (that wastes some bytes of memory), so the gamefield is composed of a 2-dimensional array of bricks, that can have a maximum size. Since the game is simple, all the levels are random generated. Also, I have a helper function that lets us do the ball hits a brick check and update.


The implementation is really simple, and I will describe the important bits below.

This GameField::do_new_random_level(int w, int h, int max_life) creates a new level.

It takes the width and height of the level, and the maximum life that each brick can have (how many hits it can take before it breaks and disappears).

The algorithm is very simple, it just fills the matrix with random coloured bricks, and each brick has a size proportional so the gamefield takes all the screen width, and one third of the screen height.

<highlightSyntax language="cpp"> void GameField::do_new_random_level(int w, int h, int max_life) { if (w < 1 || w > GAMEFIELD_MAX_W) w = GAMEFIELD_MAX_W; // safe check if (h < 1 || h > GAMEFIELD_MAX_H) h = GAMEFIELD_MAX_H; // safe check

this->w = w; this->h = h; bc = 0;

// fill the matrix with random level for (int y = 0 ; y < h; y++) { for (int x = 0 ; x < w; x++) { bricks[x][y].life = rand() % max_life + 1;

bricks[x][y].x = x * SCREEN_W / w; bricks[x][y].y = y * SCREEN_H / 3 / h;

bricks[x][y].w = SCREEN_W / w; bricks[x][y].h = SCREEN_H / 3 / h;

// pick a random color bricks[x][y].c.r = rand_ex_i(128, 255); bricks[x][y].c.g = rand_ex_i(128, 255); bricks[x][y].c.b = rand_ex_i(128, 255);

bc ++; // count bricks (lame) } } } </highlightSyntax>

The logic update() currently does nothing more that just return true if I don't have more bricks left (I won the level), or false if I still have bricks left.

<highlightSyntax language="cpp"> // returns true if we finished the level (0 bricks left) bool GameField::update() { return (bool)(bc < 1); } </highlightSyntax>

Here, GameField::render(BITMAP *bmp) renders the game field (the bricks)

<highlightSyntax language="cpp"> void GameField::render(BITMAP *bmp) { for (int y = 0 ; y < h; y++) for (int x = 0 ; x < w; x++) bricks[x][y].render(bmp); } </highlightSyntax>

GameField::ball_hit_brick() checks the hit of the ball in a given x_px, y_px position (in pixels). The ball coordinates in pixels are translated to brick coordinates, and then a check is performed against the gamefield matrix. If the ball hit a brick, the life of the brick is decreased, and if it reaches zero, I count a brick less (so I can know when to pass the level). Will return false if I didn't hit anything, or true otherwise.

<highlightSyntax language="cpp"> bool GameField::ball_hit_brick(int x_px , int y_px) { // this is used by the ball to hit the bricks, returns true if a brick was hit int w_b = SCREEN_W / w; int h_b = SCREEN_H / 3 / h;

if (y_px < 0 || x_px < 0 || y_px / h_b > h || x_px / w_b > w) return false; // ball too low or out of bounds

if (bricks[x_px / w_b][y_px / h_b].life > 0) { bricks[x_px / w_b][y_px / h_b].life--;

if (bricks[x_px / w_b][y_px / h_b].life <= 0) bc--; // wasted brick!

return true; // hit! }

return false; } </highlightSyntax>

The bricks

As I already said, the gamefield is composed of bricks.


Each brick has a life (hits remaining before breaking), a position (x,y), width and height (w,h), and a RGB color (c). The class declaration looks like this: <highlightSyntax language="cpp"> class Brick { public: // Operations Brick(); ~Brick();

void update(); void render(BITMAP * bmp);

// Attributes int life; // life, in ball hits

int x; // position, in pixels int y;

int w; // size, in pixels int h;

RGB c; // color, in R,G,B }; </highlightSyntax>


The brick implementation is really simple, there is only one interesting function here.

Each brick is a rectangle that is draw in Brick::render(BITMAP *bmp)

<highlightSyntax language="cpp"> void Brick::render(BITMAP *bmp) { if (life < 1) return; // we don't draw broken bricks if (w > 12 && h > 12) // check if the brick is big enough to shadow it { // render with shadow rectfill(bmp, x, y, x + w, y + h, makecol((int)(c.r*0.8), (int)(c.g*0.8), (int)(c.b*0.8))); rectfill(bmp, x+3, y+3, x + w-3, y + h-3, makecol((int)(c.r*0.9), (int)(c.g*0.9), (int)(c.b*0.9))); rectfill(bmp, x+6, y+6, x + w-6, y + h-6, makecol(c.r, c.g, c.b)); } else { // render normal rectfill(bmp, x, y, x + w, y + h, makecol(c.r, c.g, c.b)); } }</highlightSyntax>

The paddle

The paddle is how the player prevents the ball for going outside the screen. He moves the paddle using the mouse.


The paddle is composed of a position (x,y), a width, height (w,h), and a RGB color (c).

<highlightSyntax language="cpp">class Paddle { public: // Operations Paddle(); ~Paddle(); void init(); void update(); void render(BITMAP * bmp);

// Attributes float x; float y; int w; int h; RGB c; };</highlightSyntax>


The paddle has little stuff to do, it just moves from left to right, and bounces the ball.

Paddle::init() just sets the paddle in the starting position. I encourage you to play with this values.

<highlightSyntax language="cpp"> void Paddle::init() { // lame default values... DEBUG - this should be better done w = (int)(SCREEN_W * 0.20); h = (int)(SCREEN_H * 0.05);

x = SCREEN_W / 2; y = SCREEN_H - h - 10;

// paddle color c.r = 0; c.g = 128; c.b = 200;

} </highlightSyntax>

This Paddle::update() does the control of paddle, using the mouse position. There is not a lot to explain. Also, keeps a eye to make sure the paddle stays inside the screen. <highlightSyntax language="cpp"> void Paddle::update() { // mouse control... little lame

x = mouse_x - (w / 2); //y = mouse_y - (h / 2); // I disabled the Y movement for now -- DEBUG

if (y < SCREEN_H - (SCREEN_H / 3)) y = SCREEN_H - (SCREEN_H / 3);

if (y > SCREEN_H - h) y = SCREEN_H - h;

if (x < 0) x = 0;

if (x > SCREEN_W - w) x = SCREEN_W - w; } </highlightSyntax>

The Paddle::render() draws the paddle, which is just a shadowed rectangle. You could, as a exercise, replace this drawing code, for example with a sprite, or a gradient. <highlightSyntax language="cpp"> void Paddle::render( BITMAP * bmp ) {

rectfill(bmp, (int)x, (int)y, (int)x + w, (int)y + h, makecol((int)(c.r*0.6), (int)(c.g*0.6), (int)(c.b*0.6))); rectfill(bmp, (int)x+2, (int)y+2, (int)x + w-2, (int)y + h-2, makecol((int)(c.r*0.7), (int)(c.g*0.7), (int)(c.b*0.7))); rectfill(bmp, (int)x+4, (int)y+4, (int)x + w-4, (int)y + h-4, makecol((int)(c.r*0.8), (int)(c.g*0.8), (int)(c.b*0.8))); rectfill(bmp, (int)x+6, (int)y+6, (int)x + w-6, (int)y + h-6, makecol((int)(c.r*0.9), (int)(c.g*0.9), (int)(c.b*0.9)));

rectfill(bmp, (int)x + 8, (int)y + 8, (int)x + w - 8, (int)y + h - 8, makecol(c.r, c.g, c.b)); } </highlightSyntax>

The ball

The ball is a very important piece of the gameplay. With the ball, the player removes the bricks in order to move fordward in the levels.


The ball is composed of a position (x,y), a direction (dx,dy), a radius (r), and a color (c).

Also, it has a time of the ball to be "sticky" (glued) to the paddle. After this time expires, the ball is released.

<highlightSyntax language="cpp"> class Ball { public: // Operations Ball(); ~Ball(); void init(); bool update(Paddle &paddle, GameField &game_field); void render(BITMAP * bmp);

// Attributes // position float x; float y;

// direction (speed in x,y) float dx; float dy;

// radius int r;

// color RGB c;

// time of the ball to be "sticky" to paddle... after this time ,the ball releases... given in tick counts int sticky_time; private: void bounce_x(); void bounce_y(); }; </highlightSyntax>


The implementation of the ball don't has secrets, is very simple. I will explain only the important stuff.

Ball::update(Paddle &paddle, GameField &game_field) updates the ball. Returns true if the ball was lost (I lose a life).

This is possible the most complicated part of the entire game.

I receive the player's paddle, and the gamefield, so I can check against them.

<highlightSyntax language="cpp"> bool Ball::update(Paddle &paddle, GameField &game_field) { static float paddle_last_y = 0; // we use this so the ball can't go trough the paddle, we interpolate

if (sticky_time > 0) {

sticky_time--; x = paddle.x + paddle.w / 2; y = paddle.y - r;

if (mouse_b & 1) // mouse button is pressed, release the ball sticky_time = 0;

if (sticky_time <= 0) // time is up? { // do the up release dy = -rand_ex_f(BALL_MIN_SPD ,BALL_MAX_SPD ); dx = rand_sign_switch(rand_ex_f(BALL_MIN_SPD,BALL_MAX_SPD )); } return false; // we are stick to the paddle. all OK } else sticky_time = 0;

// upgrade ball position with speed x,y x += dx; y += dy;

// bounce on field bounds if (x < r) { x = r; bounce_x(); }

if (x > SCREEN_W - r) { x = SCREEN_W - r; bounce_x(); }

if (y < r) { y = r; bounce_y(); }

if (y > SCREEN_H - r) // here we DIE ... { return true; // oops >;^) shit happens /* y = SCREEN_H - r; bounce_y(); */ }

// bounce on paddle, only if going down =P if (x + r > paddle.x && x - r < paddle.x + paddle.w && (y + r > paddle.y || y + r > paddle_last_y ) && (y - r < paddle.y + paddle.h || y - r < paddle_last_y + paddle.h)) { y = paddle.y - r; // this is lame safe check

bounce_y(); }

// bounce and hit on bricks if (game_field.ball_hit_brick((int)x-r,(int)y) || game_field.ball_hit_brick((int)x+r,(int)y)) bounce_x();

if (game_field.ball_hit_brick((int)x,(int)y-r) || game_field.ball_hit_brick((int)x,(int)y+r)) bounce_y();

// never go faster than paddle size, or we are screwed :P if (dy > paddle.h*0.25) dy = paddle.h*0.25;

if (dy < -paddle.h*0.25) dy = -paddle.h*0.25;

if (dx > paddle.w*0.25) dx = paddle.w*0.25;

if (dx < -paddle.w*0.25) dx = -paddle.w*0.25;

paddle_last_y = paddle.y; // save our last position

return false; // all OK for now } </highlightSyntax>

The ball has to bounce around, since I'm doing a simple tutorial, I really simplified the physics of the ball, so the bounce is a little weird, but works OK. This two functions, Ball::bounce_x() and Ball::bounce_y() are helpers for the bouncing of the ball, and give the ball a random spin in the bounce direction. I use random number generation functions defined in krandom.cpp and krandom.h, so I can easily get numbers inside a range.

<highlightSyntax language="cpp"> void Ball::bounce_x() { dx = -rand_ex_f(dx * 0.9, dx * 1.1);

if (rand() % 100 < 10) dx = rand_sign_switch(rand_ex_f(BALL_MIN_SPD , BALL_MAX_SPD )); }

void Ball::bounce_y() { dy = -rand_ex_f(dy * 0.9, dy*1.1); } </highlightSyntax>

Ball::render() just renders the ball, is a shadowed ball.

<highlightSyntax language="cpp"> void Ball::render(BITMAP * bmp) { circlefill(bmp, (int)x, (int)y, r, makecol((int)(c.r*0.6), (int)(c.g*0.6), (int)(c.b*0.6))); circlefill(bmp, (int)x, (int)y, r-2, makecol((int)(c.r*0.8), (int)(c.g*0.8), (int)(c.b*0.8))); circlefill(bmp, (int)x, (int)y, r-4, makecol(c.r, c.g, c.b)); } </highlightSyntax>

Miscellaneous source files

I have some files in the project that aren't really related to the gameplay, but are really needed in order to get the game working.

gerror.cpp, gerror.h

This files serve the purpose of gracefully reporting errors to the player. The only function is raise_error(), which works like printf(), but it will show a error message in a way appropriate to the platform, and then will finish the game and return to the operating system.

<highlightSyntax language="cpp">/// Goes back to text mode, shows the message and ends the program. Printf style. void raise_error(AL_CONST char *msg, ...); </highlightSyntax>

I use it to report critical errors, like the lack of memory, or a proper graphics video mode.

mtimer.cpp, mtimer.h

Here I have a global timer system to be used in the game. The timer system allows the game to run at the same speed on different hardware (so the game don't runs too fast on new machines or too slow on old ones). Thanks to this timer, I can measure how fast the game is going, and keep the logic updates at a constant frame rate. The drawed frames per second (FPS) are stored in the global variable fps_real The functions here are: <highlightSyntax language="cpp">void _start_global_timer(); ///< starts global timer void _stop_global_timer(); ///< stops global timer </highlightSyntax>

krandom.cpp, krandom.h

The functions here are:

<highlightSyntax language="cpp"> int rand_ex_i(int min, int max); // integer version float rand_ex_f(float min, float max); // floating point, with 3 decimals

// version for switching the sign (positive, negative) int rand_sign_switch(int number); float rand_sign_switch(float number);</highlightSyntax>

With this functions, I can easily choose random numbers in a given range, integers or floats.


To build the project, I used a makefile. That way, in the command line (for example, bash), you just type "make" (without the ") and the thing compiles (if the development environment is set up fine).

In computer programming, make is a utility for automatically building large applications. Files specifying instructions for make are called Makefiles. make is most commonly used in C/C++ projects, but in principle it can be used with almost any compiled language.

The makefile that I used is AlMake, a makefile made specially for Allegro projects, that you can use too, and can be downloaded here. AlMake is a group of scripts and files that helps the developer and end-user to configure, update, and build Allegro and AllegroGL projects, on many platforms, and with different compilers. The main feature is that is multiplatform, and auto detects most common configurations, thus is so easy as just running 'make' on project dir.

Example of a compilation of Kronoide in GNU/Linux Ubuntu

kronoman@motorhead:~/pixelate/kronoide_tutorial/kronoide.1.0.0$ make
g++ -Iinclude -Wall -O3 -fomit-frame-pointer -c src/ball.cpp -o obj/linux/ball.o
g++ -Iinclude -Wall -O3 -fomit-frame-pointer -c src/brick.cpp -o obj/linux/brick.o
g++ -Iinclude -Wall -O3 -fomit-frame-pointer -c src/gamefield.cpp -o obj/linux/gamefield.o
g++ -Iinclude -Wall -O3 -fomit-frame-pointer -c src/gerror.cpp -o obj/linux/gerror.o
g++ -Iinclude -Wall -O3 -fomit-frame-pointer -c src/kernel.cpp -o obj/linux/kernel.o
g++ -Iinclude -Wall -O3 -fomit-frame-pointer -c src/krandom.cpp -o obj/linux/krandom.o
g++ -Iinclude -Wall -O3 -fomit-frame-pointer -c src/main.cpp -o obj/linux/main.o
g++ -Iinclude -Wall -O3 -fomit-frame-pointer -c src/mtimer.cpp -o obj/linux/mtimer.o
g++ -Iinclude -Wall -O3 -fomit-frame-pointer -c src/paddle.cpp -o obj/linux/paddle.o
g++ obj/linux/ball.o obj/linux/brick.o obj/linux/gamefield.o obj/linux/gerror.o obj/linux/kernel.o obj/linux/krandom.o obj/linux/main.o obj/linux/mtimer.o obj/linux/paddle.o -o bin/kronoide -s `allegro-config --libs`
The bin/kronoide is ready!
Finished Kronoide
Product is at bin/kronoide.
Makefile script done with AlMake - Generic Allegro build system
Get updates of AlMake at official website:

Features to add to the game

This game is very simple, and can be vastly improved. It would be a great exercise to add features to it, for example

  • Score system, level count and messages on screen.
  • Life count and game over.
  • Introduction screen, about screen, etc...
  • Particle system (so the bricks explode!)
  • Power ups (multiball? should not be that hard to implement)
  • A nice background or background set instead of plain black. (Maybe fractals?)
  • Sound and/or music.
  • Keyboard and joystick support to move the paddle.
  • Level editor (to avoid random generated levels).
  • Better graphics (use sprites)

Your imagination is the limit... start hacking it! :)