You are on page 1of 50

C++ Basic Lessons

Why C++?
C++ is a simple yet powerful Object Oriented programming language. It has almost all
the same uses as C, but brings a few new features to the table, along with simpler code.
One of the new features is a data type called class, which is used to create objects.
Objects will allow you to write your code in a more organized fashion, instead of having
data scattered about. This makes it much easier for the different functions throughout
your program to access the data they need in order to get the job done. This way the
amount of code you have to write is reduced significantly, thus making your program
easier to maintain.
Where to start
First thing you will need is a compiler. A compiler basically takes the code you write and
translates it into a form the computer will understand so that it can be executed. I used
Dev-C++ for the examples you will find throughout this site, although the code should
work with most compilers. Dev-C++ can be found on Bloodshed's site.
Lets Begin
Now that you have your compiler, lets move on to actually learning how to code C++. If
you are using Dev-C++, the first thing you are going to want to do once you open it is
select "File" > "New" > "Project. Then select "Console Application" and name your
project. Once finished you will be presented with a small program, simply erase this so
we can begin! Our first program will simply send "Hello World!" to the screen, here is
the code:
//My first program

#include <iostream>

using namespace std;

int main(){

cout << "Hello World!\n";

system("Pause");

Now lets break this down. The first line "//My first program" is a comment, the compiler
will ignore this line completely. To add comments to your program, simply begin the line
with "//" and anything after that will be ignored.

The first line of actuall code tells the compiler that we want to include "iostream" in our
program. iostream is part of the standard library, all C++ compilers will understand any
command included in any part of the standard library. iostream contains the basic I/O
functions used to write to the screen and recieve input from the user.
The next line "using namespace std;" defines what namespace we will be using, in this
case std. A namespace is basically a list of variable and function names, in order to not
get standard library names mixed with others, the standard library creates the namespace
std, so any time you want to use a command from the standard library you must include
this line. The semicolon at the end of the line is needed for almost every line in C++, this
tells the compiler that it has reached the end of that line.

"int main(){" this is a function decleration. A function is a block of code which begins
and ends with a pair of curly brackets " { } ". This way we have a way of referencing this
block of code in case if we want the program to run the same code multipule times.
Functions also help keep the code looking clean. "int" is the data type the function
returns, we will discuss data types later. "main" is the name of this function, every C++
program must have a main() function, this is where the program will begin to execute. If
you want to pass a variable to a function, you would place the type of variable and
specify a name for it between the parenthesis, for example "int myFunction( int
number)". The curly braket shows where the function begins.

"cout << "Hello World!\n";" This line displays the text "Hello World!" on the screen. cout
takes the text using "<<" which is known as an insertion operator. Think of it as a funnel,
we want the data, in this case "Hello World!", to be "funneled" into cout. The "\n" means
new line, its like pressing the enter key while typing in a text editor.

"system("Pause");" system() is used to send commands to the operating system, in this


case we are sending "pause" which is a DOS command which pauses the screen until the
user presses any key. I included this because once the program runs out of code to
execute, it will close the window and you will not get a chance to see the results.

Ok now lets see it in action, type the code into Dev-C++, do not copy and paste it. You
can copy and paste if you want, it will work just fine, but it will help you memorize the
code quicker if you type it yourself. Once done, save it and press the compile button,
once it finished press the run button. You should be presented with a DOS prompt which
will give you this output:

Hello World!
Press any key to continue...

Too easy isn't it? Lets move on to data types.

Data types
So far you've seen how to display whatever you put into your program, now lets see how
to get input from the user. Before doing this we need somewhere to store the data the user
gives us, this is where the different data types come in. Here is a list of the basics data
types:
int: used to store integers (whole numbers, no decimals/fractions)
long: used to store larger integers
double: used to store numbers with two decimal places
float: used to store numbers with multiple decimal places
char: used to store a single character

Ok now lets see these in action:


#include <iostream>

using namespace std;

int a;

int main(){

int b;
int c;

cout << "Enter a number: ";


cin >> a;

cout << "Enter a second number: ";


cin >> b;

c = a+b;

cout << "The sum is: " << c << "\n";

system("pause");

Here I declared three integers, a, b, and c. Notice how "a" is outside of main()? In this
case, a would be known as a global variable, all functions can access it freely, but since b
and c were declared inside of main() it is only accessible to main().

The next new line would be "cin << a+b;". Here we see the insertion operator again,
except this time its pointing in the other direction. Since cin is the command for input, we
want to "funnel" the data from the function to the variable.

After collecting the information from the user we use it to give c a value. "c = a+b;" give
c the value of the sum of a and b, you can also use - for subtraction, * for multiplication,
and / for division.

Finally we display the value of c, notice how there are two insertion operators in the final
output? This allows us to display text and variables in one line instead of having to write
"cout" several times. Notice how text is written in between quotes and variables are
without quotes. If you wanted to assign a variable a number you would not use quotes
either ( int a = 10; ).

Arrays
In the last lesson we saw how to create simple variables and store user input in them.
Now we will look into arrays. An array is simply a list of variables of the same type. Lets
say your program required you to keep track of 100 integers, in which case you would
have to create 100 integers by typing up each one, one by one... Needless to say that
would take quite a while, but with arrays you can cut the typing down to one single line!
Lets see how it works:
#include <iostream>

using namespace std;

int main(){

int myArray[3];

cout << "Enter a number: ";


cin >> myArray[0];

cout << "Enter a second number: ";


cin >> myArray[1];

myArray[2] = myArray[0]+myArray[1];

cout << "The sum is: " << myArray[2];

system("pause");

Here we have the same sample program from the previous lesson, except I replaced the
three integers with a single array made up of three integers. "int myArray[3];" creates an
array of three integers. Each integer inside this array will have a corresponding number,
starting at 0. So in this case the three integers are myArray[0], myArray[1], and
myArray[2]. Since 0 counts, there is not myArray[3]! Everything else is exactly the same.

You can also use arrays to store a string of text by creating an array of characters. Here
you would make the array the max size of characters you want plus one, since strings
must end the null character (null mean nothing, not 0, just nothing). We will look more
into strings in a latter lesson though.

Two Dimensional Arrays


2D arrays work just like normal arrays except they have two numbers per variable. In
order to declare one you would add an extra pair of brackets (int my2dArray[3][3]). Here
is a graphical representation of a 2D array:
XXX
XXX
XXX

These will come in handy when you are programming graphics and animations, lets see
an example program:
#include <iostream>

using namespace std;


int main(){

int myArray[10][10];
for (int i = 0; i <= 9; ++i){

for (int t = 0; t <=9; ++t){

myArray[i][t] = i+t; //This will give each


element a value

for (int i = 0; i <= 9; ++i){

for (int t = 0; t <=9; ++t){

cout << myArray[i][t];

system("pause");

Ignore the for loops for now, we will look into those in the loops lesson. This program
simply assigns a value to each element in myArray and then displays each one. As you
can see there is not much difference between using normal arrays and 2d arrays.
If-Then-Else
Now we will look into how to get our programs to compare values. A conditional
statement checks to see if the conditions you are looking for are met or not, if they are
they will execute a certain block of code, if not they will keep on. Here is an example:

#include <iostream>

using namespace std;

int main(){

int a;
int b;

cout << "Enter a value for a: ";


cin >> a;

cout << "Enter a value for b: ";


cin >> b;

if (a > b){
cout << a << "Is greater than" << b;

} else if(a < b){

cout << a << "Is less than" << b;

} else {

cout << a << "Is equal to" << b;

Here we see what is known as an if-then-else statemnt. I basically reads "If a is greater
than b execute this code" if it is not greater it will move on, if it is true it will execute
what ever you place in between its curly brackets and continue ignoring any line that
begins with else after it. If it is false, the program will check the next condition "else if(a
< b){" which basically reads "If the condition above is false and a is less than b execute
this code". Finally, if that one proves false as well the program will go to the final "else"
which has no conditions so will always be executed if the above conditions were false.
Here are a list of the condition you can chck for:
== : equality, must use two equal signs
< : less than
> : greater than
<=: less than or equal to
>= : greater than or equal to
!= : not equal

You can also check for more than one condition with a single if by using && (for and)
and || (for or). For example:
if( a == 1 && b != 2) // will return true if a has a value of 1 and b
does not have a value of 2

if( a == 1 || b != 2) // will return true if a has a value of 1 or if b


does not equal 2

Switch Case
The switch case works much like a lot of if-then-else statements put together. It takes one
value and compares it against many others. Here is an examle:

#include <iostream>

using namespace std;

int main(){
int a;

cout << "What time of day is it?\n";


cout << "1) Morning\n";
cout << "2) Afternoon\n";
cout << "3) Evening\n";
cout << "Enter a choice: ";
cin >> a;

switch (a){

case 1:
cout << "Good Morning!";
break;
case 2:
cout << "Good Afternoon!";
break;
case 3:
cout << "Good Evening!";
break;

default:
cout << "Not a valid entry...";
break;

Notice how after each case, there is a colon not a semicolon. The last command in each
case must be "break;" if not it will continue to execute any code following it. "break;" can
be used to break out of any conditional statement or loop. "default" is included incase the
user eneters an invalid entry, when ever the variable doesnt match any case, the default
block is executed.
Strings
A string is an array of characters. In order to get text from a user you must use a string.
Strings work a bit different from other arrays though, here we will look into the different
funcitons used for strings. Here is an example:

#include <iostream>

using namespace std;

int main(){

char myArray[50];

cout << "Whats the password? ";

cin.getline( myArray, 50, '\n');

if( !strcmp( myArray, "cheesecake")){


strcat( myArray, " is correct! Access granted!\n");

} else {

strcpy( myArray, "Invalid password!\n");

cout << myArray;

system("pause");

Here we begin by declaring a string of 50 characters. The first line with a new function
would be "cin.getline( myArray, 50, '\n');", the first parameter getline() takes is the string
you want to store the data in, next is the max amount of characters allowed, and finally
what you want the string to be terminated with.

"if( !strcmp( myArray, "cheesecake")){" will check if myArray is equal to cheesecake.


Notice how I used the Not operator here, this is because strcmp returns false if the
condition is met. Also remember strcmp() is case sensitive!

"strcat( myArray, " is correct! Access granted!\n");" This will add " is correct! Access
granted!\n" to the end of myArray, you can also place another string in place of the text in
order to join two strings.

"strcpy( myArray, "Invalid password!\n");" This will replace myArray with "Invalid
password!\n". Whatever was in myArray will be wiped out and replaced by the text.

While Loop
Loops are used to loop back and execute the same block of code over and over again until
a certain condition is met. Heres an example using the while loop:
#include <iostream>

using namespace std;

int main(){

int a;

cout << "How many times do you want the loop to run? ";
cin >> a;

while (a){
cout << a << "\n";
--a;
}
return 0;

}
This code takes a value from the user and runs a while loop that many times. The
conditions used for the while loop are the same as the if-then-else statements, same goes
for every loop. Here since I only put "a" the program will read "While a is true execute
this block" and as long as a is a positive integer it is considered to be 'true'.
For Loop
The for loop works a little bit differently. Instead of taking just one parameter, it takes
three. The first is the variable you want to use, you can either use an existing one, or
declare one within the for loop. The second parameter is the condition, and the third is
used to change the value of the variable chosen in the first parameter. Lets look at the
code from the Arrays lesson:
#include <iostream>

using namespace std;

int main(){

int myArray[10][10];
for (int i = 0; i <= 9; ++i){

for (int t = 0; t <=9; ++t){

myArray[i][t] = i+t; //This will give each


element a value

for (int i = 0; i <= 9; ++i){

for (int t = 0; t <=9; ++t){

cout << myArray[i][t];

system("pause");

Here the first for loop defines i as an integer with a value of 0. Since the array is 10x10
and 0 counts when counting the elements of an array, we will run the loop until i is equal
or greater than 9. "++i" means "add 1 to i", it can be used with any numeric data type.
Since the array is two dimensional we will need a second for loop to get the second index
number. This is setup the exact same way, except I used a t instead of an i. So now every
time the first for loop runs, the second will run 10 times, and then return to the first until
the first has been run 10 times thus covering every element in the array.
Functions
Functions are used to define a block of code, unlike the loops we discussed earlier,
functions can be called from any place in your program so that you do not have to repeat
the same code over and over again. Here is a basic function at work:
#include <iostream>

using namespace std;

int addNumbers( int a, int b){

return a+b;

int main(){

int a;
int b;

cout << "Enter a number: ";


cin >> a;

cout << "Enter an other number: ";


cin >> b;

cout << "Sum of the two numbers is: " << addNumbers( a, b) <<
"\n";

system("pause");

return 0;

}
Here we create a function called addNumbers, which returns an integer. main() collects
the data from the user and then sends it to addNumbers(), notice how I declared the
integers in both main() and addNumbers. This is because the ones in main() are local
variables which cannot be touched by other functions. The parameters for addNumbers()
does not have to be the same as the variables containing the values being sent to
addNumbers(). Once addNumbers() is called, it takes the values given to it by main() and
returns the sum of them to the function that called it, which in this case is main(). Also
notice how addNumbers() goes before main(). If you flip them around it will error out. If
a function is being called by a function that apears before it in your source file, it must be
declared at before it is called. Here is an example of this:
#include <iostream>

using namespace std;

int addNumbers( int a, int b);

int main(){

int a;
int b;

cout << "Enter a number: ";


cin >> a;

cout << "Enter an other number: ";


cin >> b;

cout << "Sum of the two numbers is: " << addNumbers( a, b);

system("pause");

return 0;

int addNumbers( int a, int b){

return a+b;

File I/O
File input and output is extremely simple in C++ compared to C. It works just like
reading and writting to standard I/O. In order to use the C++ functions needed to
accomplish file I/O you must include the header file . Here is an example:
#include <iostream>
#include <fstream>

using namespace std;

int main(){

ofstream outputFile("file.txt"); //ofstream will create the file


if it doesn't exist, ifstream will not
ifstream inputFile;

char myString[50];

cout << "Enter a string: ";


cin.getline( myString, 50, '\n');

cout << "Writting string to file...\n";

outputFile << myString;

outputFile.close();

inputFile.open("file.txt");

cout << "Reading string from file...\n";

inputFile.getline(myString, 50, '\n');


cout << myString;

system("pause");

return 0;

}
Here are two new data types, ofstream and ifstream. When a program open a file it asigns
it a number called a handle in order to keep track of it, this is what is assigned to the
ofstream and ifstream type variables every time you open a file. As you see there are two
was of opening a file, at the declaration, "ofstream outputFile("file.txt");", and anywhere
else by using open(), "inputFile.open("test.txt");".

Output works just like cout, and input works exactly like cin! Notice how I used getline()
with inputFile and it worked exactly like it would with cin.

If a file is opened from an ifstream and the file does not exist, it will not create the file.
Ofstream will create a non-existant file, but will also wipe out its contents. What if you
wanted ifstream to create the file, and ofstream not to? Or have ofstream add to a file
rather than delete it? Heres how:

#include <iostream>
#include <fstream>

using namespace std;

int main(){

ofstream outputFile("file.txt", ios::app); //ofstream will


append to file
ifstream inputFile;

char myString[50];

cout << "Enter a string: ";


cin.getline( myString, 50, '\n');

cout << "Writting string to file...\n";

outputFile << myString;

outputFile.close();

inputFile.open("file.txt");

cout << "Reading string from file...\n";

inputFile.getline(myString, 50, '\n');


cout << myString;

system("pause");

return 0;

}
Here we have the same program from before, except we are now adding on to file.txt.
Here are other options for files:
ios::app - Apend
ios::trunc - wipe out file
ios::ate - Set position at end of file

Classes
Now for the object oriented programming. Classes are used to create object which can be
given different properties and functions just like real life objects making them easier to
work with than just a bunch of lose variables. Heres an example:
#include <iostream>

using namespace std;

class dog{

public:

dog();
~dog();
int getAge();
void setAge(int a);

protected:
int age;

};

dog::dog(){

dog::~dog(){

int dog::getAge(){

return age;
}

void dog::setAge(int a){

age = a;
}

int main(){

dog myDog;

myDog.setAge(5);

cout << "The dog is " << myDog.getAge() << " years old!\n";

system("pause");

return 0;

}
Here I started by creating a class called "dog". After the class declaration I definded some
variables and functions as public and others protected. Public means any function can
access them, protected ones can only be called from inside the class. Classes have two
special functions called the constructor ( dog() ) and the deconstructor (~dog() ) which
are called when an instance of the class is created and destroyed respectively.

"dog myDog" creates an instance of dog called myDog, myDog would be the actuall
object modelled after the dog class. In order to run a function inside a class you must use
the name of the instance followed by a "." and the name of the function
(myDog.setAge()). The same goes for any public variables you may have declared.

Array of Classes
A class by itself, such as the Dog class from the "Classes" tutorial, is quite useless. To
make good use of such a class for video game programming purposes we need to be able
to group several of them, this way we can minimize code when it comes to controling
several objects at a time. This can be done by creating an Array of the object just like you
would with any other data type. I will be splitting this programming up into several files
as well, this will help keep things organized once your programs get bigger. Heres the
example code:
//Dog.h
#ifndef DOG_H
#define DOG_H 1

class Dog{

public:

Dog();
int getAge();
void setAge(int newValue);

protected:
int age;

};

#endif

This is the header file for the Dog class, it simply holds the prototype for the class, the
actual code will be in a seperate file, Dog.cpp. The "#ifndef DOG_H" line is used to
make sure Dog isnt declared twice.
//Dog.cpp
#include "Dog.h"

Dog::Dog(){

int Dog::getAge(){

return age;

void Dog::setAge(int newValue){

age = newValue;

Dog.cpp first includes its header file in order to have the prototype for the class, the code
here should be familiar from the last lesson.
//main.cpp
#include <iostream>
#include "Dog.h"

using namespace std;

int main()
{

Dog myDogs[5];

for (int i = 0; i <= 4; i++)


myDogs[i].setAge( i * 2);

for (int i = 0; i <= 4; i++)


cout << "Dog number " << i << " is " << myDogs[i].getAge() << "
years old!\n";

delete [] myDogs;

return 0;
}
main.cpp holds the code for the actual program. It only needs to include the header file
for the class, not the actuall code file (Dog.cpp). Dog myDogs[5]; simply creates an array
of 5 Dogs, just like using any other built in data type.

In order to access each individual Dog, simply include its index number in the brackets,
and use it as you would any normal class. This example simply sets their age and displays
it.

Multi-threading
So far we've seen how to make games using a while loop that gives each process its own
turn, lets look into getting the game to run all these steps at once. Here is some example
code:
#include <iostream>
#include <process.h>

using namespace std;

void myFunction( void* number){

int myNumber = *(int*)number;

cout << "This is prcosses number: " << myNumber << "\n";

_endthread();

int main(int argc, char *argv[])


{
int tempNum[10];

for( int i = 0; i <= 9; i++){


tempNum[i] = i;
_beginthread( myFunction, 0, (void*)&tempNum[i]);
}

system("PAUSE");
return 0;
}

The new commands introduced here are _beginthread() and _endthread(), both included
in process.h. _beginthread() takes 3 parameters, first is the function you want to run, in
this case myFuntion, second is the size of the stack (just set this to 0), and third, any
parameter you want to send. If no parameters are to be sent, the function still must accept
a void* parameter, when actually calling _beginthread() set the last parameter to 0. For
example:
void myFunction( void* dummy){

....
code here
....

_beginthread( myFunction, 0, 0);


Notice the way the parameter is sent, its converted from what ever type it orginally was to
void*, this allows any data type to be sent using this function. Also make sure to place the
'&' infront of the variable, this will pass the memory address the variable points to instead
of the value.

In the function being called by _beginthread() you need to convert any parameters (unless
if there are none) back to their original data type. Just replace the int in "*(int*)number;"
to whatever datatype you need, and you can continue using the information as usual.

_endthread() will terminate the thread, its not necessary to use it since it will
automatically be called once the function called by _beginthread() ends.

Each thread doesn't actually run at the exact same time, processor time will be divided up
between the functions, since it happens so fast, it just seems as if they were all running at
the same time. When running this code, if the output is not in order, dont worry. Its
simply because one or more of the processes were not able to get their output written to
screen before the next process starting writting its own.
Allegro Lessons
Allegro Basics
Here I will show you the very basics of programming with the Allegro Game Library.
First of all, you will need to download and install Allegro. This can be a bit of a pain on
Windows. Luckily, if you are using Dev-C++, you will be able to find a link to a file
which will install allegro for Dev-C++ with a few clicks of the mouse! You can find it at
the bottom of the download section in the Allegro website. If you are not using Dev-C++,
please refer to the documentation provided on the Allegro site for installation
instructions. Also be sure to install Allegro version 4.1.18, even though it is still
'Developmental', it is required for some of the examples on this site.

Now that that's out the way, lets get down to business! Open a new project in Dev-C++,
be sure to pick "Windows Application". Now click on "Project" in the menu bar then
"Project Options". Choose "Parameters" then click "Add Library or Object", set this to
"C:\Dev-Cpp\lib\liballeg.a". This will let the compiler know where to find the Allegro
functions. Here a simple Allegro program:

#include <allegro.h>

int main(){

allegro_init();
install_keyboard();
set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0);

readkey();

return 0;

}
END_OF_MAIN();

This program will change the screen resolution to 640x480 and then wait for the user to
press a key and then exit. Lets break down the code.

The first difference you will notice from the basic C++ lessons and these is that we no
longer need to include iostream, allegro includes all the functions we will need for now.
In order to startup Allegro we have to run the allegro_init() function, it does not require
any information on your part, just remember to have this line before you start using any
Allegro functions in your program!

install_keyboard() prepares Allegro to take user input from the keyboard, I will get more
in depth with the Allegro input functions in a later lesson. set_gfx_mode() changes the
screen resolution, it takes five parameters. The first should always be set to
"GFX_AUTODETECT". The next two will be the size of the viewable screen. The last
two are used for programs that require even more space, but that is a whole other lesson.
Allegro Input/Output
The last lesson's example was pretty useless, but important, lets add on to that now. Here
is some example code:
#include <allegro.h>

int x = 10;
int y = 10;

int main(){

allegro_init();
install_keyboard();
set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0);

while ( !key[KEY_ESC] ){

clear_keybuf();

acquire_screen();

textout_ex( screen, font, " ", x, y, makecol( 0, 0, 0),


makecol( 0, 0, 0) );

if (key[KEY_UP]) --y;
else if (key[KEY_DOWN]) ++y;
else if (key[KEY_RIGHT]) ++x;
else if (key[KEY_LEFT]) --x;

textout_ex( screen, font, "@", x, y, makecol( 255, 0, 0),


makecol( 0, 0, 0) );

release_screen();

rest(50);

return 0;

}
END_OF_MAIN();

This program will write a "@" to the screen and move it around when the user presses the
up, down, left, or right arrows. The first new line here, while( !key[KEY_ESC] ){. key[]
is an array of flags which are set to true when a specific key is pressed. In order to test for
a certain key just place one of the following codes within the brackets.
KEY_A - KEY_Z,
KEY_0 - KEY_9,
KEY_0_PAD - KEY_9_PAD,
KEY_F1 - KEY_F12,

KEY_ESC, KEY_TILDE, KEY_MINUS, KEY_EQUALS,


KEY_BACKSPACE, KEY_TAB, KEY_OPENBRACE, KEY_CLOSEBRACE,
KEY_ENTER, KEY_COLON, KEY_QUOTE, KEY_BACKSLASH,
KEY_BACKSLASH2, KEY_COMMA, KEY_STOP, KEY_SLASH,
KEY_SPACE,

KEY_INSERT, KEY_DEL, KEY_HOME, KEY_END, KEY_PGUP,


KEY_PGDN, KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN,

KEY_SLASH_PAD, KEY_ASTERISK, KEY_MINUS_PAD,


KEY_PLUS_PAD, KEY_DEL_PAD, KEY_ENTER_PAD,

KEY_PRTSCR, KEY_PAUSE,

KEY_ABNT_C1, KEY_YEN, KEY_KANA, KEY_CONVERT, KEY_NOCONVERT,


KEY_AT, KEY_CIRCUMFLEX, KEY_COLON2, KEY_KANJI,

KEY_LSHIFT, KEY_RSHIFT,
KEY_LCONTROL, KEY_RCONTROL,
KEY_ALT, KEY_ALTGR,
KEY_LWIN, KEY_RWIN, KEY_MENU,
KEY_SCRLOCK, KEY_NUMLOCK, KEY_CAPSLOCK

KEY_EQUALS_PAD, KEY_BACKQUOTE, KEY_SEMICOLON, KEY_COMMAND


clear_keybuf() clears the key buffer. The key buffer is a block of memory where your
program will keep a list of all the buttons pressed, you should run clear_keybuf() before
every input just incase if there is some unwanted data left in the buffer.

acquire_screen() is used to get Allegro ready to draw to the screen, always be sure to
include this before using any functions that draw to the screen and include
release_screen() once you are finished.

textout_ex() will draw text to the screen. It takes seven parameters. The first is where you
want it to write to, Allegro creates a variable called screen which represents the actuall
screen, just use this for now. The second parameter is the type of font to be used, if you
do not want to create your own font style, just use font which is the basic font included
with Allegro. The next parameter is the text to be drawn to the screen.

The next two are the x and y coordinates which point to where you want the text to be
drawn to. When positioning something, remember that coordinates 0, 0 would be the top
left of the screen. Adding to x will move the position to the right, while adding to y will
move it further down.

Next goes the color of the text. makecol() takes three parameters, the first the intensity of
red, the second of green, and then blue. makecol() will then return a value which
represents the mix of color made from the three parameters.

The final parameter is the background color.

rest() is used to pause the program for a set amount of milliseconds, just put how long
you want to wait in milliseconds between the parenthesis.
Drawing Primitives
Now lets look into drawing basic shapes. Here is some example code:
#include <allegro.h>

int main(){

allegro_init();
install_keyboard();
set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0);

acquire_screen();

clear_to_color( screen, makecol( 255, 255, 255));

putpixel( screen, 5, 5, makecol( 128, 200, 23));

circle( screen, 20, 20, 10, makecol( 255, 0, 0));


circlefill( screen, 50, 50, 25, makecol( 0,255, 0));

rect( screen, 70, 70, 90, 90, makecol( 0, 0, 255));


rectfill( screen, 100, 100, 120, 120, makecol( 12, 34, 200));

line( screen, 130, 130, 150, 150, makecol( 255, 0, 0));


line( screen, 130, 130, 170, 130, makecol( 255, 0, 0));
line( screen, 170, 130, 150, 150, makecol( 255, 0, 0));

floodfill( screen, 140, 135, makecol( 255, 255, 0));

triangle( screen, 200, 200, 200, 220, 220, 210, makecol( 213, 79,
40));

release_screen();

readkey();

return 0;

}
END_OF_MAIN();
This program will change the background color to white and draw several shapes on the
screen. Lets break down the code.

"clear_to_color( screen, makecol( 255, 255, 255));" is used to clear any bitmap specified
in the first parameter to the color in the second. We will get more into bitmaps in a later
lesson, just use screen for now.

All the functions used to draw here take the bitmap to draw to as the first parameter.
putpixel() takes four parameters, the second and third define the x and y coordinates. The
fourth the color of the pixel. A pixel is the smallest component in an image, what you see
on your monitor is a bunch of different color pixels, the size of the pixel depends on the
resolution you set with set_gfx_mode().
circle() and circlefill() both draw circles, the difference is that circlefill() will fill in the
circle with the color specified in the last parameter while circle() simply draws the
outline. The second and third parameters specify the position. The fourth defins the radius
of the circle.

rect() and rectfill() draw rectangles which start at the point defined by the second and
third parameters and end at the point defined by the fourth and fith parameters. The
difference between rect() and rectfill() is the same as the two circle functions.

line() draws a line of the color specified in the last parameter starting at the point defined
by the second and third parameter and ending at the point defined by the fourth and fith.

floodfill() works like the "Paint Bucket" tool found in most image editing software. It
will fill an area starting at the point defined by the second and third pixel with the color
specified in the fourth.

triangle() draws a colored in triangle, there is no trianglefill(). The three points of the
triangle are defined by second through sixth parameters. The color is defined by the last
parameter.

Drawing From Files


Now that you've learned how to draw the basic shapes, lets look into drawing files
created by image editing software to screen, afterall it would take quite a bit of time to
draw video game characters using the primitive shaps. Lets start with something simple,
Tic-Tac-Toe. Here is the X and O. Here is the code:
#include <allegro.h>

BITMAP *xSprite;
BITMAP *oSprite;

int main(){

allegro_init();
install_keyboard();
set_color_depth(16);
set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0);

xSprite = load_bitmap( "x.bmp", NULL);

oSprite = load_bitmap( "o.bmp", NULL);

acquire_screen();

line( screen, 200, 0, 200, 480, makecol( 255, 255, 255));


line( screen, 400, 0, 400, 480, makecol( 255, 255, 255));
line( screen, 0, 150, 680, 150, makecol( 255, 255, 255));
line( screen, 0, 300, 680, 300, makecol( 255, 255, 255));

draw_sprite( screen, xSprite, 0, 0);


draw_sprite( screen, oSprite, 200, 0);
draw_sprite( screen, xSprite, 400, 0);

draw_sprite( screen, oSprite, 0, 150);


draw_sprite( screen, xSprite, 200, 150);
draw_sprite( screen, oSprite, 400, 150);

draw_sprite( screen, oSprite, 0, 300);


draw_sprite( screen, xSprite, 200, 300);
draw_sprite( screen, oSprite, 400, 300);

release_screen();

readkey();

return 0;

}
END_OF_MAIN();
This program will draw a filled in Tic-Tac-Toe board to screen. Lets break it down.

The first new line would be "BITMAP *xSprite;", this line introduces a new data type,
BITMAP. The * before the name of the variable means its a "pointer" so instead of
containing a value like normal variables it holds a place in memory that points to some
value. Don't worry if your somewhat lost with pointers, they're not all that important just
yet. A bitmap is basically a list of numbers which represent different colors which
combined make an image.

set_color_depth() simply sets how many bits are to be used when making a pixel. In this
case I set it to 16. This is important when it comes to choosing the transparent color in
your drawings. At 16 bits and above the RGB (Red, Green, Blue) value would be 255, 0,
255 for the transparent pixel. 8 bit uses 0, 0, 0.

The next new line is "xSprite = load_bitmap( "x.bmp", NULL);". This line stores the
place in memory where the image is located to "xSprite". If you don't understand that,
don't worry, just remember to use what ever variable you load the memory address into
(in this case xSprite) whenever you want to use this image.

The last new function in this program is draw_sprite(). This function will draw an image (
.bmp, .pcx, .lba, and .tgm are the file types supported by Allegro) to a bitmap, in this case
the screen. The first parameter is where to draw the sprite, the second is a pointer to the
sprite that you wish to draw, and the third and fourth parameter define the coordinates to
where you want your sprite to be displayed.

Animation
If you just finished reading the lessons listed before this one, you should check Tic-Tac-
Toe in the "Example Games" section just to be sure you really understand whats going
on. Now lets look more into making an object move across the screen. Here is some
example code:
#include <allegro.h>
#include <cstdlib>

int x = 100;
int y = 100;

int tempX = 100;


int tempY = 100;

int dir = 1; //This will keep track of the circles direction


//1= up and left, 2 = down and left, 3 = up and right, 4 =
down and right

void moveCircle(){

tempX = x;
tempY = y;

if (dir == 1 && x != 20 && y != 20){

--x;
--y;

} else if (dir == 2 && x != 20 && y != 460){

--x;
++y;

} else if (dir == 3 && x != 620 && y != 20){

++x;
--y;

} else if (dir == 4 && x != 620 && y != 460){

++x;
++y;

} else {

dir = rand() % 4 + 1;

acquire_screen();
circlefill ( screen, tempX, tempY, 20, makecol( 0, 0, 0));
circlefill ( screen, x, y, 20, makecol( 128, 255, 0));
release_screen();

rest(10);
}

int main(){

allegro_init();
install_keyboard();
set_color_depth(16);
set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0);

while( !key[KEY_ESC]){

moveCircle();

return 0;

}
END_OF_MAIN();

Most of the code should look familliar aside from the new header file and the rand()
function.

cstdlib contains the rand() function which is used to generate random numbers. In this
case, it is used to change the direction of the circle.

Lets break down the code. main() get Allegro ready for action and then goes into a while
loop which doesnt stop until the player presses ESC.

moveCircle() will add or subtract to x and y depending on the direction the circle is going
in (which is stored in dir). If the circle has hit the top, bottom, or side of the screen, it will
change direction.

dir = rand() % 4 +1; gives dir a random value between 1 and 4. rand() % 4 would return a
random number between 0 and 3 ( 1 - 4) so we add 1 so we get a number between 1 and
4. If you wanted a number between 3 and 4 the code would be rand() % 2 + 3, since
rand() % 2 would return either 0 or 1 so we would have to add 3. There will be more on
the rand() function later. Afterwards, a black circle is drawn in order to cover up the old
one, and then a green circle is drawn in the new position.

Fairly simple isn't it? But there is one problem with the example, which is the flickering!
Needless to say a flickering video game would be quite annoying... Lets fix this.

Double Buffering
The answer to all the flickering? Double buffering. What this means is that instead of
drawing straight to the screen, we will draw to a temporary bitmap and then have one call
to a function which will draw it to the screen. Since this will reduce the amount of times
the screen is being accessed, the animation should run smoother. Here is how its done:
#include
#include
int x = 100;
int y = 100;

int tempX = 100;


int tempY = 100;

int dir = 1; //This will keep track of the circles direction


//1= up and left, 2 = down and left, 3 = up and right, 4 =
down and right

BITMAP *buffer; //This will be our temporary bitmap for double buffering

void moveCircle(){

tempX = x;
tempY = y;

if (dir == 1 && x != 20 && y != 20){

--x;
--y;

} else if (dir == 2 && x != 20 && y != 460){

--x;
++y;

} else if (dir == 3 && x != 620 && y != 20){

++x;
--y;

} else if (dir == 4 && x != 620 && y != 460){

++x;
++y;

} else {

dir = rand() % 4 + 1;

acquire_screen();
circlefill ( buffer, tempX, tempY, 20, makecol( 0, 0, 0));
circlefill ( buffer, x, y, 20, makecol( 128, 255, 0));
draw_sprite( screen, buffer, 0, 0);
release_screen();

rest(10);

int main(){

allegro_init();
install_keyboard();
set_color_depth(16);
set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0);

buffer = create_bitmap( 640, 480);

while( !key[KEY_ESC]){

moveCircle();

return 0;

}
END_OF_MAIN();
There you have it, the flickering is no more! Here we create a bitmap called buffer and
using create_bitmap() we make it the same size as the screen. After this, anywhere you
would have normally used screen, use buffer instead ( circlefill ( buffer, tempX, tempY,
20, makecol( 0, 0, 0)); ). Once everything has been drawn, copy the buffer onto the screen
and there you have it!

Backgrounds
Now that we've got basic animations out the way, lets look into adding a background to
our game. In the Pong example, every time the ball or a paddle moved, a black circle or
rectangle took the place of the objects last position so that the player would not see a
trace of it. What if we have a multicolored background though? Easy, using a technique
known as "dirty rectangles" we can easily replace the background with the right
color/image. For this we create two 2-dimensional arrays. One will be the background,
and the other will contain the objects that will be moving around. This way we can check
an objects last position and know what color/image to fill that portion of the screen with.
It might sound some what confusing, hopefully an example will help answer any
questions.

Here is an example for a tile based game using dirty rectangles. You will need the box
image.

#include <allegro.h>

BITMAP* box;
BITMAP* buffer;

//These will hold the player's position


//instead of using pixels, we will use the position within the 2d array
int x = 15;
int y = 11;

int tempX = 15;


int tempY = 11;
//This will hold the value of how many boxes are left outside of the
holes.
int boxes;

//This will be our background, 1 = clouds, 2 = brick, 3 = floor, 4 =


hole
int map[24][32] =
{{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,2,3,3,3,3,3,3,3,3,3,2,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,2,3,3,3,3,4,3,3,3,3,2,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,2,3,3,3,3,3,3,3,3,3,2,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,2,3,3,3,3,3,3,3,3,3,2,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,2,3,3,3,3,3,3,3,3,3,2,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,2,3,3,3,3,3,3,3,3,3,2,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,2,3,3,3,3,3,3,3,3,3,2,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,2,3,3,3,3,3,3,3,3,3,2,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,2,3,3,3,3,3,3,3,3,3,2,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
,1,1,1,1,1,1}};

//This will contain all the objects, 100 = player, 101 = box
int objMap[24][32] =
{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,101,0,100,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0}};

void setupGame(){

buffer = create_bitmap( 640, 480);


box = load_bitmap( "box.bmp", NULL);
boxes = 1;

for (int i = 0; i <= 24; i++){


for( int t = 0; t <= 32; t++){

if( map[i][t] == 1) rectfill( buffer, t * 20, i * 20, (t +


1) * 20, (i + 1) * 20, makecol( 128, 255, 255));
else if( map[i][t] == 2) rectfill( buffer, t * 20, i * 20,
(t + 1) * 20, (i + 1) * 20, makecol( 255, 128, 0));
else if( map[i][t] == 3) rectfill( buffer, t * 20, i * 20,
(t + 1) * 20, (i + 1) * 20, makecol( 255, 0, 0));
else if( map[i][t] == 4) rectfill( buffer, t * 20, i * 20,
(t + 1) * 20, (i + 1) * 20, makecol( 0, 0, 0));

for (int i = 0; i <= 24; i++){

for( int t = 0; t <= 32; t++){

if( objMap[i][t] == 100) circlefill( buffer, (t * 20) + 10,


(i * 20) + 10, 10, makecol( 255, 255, 0));
else if( objMap[i][t] == 101) draw_sprite( buffer, box, t *
20, i * 20);

draw_sprite( screen, buffer, 0, 0);

void movePlayer(){

tempX = x;
tempY = y;

if ( key[KEY_UP] && map[y - 1][x] == 3){

if( objMap[y - 1][x] != 101){


--y;
} else if( objMap[y - 1][x] == 101 && map[y - 2][x] == 3 ||
objMap[y - 1][x] == 101 && map[y - 2][x] == 4){

if (map[y - 2][x] == 4) --boxes;

objMap[y - 2][x] = 101;


draw_sprite( buffer, box, x * 20, (y - 2) *20);
--y;
}

} else if ( key[KEY_DOWN] && map[y + 1][x] == 3){

if( objMap[y + 1][x] != 101){


++y;
} else if( objMap[y + 1][x] == 101 && map[y + 2][x] == 3 ||
objMap[y + 1][x] == 101 && map[y + 2][x] == 4){
if (map[y + 2][x] == 4) --boxes;

objMap[y + 2][x] = 101;


draw_sprite( buffer, box, x * 20, (y + 2) *20);
++y;
}

} else if ( key[KEY_RIGHT] && map[y][x + 1] == 3){

if( objMap[y][x + 1] != 101){


++x;
} else if( objMap[y][x + 1] == 101 && map[y][x + 2] == 3 ||
objMap[y][x + 1] == 101 && map[y][x + 2] == 4){

if (map[y][x + 2] == 4) --boxes;

objMap[y][x + 2] = 101;
draw_sprite( buffer, box, (x + 2) * 20, y * 20);
++x;
}

} else if ( key[KEY_LEFT] && map[y][x - 1] == 3){

if( objMap[y][x - 1] != 101){


--x;
} else if( objMap[y][x - 1] == 101 && map[y][x - 2] == 3 ||
objMap[y][x - 1] == 101 && map[y][x - 2] == 4){

if (map[y][x - 2] == 4) --boxes;

objMap[y][x - 2] = 101;
draw_sprite( buffer, box, (x - 2) * 20, y * 20);
--x;
}

acquire_screen();

rectfill( buffer, tempX * 20, tempY * 20, (tempX + 1) * 20, (tempY


+ 1) * 20, makecol( 255, 0, 0));

circlefill( buffer, (x * 20) + 10, (y * 20) + 10, 10, makecol( 255,


255, 0));

draw_sprite( screen, buffer, 0, 0);


release_screen();

objMap[tempY][tempX] = 0;
objMap[y][x] = 101;

if ( !boxes){
textout_ex( screen, font, "You Win!!!", 320, 240, makecol(0, 0,
255), makecol(0, 0, 0));
}
rest(100);
}

int main(){

allegro_init();
install_keyboard();
set_color_depth(16);
set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0);

setupGame();

while( !key[KEY_ESC]){

movePlayer();

return 0;
}
END_OF_MAIN();
This is a simple version of sokoban, a game where the player tries to push all the boxes
on the stage into the holes provided. It used 20x20 pixel tiles. Lets take a closer look at
the code.

Here I am using two 2D arrays to keep track of what needs to be updated. We will look
into creating a map editor later on so that we won't have to type out so many numbers in
order to create a map. One thing you should notice about the map is that when checking a
specific tile you must use arrayName[y][x], the x and y are inverted (unless if you want
to declare the 2D array as arrayName[32][24], this would make editing a bit of a hassle).

main() has the usual setup. setupGame() draws the screen and sets how many boxes will
be in the current level, since this is intended to show dirt rectangles, I only included one.

movePlayer() controls the player, moves the box when it is pushed by the player, and
declares the player a winner if he succeeds.

When the player presses an arrow key, movePlayer() checks to see if there is anything in
tile the player want to move to. If there is nothing, it will check for a box, if there isnt
one, it will move the player. If there is a box, it will check the tile where the box will be
pushed to. If that tile is empty, or a hole, it will move the box and subtract it from the
total number of boxes left in the game.

Afterwards, it draws the player and box to screen, and covers up the location the player
used to be in (We do not need to bother with the tile the box was in since it will be
occupied by the player). After this it will update the players location on the object map
and declare you a winner if there are no more boxes left.

Allegro Mouse
Here we will look into how the mouse is used with Allegro. Here is some example code:
#include <allegro.h>

BITMAP* buffer;

int cursor_x = 20;


int cursor_y = 20;

void getMouseInfo(){

if(mouse_b & 1){

cursor_x = mouse_x;
cursor_y = mouse_y;

void updateScreen(){

circlefill ( buffer, cursor_x, cursor_y, 20, makecol( 0, 0, 255));


draw_sprite( screen, buffer, 0, 0);

int main(){

allegro_init();
install_mouse();
install_keyboard();
set_color_depth(16);
set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0);

buffer = create_bitmap( 640, 480);

show_mouse(buffer);

while( !key[KEY_ESC]){

getMouseInfo();
updateScreen();
}

return 0;

}
END_OF_MAIN();

This program will draw a blue circle at the current mouse position everytime the left
mouse button is pressed.
First of all, to get the mouse to appear, show_mouse(buffer) is used. As you might expect,
function displays the mouse cursor on the bitmap specified. In order to make the mouse
dissear once again, just do a show_mouse(NULL).

In order to check for the button states, Allegro defines a variable called mouse_b. It sets
different bits in the variable to 1, depending on what button was pressed. Here is how to
check for the different buttons:

Left button: mouse_b & 1


Right button: mouse_b & 2
Wheel: mouse_b & 3
Checking mouse position is much easier. Allegro stores them in mouse_x and mouse_y.
The current wheel position is stored in mouse_z. All of these are plain old normal ints
and can be treated like any other variable you've declared (no funny '&'s or anything like
that needed).

You may have noticed a black rectangle on some of the circles with the last example.
Mostly when you try to move the mouse fast. Wmz, one of the sites viewers, submited
the following code which shows one way of eliminating this problem:

#include <allegro.h>

BITMAP* buffer;
int cursor_x = 20;
int cursor_y = 20;
int getMouseInfo(){
if(mouse_b & 1){
cursor_x = mouse_x;
cursor_y = mouse_y;
return 1;
}
return 0;
}
void updateScreen(){

show_mouse(NULL);
circlefill ( buffer, cursor_x, cursor_y, 5, makecol( 0, 0, 255));
draw_sprite( screen, buffer, 0, 0);
}
int main(){

allegro_init();
install_mouse();
install_keyboard();
set_color_depth(16);
set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0);

buffer = create_bitmap( 640, 480);

show_mouse(screen);

while( !key[KEY_ESC])
{
int switcher=1;
while(getMouseInfo())
{
updateScreen();
if(getMouseInfo()==0) switcher=0;
}
if(switcher==0) show_mouse(screen);
}

return 0;
}
END_OF_MAIN();

Here Wmz used a variable called switcher to determine wether or not the mouse cursor
should be displayed. If something needs to be drawn to the screen, updateScreen() will
first deactivate the mouse so that it does not interrupt the process, once the update is
finished, the while loop will continue and redraw the mouse cursor directly to the screen.

Allegro Animation II
Ok lets look into how to make a character move across the screen while swaying his arms
and moving his legs. First you'll need to download the images for this tutorial located
here. As always the images are not of the highest quality, but they serve their purpose :).
Now on to the example code. The program is divided into 3 files, main.cpp, character.h,
and character.cpp:
//main.cpp

#include <allegro.h>
#include "Character.h"

using namespace std;

BITMAP* buffer;
Character myChar;

void Setup(){

buffer= create_bitmap(640, 480);


myChar.SetImagesLeft( "left1.bmp", "left2.bmp", "left3.bmp");
myChar.SetImagesRight( "right1.bmp", "right2.bmp", "right3.bmp");
myChar.SetImagesUp( "up1.bmp", "up2.bmp", "up3.bmp");
myChar.SetImagesDown( "down1.bmp", "down2.bmp", "down3.bmp");

myChar.Show( screen);

void movePlayer(){

if( key[KEY_LEFT]){
myChar.MoveOnX( LEFT, buffer, screen);
} else if( key[KEY_RIGHT]){
myChar.MoveOnX( RIGHT, buffer, screen);
} else if( key[KEY_UP]){
myChar.MoveOnY( UP, buffer, screen);
} else if( key[KEY_DOWN]){
myChar.MoveOnY( DOWN, buffer, screen);
}

int main(int argc, char *argv[])


{
allegro_init();
install_mouse();
install_keyboard();
set_color_depth(16);

set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0);

Setup();

while( !key[KEY_ESC]){
movePlayer();
}

return 0;
}
END_OF_MAIN();

//Character.h

#ifndef CHARACTER_H
#define CHARACTER_H

#define LEFT 1
#define RIGHT 2
#define UP 3
#define DOWN 4

#include <allegro.h>

class Character{

public:
Character();
~Character();

// The following 4 methods will be used to set the images for


the different
//stages of movement
void SetImagesLeft( char image1[], char image2[], char image3[]);
void SetImagesRight( char image1[], char image2[], char
image3[]);
void SetImagesUp( char image1[], char image2[], char image3[]);
void SetImagesDown( char image1[], char image2[], char image3[]);

//To keep the program from crashing, this function will be used
before
//calling any movement methods
bool CheckImages();

int GetX();
void SetX( int newValue);
void MoveOnX( int newValue, BITMAP* tempBitmap, BITMAP*
mainBitmap);

int GetY();
void SetY( int newValue);
void MoveOnY( int newValue, BITMAP* tempBitmap, BITMAP*
mainBitmap);

void EraseOldSprite( BITMAP* tempBitmap);


void DrawNewSprite( BITMAP* tempBitmap, BITMAP* spriteToDraw);

void Show(BITMAP* mainBitmap);

private:
bool leftDone;
bool rightDone;
bool upDone;
bool downDone;

int direction;

int x;
int y;

//This will contain all the images, [0][0-2] will be left


movements, [1][0-2] right
//[2][0-2] upwards, and [3][0-2] downwards
BITMAP *images[4][3];

};

#endif

//Character.cpp
#include "Character.h"

Character::Character(){

leftDone= false;
rightDone= false;
upDone= false;
downDone= false;

direction = DOWN;

int x= 0;
int y= 0;

}
Character::~Character(){

delete [] images;

void Character::SetImagesLeft( char image1[], char image2[], char


image3[]){

images[0][0]= load_bitmap(image1, NULL);


images[0][1]= load_bitmap(image2, NULL);
images[0][2]= load_bitmap(image3, NULL);

leftDone= true;

void Character::SetImagesRight(char image1[], char image2[], char


image3[]){

images[1][0]= load_bitmap(image1, NULL);


images[1][1]= load_bitmap(image2, NULL);
images[1][2]= load_bitmap(image3, NULL);

rightDone= true;

void Character::SetImagesUp(char image1[], char image2[], char


image3[]){

images[2][0]= load_bitmap(image1, NULL);


images[2][1]= load_bitmap(image2, NULL);
images[2][2]= load_bitmap(image3, NULL);

upDone= true;

void Character::SetImagesDown(char image1[], char image2[], char


image3[]){

images[3][0]= load_bitmap(image1, NULL);


images[3][1]= load_bitmap(image2, NULL);
images[3][2]= load_bitmap(image3, NULL);

downDone= true;

bool Character::CheckImages(){

if( rightDone && leftDone && upDone && downDone)


return true;

return false;
}

int Character::GetX(){

return x;

int Character::GetY(){

return y;

void Character::SetX( int newValue){


x = newValue;
}

void Character::SetY( int newValue){


y = newValue;
}

void Character::MoveOnX( int newDirection, BITMAP* tempBitmap, BITMAP*


mainBitmap){

direction = newDirection;

if( CheckImages()){
if( direction == LEFT){

for( int i=0; i<=3; i++){


EraseOldSprite( tempBitmap);
x -= 5;

if (i == 1 || i == 3)
DrawNewSprite( tempBitmap, images[0][0]);

if (i == 0)
DrawNewSprite( tempBitmap, images[0][1]);

if (i == 2)
DrawNewSprite( tempBitmap, images[0][2]);

draw_sprite( mainBitmap, tempBitmap, 0, 0);

rest(50);

}
} else {

for( int i=0; i<=3; i++){


EraseOldSprite( tempBitmap);
x += 5;

if (i == 1 || i == 3)
DrawNewSprite( tempBitmap, images[1][0]);

if (i == 0)
DrawNewSprite( tempBitmap, images[1][1]);

if (i == 2)
DrawNewSprite( tempBitmap, images[1][2]);

draw_sprite( mainBitmap, tempBitmap, 0, 0);

rest(50);

void Character::MoveOnY( int newDirection, BITMAP* tempBitmap, BITMAP*


mainBitmap){

direction = newDirection;

if( CheckImages()){

if( direction == UP){

for( int i=0; i<=3; i++){


EraseOldSprite( tempBitmap);
y -= 5;

if (i == 1 || i == 3)
DrawNewSprite( tempBitmap, images[2][0]);

if (i == 0)
DrawNewSprite( tempBitmap, images[2][1]);

if (i == 2)
DrawNewSprite( tempBitmap, images[2][2]);

draw_sprite( mainBitmap, tempBitmap, 0, 0);

rest(50);

}
} else {

for( int i=0; i<=3; i++){


EraseOldSprite( tempBitmap);
y += 5;

if (i == 1 || i == 3)
DrawNewSprite( tempBitmap, images[3][0]);

if (i == 0)
DrawNewSprite( tempBitmap, images[3][1]);

if (i == 2)
DrawNewSprite( tempBitmap, images[3][2]);

draw_sprite( mainBitmap, tempBitmap, 0, 0);

rest(50);

}
}
}

void Character::EraseOldSprite( BITMAP* tempBitmap){

rectfill( tempBitmap, GetX(), GetY(), GetX() + 20, GetY() + 20,


makecol ( 0, 0, 0));

void Character::DrawNewSprite( BITMAP* tempBitmap, BITMAP*


spriteToDraw){

draw_sprite( tempBitmap, spriteToDraw, GetX(), GetY());

void Character::Show(BITMAP* mainBitmap){

if( CheckImages())
draw_sprite( screen, images[3][0], 0, 0);

In this program most of the work is done by the Character class. Here the object is
drawing itself and replacing the background as it goes. When the user presses an arrow
key, either MoveOnX() or MoveOnY() will be called. Each of these methods will move
the character 20 pixels in the desired direction, but only 5 pixels at a time. This gives the
program time to change out the drawings so that each part of the animation (defined with
SetImagesLeft, Right, Up, and Down) can be seen. Each time the for loop in these
functions runs, it will have the old sprite drawn over by the background (in this case a
black rectangle is all that is needed) and then the next step in the animation will be drawn
5 pixels past the old one. If you decide to use a more complex background, simply
modify the DrawNewSprite() method so that I redraws 2 tiles from the background (the
one the character is currently on, and the one he is moving to). By now you should be
able to understand the rest, if not, feel free to drop by the forums and ask any questions
you may have!

Examples of games
Tic-Tac-Toe
Here is the source code to the game, you will also need the X and O images. This is a
very simple version of the game, nothing fancy, no menus, no nothing, just the actuall
game was coded in hopes of making it easier for beginners.
#include <allegro.h>

BITMAP *xSprite;
BITMAP *oSprite;

int board[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0}; //This will be used to keep


//track of the Xs and Os
int curSquare = 0; //This will keep track of the current square
//the selector is on

int turn = 1; //This will keep track of whose turn it is


//1 Will be for X and 2 for O

int x = 0; //X and Y position of selector


int y = 0;

int tempX = 0; //holds temporary values used to clear selector


int tempY = 0;

void setupBoard(){ //This function will draw in the grid

acquire_screen();

line( screen, 200, 0, 200, 480, makecol( 255, 255, 255));


line( screen, 400, 0, 400, 480, makecol( 255, 255, 255));
line( screen, 0, 150, 680, 150, makecol( 255, 255, 255));
line( screen, 0, 300, 680, 300, makecol( 255, 255, 255));

rect( screen, x+1, y+1, x + 199, y + 149, makecol( 255, 255, 0));

release_screen();

void updateBoard(){ //draws in selector

rect( screen, tempX+1, tempY+1, tempX + 199, tempY + 149, makecol(


0, 0, 0));
rect( screen, x+1, y+1, x + 199, y + 149, makecol( 255, 255, 0));
rest(100);
}

void announceWinner(){ //Announces the winner

if( turn == 1){


textout_ex( screen, font, "X Wins!!!!", 300, 240,
makecol( 255, 0, 0), makecol(0, 0, 0));
} else {
textout_ex( screen, font, "O Wins!!!!", 300, 240,
makecol( 255, 0, 0), makecol(0, 0, 0));
}

void checkWin(){ //checks for a winner

if( board[0] == turn && board[1] == turn && board[2] == turn){


announceWinner();
} else if( board[0] == turn && board[3] == turn && board[6] ==
turn){
announceWinner();
} else if( board[0] == turn && board[4] == turn && board[8] ==
turn){
announceWinner();
} else if( board[1] == turn && board[4] == turn && board[7] ==
turn){
announceWinner();
} else if( board[2] == turn && board[4] == turn && board[6] ==
turn){
announceWinner();
} else if( board[2] == turn && board[5] == turn && board[8] ==
turn){
announceWinner();
} else if( board[3] == turn && board[4] == turn && board[5] ==
turn){
announceWinner();
} else if( board[6] == turn && board[7] == turn && board[8] ==
turn){
announceWinner();
}

void drawXO(){ //draws in the X and O

acquire_screen();

if(turn == 1){
draw_sprite( screen, xSprite, x, y);
board[curSquare] = 1;
checkWin();
++turn;
} else if( turn == 2){
draw_sprite( screen, oSprite, x, y);
board[curSquare] = 2;
checkWin();
--turn;
}

release_screen();

rest(100);

}
void moveBox(){ //takes input

clear_keybuf();
tempX = x;
tempY = y;

if( key[KEY_UP] && y != 0){

y -= 150;
curSquare -=3;
updateBoard();

} else if( key[KEY_DOWN] && y != 300){

y += 150;
curSquare +=3;
updateBoard();

} else if( key[KEY_RIGHT] && x != 400){

x += 200;
++curSquare;
updateBoard();

} else if( key[KEY_LEFT] && x != 0){

x -= 200;
--curSquare;
updateBoard();

} else if( key[KEY_ENTER] && board[curSquare] == 0){

drawXO();

int main(){

allegro_init();
install_keyboard();
set_color_depth(16);
set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0);

xSprite = load_bitmap( "x.bmp", NULL);

oSprite = load_bitmap( "o.bmp", NULL);

setupBoard();

while( !key[KEY_ESC]){
moveBox();

}
destroy_bitmap( xSprite);
destroy_bitmap( oSprite);

return 0;

}
END_OF_MAIN();

Lets break the code down function by function.

main() runs the normal functions used to setup Allegro and the screen. It includes a call to
setupBoard() which will simply draw lines to for the grid and draw in a box so the player
knows what square is currently selected.

while ( !key[KEY_ESC]) is the main loop, this keeps the game running until ESC is
pressed.

moveBox() takes input from the player and calls different functions depending on the key
pressed. If an arrow key is pressed the x or y variable will be adjusted to get the selector
to the next square and curSquare is updated so that we can easily find which part of
board[] corresponds to the square the player is currently in. updateBoard() is called to
simply clear out the old selector and draw in the new one.

If enter is pressed and the current square is not occupied, drawXO() is called. This
function will check whose turn it is and draw in the corresponding shape ( X or O ). It
then updates board[] so that the current square will be marked as being occupied by either
a X or an O. Then it calls checkWin() which checks to see if someone has won, and then
changes the turn variable so that the next player can go ( 1 = X's turn, 2 = O's turn).

checkWin() checks for a winner. Since drawXO() changes board[curSquare] so that it


equals the current users turn, board will have 1's to represent X's and 2's to represent O's.
checkWin() will check to see if there are three 1's or 2's in a row, depending on whose
turn it is and call announceWinner() if there are.

announceWinner() simply checks whose turn it is (who should be the winner since the
turn has not been modified by drawXO() yet) and prints out who the winner is to screen.

Pong
Pong requires a little bit more skill to code than the last example, Tic-Tac-Toe. Here we
have three objects moving about, we need to know when the ball hits a player's paddle or
someone scores, plus we need to calculate a random number for the direction of the ball.
Here is the code:
#include <allegro.h>
#include <cstdlib>
#include <time.h>

int ball_x = 320;


int ball_y = 240;

int ball_tempX = 320;


int ball_tempY = 240;

int p1_x = 20;


int p1_y = 210;

int p1_tempX = 20;


int p1_tempY = 210;

int p2_x = 620;


int p2_y = 210;

int p2_tempX = 620;


int p2_tempY = 210;

time_t secs; //The seconds on the system clock will be stored here
//this will be used as the seed for srand()

int dir; //This will keep track of the circles direction


//1= up and left, 2 = down and left, 3 = up and right, 4 =
down and right

BITMAP *buffer; //This will be our temporary bitmap for double buffering

void moveBall(){

ball_tempX = ball_x;
ball_tempY = ball_y;

if (dir == 1 && ball_x > 5 && ball_y > 5){

if( ball_x == p1_x + 15 && ball_y >= p1_y && ball_y <= p1_y +
60){
dir = rand()% 2 + 3;
}else{
--ball_x;
--ball_y;
}

} else if (dir == 2 && ball_x > 5 && ball_y < 475){

if( ball_x == p1_x + 15 && ball_y >= p1_y && ball_y <= p1_y +
60){
dir = rand()% 2 + 3;
}else{
--ball_x;
++ball_y;
}

} else if (dir == 3 && ball_x < 635 && ball_y > 5){
if( ball_x + 5 == p2_x && ball_y >= p2_y && ball_y <= p2_y +
60){
dir = rand()% 2 + 1;
}else{
++ball_x;
--ball_y;
}

} else if (dir == 4 && ball_x < 635 && ball_y < 475){

if( ball_x + 5 == p2_x && ball_y >= p2_y && ball_y <= p2_y +
60){
dir = rand()% 2 + 1;
}else{
++ball_x;
++ball_y;
}

} else {

if (dir == 1 || dir == 3) ++dir;


else if (dir == 2 || dir == 4) --dir;

acquire_screen();
circlefill ( buffer, ball_tempX, ball_tempY, 5, makecol( 0, 0, 0));
circlefill ( buffer, ball_x, ball_y, 5, makecol( 128, 255, 0));
draw_sprite( screen, buffer, 0, 0);
release_screen();

rest(5);

void p1Move(){

p1_tempY = p1_y;

if( key[KEY_W] && p1_y > 0){

--p1_y;

} else if( key[KEY_S] && p1_y < 420){

++p1_y;

acquire_screen();
rectfill( buffer, p1_tempX, p1_tempY, p1_tempX + 10, p1_tempY + 60,
makecol ( 0, 0, 0));
rectfill( buffer, p1_x, p1_y, p1_x + 10, p1_y + 60, makecol ( 0, 0,
255));
release_screen();

}
void p2Move(){

p2_tempY = p2_y;

if( key[KEY_UP] && p2_y > 0){

--p2_y;

} else if( key[KEY_DOWN] && p2_y < 420){

++p2_y;

acquire_screen();
rectfill( buffer, p2_tempX, p2_tempY, p2_tempX + 10, p2_tempY + 60,
makecol ( 0, 0, 0));
rectfill( buffer, p2_x, p2_y, p2_x + 10, p2_y + 60, makecol ( 0, 0,
255));
release_screen();

void startNew(){

clear_keybuf();
readkey();
clear_to_color( buffer, makecol( 0, 0, 0));
ball_x = 320;
ball_y = 240;

p1_x = 20;
p1_y = 210;

p2_x = 620;
p2_y = 210;

void checkWin(){

if ( ball_x < p1_x){


textout_ex( screen, font, "Player 2 Wins!", 320, 240, makecol(
255, 0, 0), makecol( 0, 0, 0));
startNew();
} else if ( ball_x > p2_x){
textout_ex( screen, font, "Player 1 Wins!", 320, 240, makecol(
255, 0, 0), makecol( 0, 0, 0));
startNew();
}

void setupGame(){

acquire_screen();
rectfill( buffer, p1_x, p1_y, p1_x + 10, p1_y + 60, makecol ( 0, 0,
255));
rectfill( buffer, p2_x, p2_y, p2_x + 10, p2_y + 60, makecol ( 0, 0,
255));
circlefill ( buffer, ball_x, ball_y, 5, makecol( 128, 255, 0));
draw_sprite( screen, buffer, 0, 0);
release_screen();

time(&secs);
srand( (unsigned int)secs);
dir = rand() % 4 + 1;

int main(){

allegro_init();
install_keyboard();
set_color_depth(16);
set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0);

buffer = create_bitmap( 640, 480);

setupGame();

while( !key[KEY_ESC]){

p1Move();
p2Move();
moveBall();
checkWin();

return 0;

}
END_OF_MAIN();
Lets break this down. There is a new header file not covered in the lessons so far, time.h.
This contains the functions used to get the current time from the system clock, this will
be used to calculate the random numbers.

main() runs through the usuall setup for the game and then calls setupGame(). This
function draws the screen and calls time() to get the current time. srand() is a function
that changes the "seed" that rand() will use to make random numbers, the seed is the
initial value rand() will begin with. In this case the seed is set to the current amount of
seconds the system clock is displaying, this way there will always be a new seed
everytime the program runs so there will never be a repetetive pattern.

dir = rand() % 4 + 1; will give dir a value between 1 and 4. rand() % x will return a
random number between 0 and x-1, in this case 0 to 3. Since we want a number from 1 to
4, we simply add 1 to the result.
Once the setup is complete, the main loop begins. p1Move() will move the paddle on the
left side of the screen when W and S are pressed, and p2Move() will do the same for the
other paddle when up and down are pressed. moveBall() checks to see if it is about to go
off the screen, or hit a paddle and change its course accordingly.

checkWin() will see if the ball has passed a paddle and declare a winner if it has.
startNew() will simply clear the screen and reset the values for the ball's and players'
positions.

You might also like