0% found this document useful (0 votes)
146 views

PDF Appendix e Game Programming With The Allegro Library DL

Uploaded by

Felipe George
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
146 views

PDF Appendix e Game Programming With The Allegro Library DL

Uploaded by

Felipe George
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 57

 

Game Programming with the


Allegro C Library E
One picture is worth ten
thousand words.
—Chinese proverb

Treat nature in terms of the 


cylin
cylinde
derr, the sph
spher
ere,
e, the con
cone,
e, all 
all 
in perspecti
perspective.
ve.
—Paul Cezanne

Nothing ever becomes real till it 


is experience
experienced—even
d—even a proveproverb 
rb 
is no prov
proverb
erb to you til
tilll yo
your
ur llife 
ife 
has illustrated it.
—John Keats

Objectives
In this appendix, you’ll learn:
■  How to install the Allegro
game programming
programming library to
work with your C programs.
■  To create games using
Allegro.
■  To import and display
graphics.
■  To use “double buffering” to
create smooth animation
animations.
s.
■  To import and play sounds.
■  To recognize and process
keyboard input.
■  To create the simple game
Pong.
■  To use timers to regulate the
speed of a game.
■  To use datafiles to shorten
the amount of code in a
program.

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

II   Append
Appendix
ix E Game Progra
Programming
mming with the Allegro C Librar
Library
y

E.1   Introduction E.7   Keyboard Input


E.2   Installing Allegro E.8  Fonts and Displaying Text
E.3  A Simple Allegro Program E.9   Implementing the Game of Pong
E.4  Simple Graphics: Importing Bitmaps E.10  Timers in Allegro
and Blitting E.11   The Grabber and Allegro Datafiles
E.5   Animation with Double Buffering E.12   Other Allegro Capabilities
E.6  Importing and Playing Sounds E.13  Allegro Resource Center 

Summary | Terminology | Self-Review Exercises | Answers to Self-Review Exercises | Exercises

E.1 Int
Introd
roduct
uction
ion
 We now present game programming and graphics with the Allegro C library. Created in
1995 by Climax game programmer Shawn Hargreaves,  Allegro
 Allegro is
 is now an open source
project maintained by the game developer community at  www.allegro.cc.
In this appendix, we show how to use the Allegro C library to create the simple game
of Pong.
 We Weadditional
explain demonstrate how such
features to display graphics
as sound, and smoothly
keyboard animate
input, text outputmoving objects.
and timers that
are useful in creating games. The appendix includes
includes web links to over 1,000 open source
 Allegro games and tutorials on advanced Allegro techniques.

E.2 Insta
Installing
lling Allegr
Allegro
o
 Allegro was created to be a relatively simple programming library, but its installation can
be tricky. Here we cover installation using Visual C++ 2008 Express Edition on Windows
and GCC 4.3 on Linux. The full source code download of Allegro contains instructions
for compiling from source on a wide variety of platforms in the  docs/build directory.
Installing Allegro on Windows 
To begin, you need the Allegro library itself, which is available at   www.allegro.cc/files
www.allegro.cc/files.
Download the pre-compiled Allegro 4.2.2 for Microsoft Visual C++ 9.0 and the zip file
containing the tools and examples. Extract these files to a convenient location, such as
C:\Allegro.
In Visual Studio 2008, go to  Tools > Options > Projects and Solutions > VC++ Direc-
tories, and select  Include files from the  Show Directories for: combobox. Select a blank line
and browse for the   include   folder included with the Allegro download. Next, select
Library
Libr files fro
ary files from
m the
the co
comb
mbobobox
ox an
and
d br
brow
owse
se fo
forr the
the lib folder. Finally, copy all of the  .dll
file
filess from
from th thee   bin   fold
folder
er in
incl
clud
uded
ed with
with the Alle
Allegr
groo do
down
wnlo
load
ad into
into th
thee   C:\Win-
dows\System32 folder.
Once the installation is complete, you must tell Visual Studio where to find the
 Allegro library when you create a new p project.
roject. To do this, create a new   Win32 Project. In

the  Empty project checkbox. ,Once


the  Win32 Applica
Applicatio
tion
n Wizard select  Windo
Wizard  Windows
the application as the application type, and select
ws application
project has been created, go to  Project > Properties,
then   Configuration Properties > Linker > Input. Select  Additional Dependencies   and add
“alleg.lib”. You must perform this step for every Allegro project you create. This

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.3 A Simpl
Simplee Alleg
Allegro
ro Prog
Program
ram   III

appendix’s
appendi x’s exa
exampl
mples
es fol
folder
der inc
includ
ludes
es an empt
emptyy pro
projec
jectt and sol
soluti
ution
on wit
with
h the Alleg
Allegro
ro lib
libra
rary 
ry 
already added as a dependency that you can use for running the programs.
Installing Allegro on Linux 
Most Linux distributions have precompiled packages for Allegro, though the exact name
of the package differs. On Debian and Debian-based distributions such as Ubuntu, the
package
pack age is liballegro4.2-dev; on FedoFedorra it is ca
call
lled
ed allegro; an andd on op
openenSSUS
USEE it is spli
splitt
into the  allegro-devel   and  allegro-tools  packages. Install the proper Allegro pack-
age(s) and the   make  package using your distribution’s package manager (e.g., Synaptic,
PackageKit or YaST).
The make pro
progr
gram
am ma
makekess com
compi
pila
lati
tion
on ea
easi
sier
er by letti
letting
ng you
you stor
storee in
inst
stru
ruct
ctio
ions
ns for
for com
com--
piling programs in a file called  Makefile instead of typing them out on the command line
each time you build the program. We have supplied a  Makefile Makefile with the examples for this
append
app endix—
ix—sim
simply
ply run
runnin
ningg “make” from
from ininsi
side
de the
the didire
rect
ctor
oryy wi
will
ll use
use th
thee Makefile to com-
com-
pile all of the examples in the appendix. If you are creating your own project, you can
adapt our   Makefile  or use the  allegro-config  program, which displays the compiler
options needed to compile and link Allegro programs.

E.3 A aSimple
Consider Simp
simplele Allegro
Allegr
Allegro o Progra
Pro
program thatgramm a message (Fig. E.1). In addition to the
displays
preprocessor directive to include the  allegro.h  header at line 3 (this directive must be
present for an Allegro program to operate correctly), you will notice several functions in
this program that we have not previously used. The function call  allegro_init  (line 7)
initializes the Allegro library. It is required for an Allegro program to run, and must be
called before any other Allegro functions.

1   /* Fig. E.1:
E.1: figE_01
figE_01.c
.c
2   A sim
simple
ple All
Allegr
egro
o pro
progra
gram.
m. */
3   #include   <allegro.h>
4
5   int   main(   void   )
6   {
7    allegro_init();   /* ini initia
tializ
lize
e All
Allegr
egro
o */
8   allegro_message(   "Welcome
"Welcome to Alleg
Allegro!"
ro!"   );   /* di
disp
spla
lay
y a me
mess
ssag
age
e */
9   return   0;
10   }   /* en
end
d fu
funcncti
tionon ma
main
in */
11   END_OF_MAIN()   /* All Allegr
egro-s
o-spec
pecifi
ificc mac
macro
ro */

Fig. E.1   |  A simple Allegro program.

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

IV    Appendix
Appendix E Game Progra
Programming
mming with the Allegr
Allegro
o C Libra
Library
ry

The call to  allegro_message (line 8) displays a message to the user in the form of an


alert box. Since alert boxes interrupt running programs, you will probably not use this
function much—it is preferable to use Allegro’s text display functions to display messages
on the scree
screen
n witho
without
ut stopping the progra
program.
m. The  allegro_message  function is typically 
used to notify the user if something is preventing Allegro from working correctly.
The use of the  END_OF_MAIN  macro is the last of the new elements in this program.
 Windows, some Unix systems, and Mac OS X cannot run Allegro programs without this
macro, as the executable that an Allegro program creates during compilation will not be
able start correctly on those systems. The  END_OF_MAIN  macro checks the currently run-
ning operating system during compilation, and applies an appropriate fix to this problem
if one is required. On systems other than the ones listed previously,  END_OF_MAIN  will do
nothing, and your program will compile and run perfectly without it. However, you
should
shou ld st
still
ill always
always aadd
dd the ma
macro
cro af
after
ter the ri
right
ght bra
brace
ce of you
yourr main to ensu
ensure
re th
that
at your
your pro-
pro-
gram is compatible with systems that require it.
So, to get any Allegro program to run, you need to have three lines of code—the pre-
processor directive to include  allegro.h, the call to  allegro_init  and (if your system
requires it) the call to the  END_OF_MAIN macro following the right brace of your program’s
main function. Now we discuss Allegro’s main capability—displaying graphics.

E.4 Simple Graphics


Graphics:: Importing
Importing Bitmaps and
and Blitting 
 Allegro can draw lines and simple shapes on its own, but the majority of the graphics it
can display come from extern
external
al sources. The  allegro.h  header defines several types that
can be used to hold image data from external files—the  BITMAP* pointer type is
type  is the most
ba
basi
sicc of th
thes
ese.
e. A BITMAP* po
poin
ints
ts to a struct in memo
memory
ry wh
wher
eree im
imag
agee da
data
ta is stor
stored
ed.. Alle
Allegr
groo
has many functions that can be used to manipulate bitmaps. The most important of these
are shown in Fig. E.2.

Function prototype Description

BITMAP *creat
*create_bitmap
e_bitmap(
(int   width, Creates and returns a pointer to a blank bitmap
int hei
height)
ght)  with specified width and height (in pixels).
BITMAP *load_b
*load_bitmap(c
itmap(const
onst Loads and returns a pointer to a bitmap from
char   *filenam
*filename,
e, RGB *pa
*pal)
l) the location specified in  filename with palette
pal.
void   clear_bitmap(BITMAP
clear_bitmap(BITMAP *bmp)   Clears
Clears a bitmap of its image data and makes it
blank.
void   clear_to_color(BITMA
clear_to_color(BITMAP
P *bmp, Clears a bitmap of its image data and makes the
int   color) entire bitmap the color specified.
void   destroy_bitmap(BITMA
destroy_bitmap(BITMAP
P *bmp)   Destroys a bitmap and frees up the memory 
previously allocated to it. Use this function

 when youleaks.
memory are done with a bitmap to prevent

Fig. E.2   |  Important BITMAP functions.

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.4 Simpl
Simplee Graphics:
Graphics: Importi
Importing
ng Bitmaps
Bitmaps and Blitting
Blitting   V 

Now let’s use Allegro’s functions to load a bitmap and display it on the screen until a 
key is pressed. First we need a bitmap to load from, so copy the bitmap  picture.bmp
included with this appendix’s examples and save it in the same folder as your Allegro
project. The code in Fig. E.3 displays the bitmap until a key is pressed.

Common Programming Error E.1


Telling Allegro toerror,
cause a runtime load unless
a file that
you is notfically
in thetell
specifically
speci samethefolder as the
program theprogram
folder inbeing
whichrun
thewill 
file 
is located by typing the full path name.

1   /* Fig. E.3:
E.3: figE_03
figE_03.c
.c
2   Di
Disp
spla
layiying
ng a bit
bitma
map
p on the
the scr
scree
een.
n. */
*/
3   #include   <allegro.h>
4
5   int   main(   void   )
6   {
7    BITMAP
BITMAP *bmp;   /* popoin
inte
ter
r to th
the
e bi
bitm
tmap
ap */
8
9   allegro_init();   /* ini
initia
tializ
lize e All
Allegr
egro
o */
10 install_keyboard();   /* all allowow All
Allegr
egroo to rec
receiv
eive
e key
keyboa
board
rd inp
input
ut */
11 set_color_depth(   16   );   /* seset t th
the
e co
colo
lorr de
dept
pth
h to 1616-b
-bit
it*/
*/
12 set_gfx_mode( GFX_AUTODETECT,   640,   480,   0,   0   );   /* sesett gr
grap
aphi
hics
cs mo
mode
de */
13 bmp = load_b
load_bitm ap(   "picture.bmp",   NULL   );   /* lo
itmap( load
ad ththe
e bi
bitm
tmap
ap fi
file
le */
14 blit(
blit( bmp,
bmp, screen ,   0,   0,   0,   0, bm
screen, bmp-
p->w
>w,
, bmp-
bmp->h
>h );   /* dr
draw
aw th
the
e bi
bitm
tmap
ap */
15 readkey();   /* wa
wait
it fofor
r a ke keyp
ypreress
ss */
16 destroy_bi
destr oy_bitmap(
tmap( bmp );   /* fr freeee th
thee me
memo
mory
ry al
allo
loca
cate
ted d to bm
bmp
p */
17    return   0;
18   }   /* en
end
d fu
func
ncti
tion
on ma
main
in */
19   END_OF_MAIN()   /* All
Allegr
egro-s
o-spec
pecifi
ific c mac
macro
ro */

Fig. E.3   |   Displa


Displaying
ying a bitmap on the screen.
screen.

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

 VI   Appen
Appendix
dix E Game Progra
Programming
mming with the Allegr
Allegro
o C Libra
Library
ry

First, this program initializes the Allegro library and adds the ability to read keyboard
input. Then, it sets the graphics mode of the program. Finally, it loads  picture.bmp, dis-
plays it at the top-left corner of the screen, then waits for a key press. When a key is
pressed, the program frees the memory that was allocated to the bitmap, then exits.
Ther
Th eree are
are ma
many
ny ne
new
w Alle
Allegr
groo func
functi
tion
onss in this
this prog
progra
ram.
m. The
The call
call to install_keyboard
at line 10 “inst
“installs”
alls” the keyboard so that Alleg
Allegroro can recog
recognize
nize and use it. It doesn’
doesn’tt have
anything to do with displaying our bitmap, but it needs to be called so that Allegro will
know how to “wait” for a key press after the bitmap is displayed.
Line 11 calls our first graphics-related function,  set_color_depth, which sets the
color depth of the screen to n
to n-bit,
-bit, where n
where n is
 is the  int  passed to the function. A color depth
of   n-bits n
n-bits means that there are 2 possible colors that can be displayed. A lower color depth
 will make a program require less memory, but its appearance may not be as good as a 
higher one. While we set the color depth to 16-bit in our program, you can use a different
color depth if you wish, but the only values that  set_color_depth  accepts are 8, 15, 16,
24, and 32. It is advised, though, that you avoid using an 8-bit depth until you are more
experienced with Allegro. If the color depth is set to 8-bit, loading a bitmap also requires
th
thatat yo
you
u lo
load
ad th
thee bi
bitm
tmap
ap’s
’s pa
pale
lett
tte—
e—in
in othe
otherr wo
word
rds,s, th
thee set
set of colo
colors
rs th
that
at th
thee bi
bitm
tmap
ap uses
uses—

 which is a process that is beyond our scope. At the least, a 16-bit color depth is recom-

mended. A 12
In line 15-bit depth
we call is alsographics-related
another acceptable, but function,
not all platforms support. This
 set_gfx_mode it. call sets the
graphics mode of the program. This is an important function; let’s examine its prototype.

int   set_gfx_mode(int   card,   int   width,   int   height,   int   v_w,   int   v_h);

If the function is successful, it returns 0; otherwise, it returns a non-zero value. In general,


most Allegro functions that can fail follow the same paradigm. If you wish, you can insert
if stat
statem
emen
ents
ts in
into
to your
your prog
progra
ramm to ch
chec
eckk if your
your fu
func
ncti
tion
onss wor
workk cor
corre
rect
ctly
ly and
and te
tell
ll the pro-
pro-
gram how to proceed if one fails, but to save space, our sample programs will assume that
all our functions work as they should.
The first parameter of the  set_gfx_mode  function is  int card. In earlier versions of 
 Allegro, this parameter was used ttoo tell th
thee computer which video card driver to use, but
determining which
difficult process. In driver
newer would work
versions correctly
of the library,with a givenofsystem
a number and“magic
so-called program was a 
drivers”
 were added that detect the computer’s drivers automatically—GFX_AUTODETECT,
GFX_AUTODETECT_FULLSCREEN,   GFX_AUTODETECT_WINDOWED
GFX_AUTODETECT_WINDOWED, and  GFX_SAFE (all of these are
symbolic constants defined in  allegro.h). In addition to specifying the driver to use,
passing the parameter one of the preceding values also tells Allegro whether it should run
the program in a window, or whether the program should use the entire screen. Passing 
GFX_AUTODETECT_FULLSCREEN  or  GFX_AUTODETECT_WINDOWED  tells the program to run in
fullscreen mode (the program takes up the entire screen) or windowed mode (the program
runs in a standard window), respectively. Passing  GFX_AUTODETECT
 GFX_AUTODETECT makes the program try 
fullsc
fullscree
reen
n mod
modee first,
first, the
then
n try win
window
doweded mod
modee if ful
fullsc
lscree
reenn mod
modee cau
causes
ses an err
error.
or.
GFX_SAFE  mode is generally not used; though it acts the same way as  GFX_AUTODETECT,
there is one addition. If both fullscreen and windowed mode fail,  GFX_SAFE  mode forces
the computer to use settings that it “knows” will work. However these “safe” modes usu-
ally have extremely low resolution and color depth, so they are generally avoided. There is
also a fifth symbolic constant,   GFX_TEXT, but this setting allows only text as the name

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.4 Simpl
Simplee Graphics:
Graphics: Importin
Importing
g Bitmaps
Bitmaps and Blitting
Blitting   VII

implies and passi


implies passing
ng it to set_gfx_mode will essentially “turn off” any window or fullscreen
graphics that are already running.

Software Engineering Observation E.1


 Avoid using the  GFX_SAFE 
  GFX_SAFE  “magic
  “magic driver” if possible. The “safe” graphics modes generally 
have a negative impact on your program’s appearance.

The next two parameter


parameters,s,  width  and  height, determine the number of pixels in the
 width and height of the screen (or the window, if you’re using windowed mode). The last
two parameters (v_w and  v_h ) define the minimum pixel width and height, respectively, of 
 what is called the “ virtual screen
screen.”
.” The “virtual screen” was used in earlier versions of 
 Allegro to help create games where action can occur out of the view of the visible screen,
but it no longer has any real use in Allegro’s current version as most systems today do not
support it. Thus, the  v_w  and  v_h  parameters should simply be passed the value 0.
Now that we know how to set the graphics mode, we consider the function at line 13,
load_bitmap. This function, introduced in Fig. E.2, loads the picture that we saved as
picture.bmp and has the pointer  bmp  point to it. We did not pass the function a palette—
this is not necessary. Recall that passing a bitmap’s palette is required only when the color
depth is set to 8-bit
8-bit.. However, it is important that you make sure you set the color depth
and graphics mode in your program before you attempt to load a bitmap file. Otherwise,
 Allegro will have no information on how to store th thee bitmap in memory (it will no
nott know 
how many bits in memory to use for each pixel, for example), and will instead try to
“guess” how to do so. This can lead to various errors in your program.

Common Programming Error E.2


Loading a bitmap before setting the color depth and graphics mode of a program will likely 
result in Allegro storing the bitmap incorrectly.

If  load_bitmap
 load_bitmap  fails—if, for example, you tell it to load a bitmap that is not there—
then it does not actua
actually
lly cause an error on that line. Instea
Instead,
d, telling  load_bitmap
 load_bitmap  to load
a nonexistent file simply makes the function return the value  NULL. Obviously, this can
cause problems later in the program, but compilers do not recognize a failed call to
load_bitmap   as an error. In general, any Allegro function that loads an external file
behaves in the same way.
Line 14 contains a call to what is probably the most important function in this pro-
gram,  blit. The  blit function (blit stands for BLock Transfer—the “i” is there only to
make it pronounceable) is an Allegro function that takes a block of one bitmap (the block 
can be the entire picture, if you wish) and draws it onto another. Consider this function’s
prototype:
void   blit(BITM
blit(BITMAP
AP *source,
*source, BITMAP *dest,   int   source_x,   int   source_y,
BITMAP *dest,
int   dest_x,   int   dest_y,   int   width,   int   height);

Because blit draws one bitmap onto another, we must specify those bitmaps for the func-
ti
tion
on to wo
bitmaps,work
rk.. Th
Thee fi
firs
respectively,rstt so
two
twin
o pa
para
rame
ourmete
ters
rs (source
program we areand dest) de
taking defi
fine
a blockneof 
th
thee sour
 bmp
 bmpso and
urce
ce drawing
and
and de
dest
stin
inat
it atio
ion
onton
the  screen. The symbolic constant   screen  (defined in  allegro.h) refers to the screen of 
the computer. Blitting onto the screen is the only way to display graphics.

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

 VIII   Append
Appendix
ix E Game Progra
Programming
mming with the Allegr
Allegro
o C Libra
Library
ry

Since blitting takes a block from a bitmap, we also have to specify the position of this
block in the source bitmap. The parameters  source_x  and  source_y  specify the coordi-
nates of the top-left corner of the block we want to draw onto the destination bitmap.
 Allegro bitmap coordinates do not work the same way as tthey hey do on most graphs in your
algebra
algebra and geometry classes: A larg
larger
er x 
 x -value
-value means further to the right, but a larger y 
larger  y -
value means further down, not up. This means that the top-left point of any bitmap image
is at the coordinates (0, 0). Figure E.4 illustrates this coordinate system using the output
of the program we wrote in Fig. E.3.

Fig. E.4   |  Allegro’s coordinate system.

To draw onto a bitmap, we must also tell the function where we want the drawing to
take place. The parameters  dest_x  and  dest_y  determine the coordinates of the top-left
point of this location. Again, the coordinates (0, 0) represent the top left of a bitmap.
Finally, though we have specified the top-left corner of the block we want to copy 
from our source bitmap, we have not yet specified its size. The last two parameters specify 
the  width and height of the block we are blitting. You may be wondering why in our pro-
gram, we were able to pass these parameters the values of  bmp->w  and  bmp->h. The reason
for this is that the  BITMAP*  type
 type defined
 defined by Allegro is a pointer to a  struct. Along with
the image data and a few other variables, the  BITMAP struct  contains two  int s,  w  and   h,
that represent the width and height of the bitmap, respectively. Unless you do not want
to display the entire image, you should pass these parameters the values  bmp->w  and  bmp-
>h, replacing  bmp  with the name of your bitmap.
The  blit bmp
 function that we called at line 14 then copies a block from  bmp , whose top-
left corner
corner and sizsizee are those of  bmp
 bmp , and draws
draws iitt at the top-lef
top-leftt corner of the virtua
virtuall scree
screen.
n.
In short, it displays the image in  picture.bmp  at the top-le top-left
ft of the scree
screen.
n.

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.5 Animat
Animation
ion with Double Bufferi
Buffering
ng   IX

 After blitting the image onto the screen, the program makes a call to the function
readkey. This function is the reason we called  install_keyboard  earlier in the program.
Function  readkey  waits for a key to be pressed, then returns the value of the key pressed
as an  int . Even though we do nothing with the value it returns,
returns, this function is useful
useful in
this program becau
because,
se, like  scanf, it causes the program to pause until the user provides
some input. Without it, the program would end before we had a chance to see the bitmap.
Finally, after we hit a key, the program calls  destroy_bitmap. As explained previ-
ously, this function destroys the bitmap passed to it and performs the equivalent of the
free function on the memory that was allocated to it.

Error-Prevention Tip E.1


Use the  destroy_bitmap 
  destroy_bitmap  function
 function to free the memory of a bitmap that is no longer needed 
and prevent memory leaks.

Common Programming Error E.3


Trying to destroy a bitmap that has not been initialized
initialized causes a runtime
runtime error.

E.5 Animation
Animat ion with
with Double
Double Buffering 
Buffering 
Now that we know how to draw bitmaps on the screen, animating bitmaps and making 
them move around the screen is straightforward. We are now going to develop the simple
game “Pong.” We begin by using animation techniques to create a square “ball” that
bounces around a white screen. For this purpose, we need a bitmap that serves as our
“ball.” Copy the file  ball.bmp  from this appendix’s examples
examples folder, and save it in a new 
project called  pong. The image  ball.bmp  is 40 pixels wide by 40 pixels tall—this will be
important as we code the program.
In most Pong games, the ball can travel at many different angles. However, since we
are just starting with Allegro, we want to keep things as simple as possible. For this reason,
in our
our Pon
Pongg ga
game
me,, the
the ba
ball
ll on
only
ly ha
hass fo
four
ur poss
possib
ible
le dire
directi
ction
onss of trav
travel
el:: do
down
wn-r
-rig
ight
ht,, up
up-r
-rig
ight
ht,,
down-left, and up-left—all of these at 45-degree angles to the  x - and y  and  y -axes
-axes in our pro-
gram. We use an  int  to keep track of the ball’s current direction, so we can use symbolic
constants for each of the possible directions.
Moving a bitmap around the screen is simple—we just blit our bitmap onto the
screen, then when we want to move it, we clear the screen and blit the bitmap at its new 
position. The program in Fig. E.5 creates a ball that moves around and bounces off the
edges of the screen until we hit the Esc 
the  Esc  key.
 key.

1   /* Fig. E.5:
E.5: figE_05
figE_05.c
.c
2   Cre
Creati
atingng the bou
bounci
ncing
ng bal
ball.
l. */
3   #include   <allegro.h>
4
5   /* sym
symbol
bolicic con
consta
stants
nts for the ball’s
ball’s pos
possib
sible
le dir
direct
ection
ions
s */
6   #define   DOWN_RIG
DOWN_RIGHT
HT 0
7    #define   UP_RIGH
UP_RIGHT
T 1
8   #define   DOWN_LEF
DOWN_LEFT
T 2

Fig. E.5   |  Creating the bouncing ball. (Part 1 of 3.)

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

X   Appen
Appendix
dix E Game Progra
Programming
mming with the Allegro C Librar
Library
y

9   #define   UP_LEF
UP_LEFT
T 3
10
11   /* functio
function n pro
protot
totype
ypes s */
12   void   moveBall(   void   );
13   void   reverseVerticalDirection(   void   );
14   void  reverseHorizontalDirection(   void   );
15
16   int   ball_x;   /* the bal
ball’s
l’s x-c
x-coor
oordin
dinate
ate */
17    int   ball_y;   /* the bal
ball’s
l’s y-c
y-coor
oordin
dinate
ate */
18   int   direction;   /* the bal
ball’s
l’s directio
direction
n */
19   BITM
BITMAPAP *ball;
*ball;   /* po
poin
inte
ter
r to th
the
e ba
ball
ll’s
’s imag
image
e bi
bitm
tmap
ap */
20
21   int   main(   void   )
22   {
23   /* firs
first,t, set
set up Alle
Allegrgro
o and thethe grap
graphi
hics
cs mode
mode */
*/
24   allegro_init();   /* ini initia
tializ
lize
e All
Allegr
egroo */
25   install_keyboard();   /* in inststal
alll th
the
e ke
keyb
yboa
oard
rd fo
for
r Al
Alle
legr
groo to us
use
e */
26   set_color_depth(   16   );   /* se set
t th
the
e co
colo
lor
r dedept
pth
h to 1616-b
-bit
it */
27    set_gfx_mode(   GFX_AUTODETECT,   640,   480,   0,   0   );   /* se set
t gr
grap
aphi
hics
cs mo
mode
de */
28   ball
ball = load_b
load_bitm ap(   "ball.bmp",   NULL   );   /* lo
itmap( load
ad th
thee ba
ball
ll bi
bitm
tmap
ap */
29 l_x =   SCREEN_W   /   2; /* giv
ball_x
bal givee the bal
ball
l its ini
initia
tial l x-c
x-coor
oordin
dinate
ate */
30 l_y =   SCREEN_H   /   2; /* giv
ball_y
bal givee the bal
ball
l its ini
initia
tial l y-c
y-coor
oordin
dinate
ate */
31 srand( time(   NULL   ) );   /* se
  srand( seed
ed th
the
e ra
rand
ndom
om fu
func
ncti
tion
on */
32   direct
direction rand() %   4;   /* an
ion = rand() andd th
then
en ma
make
ke a rarand
ndom
om ininit
itia
ial
l di
dire
rect
ctio
ion
n */
33
34 while   ( !k
!key [KEY_ESC] ) /* un
  ey[ unti
til
l th
the
e es
esca
capepe ke
key y is prpres
esse
sed
d ..
.... */
35   {
36   moveBall();   /* momove
ve ththe
e baball
ll */
37  clear_to_
clea r_to_color
color(
( screen, makecol(   255,   255,   255   ) );
screen, makecol(
38   /* no
now
w drdraw
aw th
the
e bi
bitm
tmapap ononto
to th
thee sc
scre
reen
en */
39   blit(
blit( ball,
ball, screen
screen,,   0,   0, bal
ball_x
l_x,
, ball_y
ball_y, , bal
ball->
l->w,w, bal
ball->
l->h
h );
40   }   /* en
endd wh
whil
ile
e */
41
42   destroy_bi
destroy_bitmap
tmap(
( ball );   /* de
dest
stro
roy
y th
the
e ba
ball
ll bi
bitm
tmap
ap */
43   return   0;
44   }   /* en
end
d fu
funcncti
tion
on ma
main
in */
45   END_OF_MAIN()   /* do don’
n’tt fo
forg
rget
et th
this
is!
! */
46
47    void   moveBall()   /* mo
move
ves
s th
the
e ba
ball
ll */
48   {
49   switch   ( di
dire
rect
ctio
ion
n ) {
50   case   DOWN_RIGHT:
51   ++ball_x;   /* mo
move
ve th
the
e ba
ball
ll to th
the
e ri
righ
ght
t */
52   ++ball_y;   /* mo
move
ve th
the
e ba
ball
ll do
down
wn */
53   break;
54   case   UP_RIGHT:
55   ++ball_x;   /* mo
move
ve th
the
e ba
ball
ll to th
the
e ri
righ
ght
t */
56   --ball_y;   /* mo
move
ve th
the
e ba
ball
ll up */
57    break;
58   case   DOWN_LEFT:
59   --ball_x;   /* mo
move
ve th
the
e ba
ball
ll to th
the
e le
left
ft */
60   ++ball_y;   /* mo
move
ve th
the
e ba
ball
ll do
down
wn */
61   break;

Fig. E.5   |  Creating the bouncing ball. (Part 2 of 3.)

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.5 Animat
Animation
ion with Double Bufferi
Buffering
ng   XI

62   case   UP_LEFT:
63   --ball_x;   /* mo
move
ve th
the
e ba
ball
ll to th
the
e le
left
ft */
64   --ball_y;   /* mo
move
ve th
the
e ba
ball
ll up */
65   break;
66   }   /* en
end
d swswit
itch
ch */
67 
68   /* make
make sure
sure the
the ball
ball does
doesn’
n’t
t go off
off the scr
scree
een
n */
69
70   /* if the
the ball
ball is goi going
ng off
off the
the top or or bot
botto
tom.
m...
.. */
71 if   ( ba
ball_y <=   30   || ba
ll_y ball_y >=   440   )
ll_y
72   reverseVerticalDirection();   /* make make it go thethe ot
othe
her
r wa
way
y */
73
74   /* if the
the ball
ball is goi going
ng off
off the
the left
left or righ
right.
t...
.. */
75 if   ( ba
ball_x <=   0   || ba
ll_x ball_x >=   600   )
ll_x
76   reverseHorizontalDirection();   /* make make it go th
the
e ot
othe
her
r wa
way
y */
77    }   /* end fun
functi
ction
on mov
moveBa
eBall
ll */
78
79   void   reverseVerticalDirection()   /* rev revers
ersee the bal
ball’s
l’s up-
up-dow
down
n dir
direct
ection
ion */
80   {
81 if   ( ( di
dire
rect
ction %   2   ) ==   0   )   /* "do
ion "down"
wn" dir
direct
ection
ions
s are eve
evenn num
number
bers
s */
82 ++direction;   /* ma
makeke th
the e baballll st
star
art
t mo
movi
ving
ng up */
83 else   /* "u
"up"
p" di
dire
rectctio
ionsns ar
are e ododd d nu
numb
mber
erss */
84 --direction;   /* ma
makeke th
the e baballll st
star
art
t mo
movi
ving
ng do
down
wn */
85   }   /* end funct
function
ion rever
reverseVe
seVertica
rticalDire
lDirection
ction */
86
87    void  reverseHorizontalDirection()   /* rev revers
erses
es the hor
horizo
izonta
ntall dir
direct
ection
ion */
88   {
89 di
dire
rect
ctio
ion
n = ( di
dire
  rect
ction +   2   ) %   4; /* rev
ion revers
erse
e hor
horizo
izonta
ntal
l dir
direct
ection
ion */
90   }   /* end funct
function
ion rever
reverseHo
seHorizon
rizontalDi
talDirecti
rection
on */

Fig. E.5   |  Creating the bouncing ball. (Part 3 of 3.)

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

XII   Appen
Appendix
dix E Game Progra
Programmin
mming
g with the Allegr
Allegro
o C Librar
Library
y

Not much is new in this program. The first lines of interest are at lines 29 and 30
 where we set the initial values for  ball_x  and  ball_y. The symbolic constants
constants  SCREEN_W
and   SCREEN_H  are reserved by Allegro—these correspond to the width and height (in
pi
pixe
xels
ls),
), re
resp
spect
ectiv
ivel
ely,
y, of the
the sc
scre
reen
en set
set by ca
call
llin
ing 
g set_gfx_mode. Th
Thes
esee line
lines,
s, the
there
refo
fore
re,, plac
placee
the ball in the center of the screen.
Line 34 contains a new keyboard-related item—Allegro has an array of   ints called
key. The array contains an index for each key on the keyboard—if a certain key is being 
pressed, the value at its corresponding index is set to 1; if it is not being pressed, the value
is set to 0. The index that we check in the  while loop is  KEY_ESC, an Allegro symbolic con-
stant that corresponds to the   Esc  Esc   key. Because the condition for our   while   loop is
!key[KEY_ESC], our our prog
progra
ramm will
will con
contitinu
nuee wh
whil
ilee key[KEY_ESC] hahass a va
vallue of 0—
0—iin ot
othe
herr
 words, while the
the Esc 
 Esc  key
 key is not being pressed. We will discuss the  key  array and Allegro’s
symbolic constants for the keyboard in more detail in Section E.7.
Li
Line
ne 37 co
cont
ntai
ains
ns the
the func
functi
tion
on that
that we use
use to draw
draw th
thee ba
back
ckgr
grou
ound
nd— —clear_to_color.
 Allegro does not have any explicit “background” defined in its library, but the
clear_to_color function, as described in Fig. E.2, sets an initial color for the screen onto
 which we can later draw. Note, though, that in our program we had to use a function to
pass the  color  parameter to  clear_to_color. This function is the  makecol  function. Its

prototype is:
int   makecol(   int   red,   int   green,   int   blue
blue );

This function returns an   int  that represents the color with the specified red, green,
and blue intensities. The intensities allowed can range from 0 to 255, so passing the values
( 255, 0, 0 ) wiwill
ll cr
crea
eate
te a br
brig
ight
ht red
red co
colo
lor,
r, ( 0, 255, 0 ) will create a bright green and
( 0, 0, 255 ) will make a bright blue. In Fig. E.5, we passed ( 25 255,
5, 25
255,
5, 25
2555 ), or the
maximum intensity of all three colors, which creates white. This means that our program
 will set the color of the screen to white when the  clear_to_color  function is called.
Figure E.6 shows a table of common colors and their red, green, and blue values.

Color Red value Green value Blue value

Red 255 0 0
Green 0 255 0
Blue 0 0 255
Orange 255 200 0
Pink 255 175 175
Cyan 0 255 255
Magenta 255 0 255
 Y
 Yellow
ellow 255 255 0
Black 0 0 0
 White 255 255 255
Gray 128 128 128

Liagrhkt ggrraayy
D 14
692 14
692 14
692

Fig. E.6   |   The red, green and blue intensities of common colors in Allegro.

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.5 Animat
Animation
ion with Double Bufferi
Buffering
ng   XIII

The re
The rest
st of th
thee prog
progra
ram
m is self
self-e
-expl
xplan
anat
ator
ory—
y—we
we ha
have
ve the
the bal
balll mov
movee ar
arou
ound
nd th
thee scre
screen
en,,
and when it hits an edge, it changes its direction so that it “bounces.” The reason that the
lines in  moveBall and the two  reverseDirection functions are highlighted is because the
math might appear to be a bit odd. First we check if the ball is going off the screen at lines
71 and 75. You may be wondering why the right and bottom boundaries of our screen
appear to be 600 and 440 in these   if  statements, as opposed to 640 and 480 (the actual
size of the screen). Recall that when we blit a bitmap onto the screen, we pass it the top-
left corner of the block onto which we want to draw. This means that if  ball_y has a value
of 440, its top boundary will be at the   y -coordinate
-coordinate 440. However, since the ball is 40
pixels tall, its bottom boundary will actually be at the   y -coordinate
-coordinate 480, which is the
bottom of the screen. The same applies to the ball’s x 
ball’s  x -coordinate,
-coordinate, which explains why the
largest value it can be is 600. Also, if you are wondering why the lowest y  lowest  y -value
-value allowed is
30, this is simply because we will use the top 30 pixels of the screen for the scoreb scoreboard
oard as
 we add more into our Pong game.
Consider the lines that change the ball’s direction. Line 82 causes the ball to start
moving up if it’s currently moving down, while line 84 does the opposite. Line 89 makes
th
thee ball
ball star
startt mo
movi
ving
ng le
left
ft if it’s
it’s curr
curren
entl
tlyy mo
movi
ving
ng righ
right,
t, and
and righ
rightt if it
it’s
’s cu
curr
rren
entl
tlyy mo
movi
ving
ng left
left..
 Why does this work? Because of the specific values of the symbolic constants (lines 6–9),

performing the operations


Our “ball” is a square in
andthese
not three lines
a circle. willdoes
This always
notget youmuch
have the direction
impact onyouour
want.
pro-
gram now, but once we add paddles into our game, having a square ball makes it much
easier to detect if the ball and paddles are touching. We will go into more detail on this
issue in Section E.9 when we add this feature to our game.
Run the program and you’ll see your ball bounce around the screen. Notice, though,
that the scree
screenn flickers substa
substantial
ntially
ly as the ball moves, to the point where it is diffi
difficult
cult to
see the ball. To fix this, we introduce a technique called double buffering.

Double Buffering for Smooth Animation


If you ran the program of the previous section, you probably noticed that the screen flick-
ered as the ball moved. Why is this? Recall that for our animation to work, we had to clear
the screen every time the ball moved. Unfortunately, this isn’t the best practice. Though
most
mo st comp
comput uter
erss ca
can
n cl
clea
earr an
andd redr
redraw
aw the
the sc
scre
reen
en quic
quickl
kly,
y, th
ther
eree is stil
stilll a sm
smal
alll am
amouount
nt of ti
time
me
that the screen is blank between when it’s cleared and when the ball is blitted onto it. Even
though the screen is blank only briefly, it is still enough to cause the screen to appear to
flicker as it animates the ball, since the ball keeps vanishing before it is redrawn.
 We can fix this with a technique
technique called double buffer
buffering,
ing, which uses a screen screen-sized
-sized,,
intermediary bitmap called a buffer to make the animation of moving bitmaps smoother.
Inst
Instea
ead
d of bl
blit
itti
ting
ng bi
bitm
tmap
apss to the
the sc
scre
reen
en,, we bl
blit
it obje
object
ctss we want
want ththee user
user to see
see to th
thee buff
buffer
er..
Once everything we want is there, we blit the buffer to the screen and clear the buffer.
 Why does this work? You’ll notice that we never clear the screen when we use this
technique.
techni que. Instead of deledeleting
ting everythi
everythingng befor
beforee redra
redrawing
wing the image
imagess on the screen, we
simply draw over what’s already there, which eliminates the flicker that the program in

Fig. E.5 (remember,


the user produceder,
(rememb when it cleared
the user theonly
can see screen.
the In addition,
 screen ), wesince the to
can blit buffer is notthe
and clear visible
buffto
buffer
er
 without worrying about it affecting anything that the user sees. Figure E.7 shows this tech-
nique in practice.

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

XIV    Appendix
Appendix E Game Progra
Programming
mming with the Allegro C Librar
Library
y

Double buffering takes only slightly more code than blitting directly to the screen—
our modified program has only four more lines of code than the original! Lines 40–43
show how to code double buffering. We simply make the buffer white and blit the ball to
the buffer at position  ball_x,  ball_y. Then, blit the whole buffer to the screen, and clear
the buffer. The screen is never cleared, only drawn over, so there is no flicker.

1   /* Fig. E.7:
E.7: figE_07
figE_07.c
.c
2   Usi
Using
ng dou
double
ble buf
buffer
fering
ing.
. */
3   #include   <allegro.h>
4
5   /* sym
symbol
bolicic con
consta
stants
nts for the ball’s
ball’s pos
possib
sible
le dir
direct
ection
ions
s */
6   #define   DOWN_RIG
DOWN_RIGHT
HT 0
7    #define   UP_RIGH
UP_RIGHTT 1
8   #define   DOWN_LEF
DOWN_LEFTT 2
9   #define   UP_LEF
UP_LEFT
T 3
10
11   /* functio
function n pro
protot
totype
ypes s */
12   void   moveBall(   void   );
13   void   reverseVerticalDirection(   void   );
14   void  reverseHorizontalDirection(   void   );
15
16   int   ball_x;   /* the bal
ball’s
l’s x-c
x-coor
oordin
dinate
ate */
17    int   ball_y;   /* the bal
ball’s
l’s y-c
y-coor
oordin
dinate
ate */
18   int   direction;   /* the bal
ball’s
l’s directio
direction
n */
19   BITM
BITMAPAP *ball;
*ball;   /* po
poin
inte
ter
r to th
the
e ba
ball
ll’s
’s im
imag
age
e bi
bitm
tmap
ap */
20 BITMAP
BITM AP   *buffer;
*buffer; /* popoin
inte
ter
r to th
the
e bu
buff
ffer
er */
21
22   int   main(   void   )
23   {
24   /* firs
first,t, set
set up Alle
Allegr
groo and the
the grap
graphi
hics
cs mode
mode */*/
25   allegro_init();   /* iniinitia
tializ
lize
e All
Allegr
egroo */
26   install_keyboard();   /* in inst
stal
alll th
the
e ke
keyb
yboa
oard
rd fo
for r AlAlle
legr
groo to us
use
e */
27    set_color_depth(   16   );   /* se
set
t th
the
e co
colo
lor
r de
dept
pth
h to 16 16-b
-bit
it */
28   set_gfx_mode( GFX_AUTODETECT,   640,   480,   0,   0   );   /* se
set
t gr
grap
aphi
hics
cs mo
mode
de */

29
30   ball
ball =
r load_b
buffer
buffe loa d_bitm
itmap(
= create_bit
creat   "ball.bmp"
ap(map(
e_bitmap( ,   NULL
  SCREEN_W   );   /*   lo
,   SCREEN_H load
);ad
/* th
the
e
crea
cr ball
ba
tell
eate bitm
bi
buff
bu tmap
erap
ffer */*/
31   ball_x =   SCREEN_W   /   2;   /* giv
ball_x give
e the bal balll its initial
initial x-c
x-coor
oordin
dinate
ate */
32   ball_y =   SCREEN_H   /   2;   /* giv
ball_y give
e the bal balll its initial
initial y-c
y-coor
oordin
dinate
ate */
33   srand( time(   NULL   ) );   /* se
srand( seed
ed th
the e rarand
ndom
om fufuncncti
tion
on ..
...
. */
34   direct
direction rand() %   4;   /* an
ion = rand() and
d th
thenen mamake
ke a ra rand
ndom
om in
init
itia
ial
l di
dire
rect
ctio
ion
n */
35
36   while   ( !k
!key [KEY_ESC] )   /* un
ey[ unti
till th
the e es
esca
cape
pe ke
key y is prpres
esse
sed
d ..
...
. */
37    {
38   moveBall();   /* momove
ve ththe
e baball
ll */
39   /* now
now,
, per
perfor
form
m dou
double
ble buf buffer
fering
ing */
40 clear_to_
clea r_to_color
color(
( buffer, makecol(   255,   255,   255   ) );
buffer, makecol(
41 blit(
bli t( ball,
ball, buffer
buffer,,   0,   0, bal
ball_x
l_x, , ball_y
ball_y,, bal
ball->
l->w,w, ball->
ball->h
h );
42 blit(
blit ( buffer, screen,   0,   0,   0,   0, buffer
buffer, screen, buffer->w
->w, , buffer
buffer->h
->h );
43 clear_bit
clea r_bitmap(
map( buffer
buffer );
44   }   /* en
end
d wh
whil
ile
e */

Fig. E.7   |  Using double buffering. (Part 1 of 3.)

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.5 Animat
Animation
ion with Doubl
Doublee Buffering
Buffering   XV 

45
46   destroy_bi
destroy_bitmap
tmap(
( ball );   /* de
dest
stro
roy
y th
the
e ba
ball
ll bi
bitm
tmap
ap */
47  destroy_bi
destr oy_bitmap(
tmap(
  buffer
buffer ); /* de
dest
stro
roy
y th
the
e bu
buff
ffer
er bi
bitm
tmap
ap */
48   return   0;
49   }   /* en
end
d fu
func
ncti
tion
on ma
main
in */
50   END_OF_MAIN()   /* dodon’
n’t
t fo
forg
rget
et th
this
is!
! */
51
52   void   moveBall()   /* mo move
ves
s th
the
e ba
ball
ll */
53   {
54   switch   ( didire
rect
ctioion n ) {
55   case   DOWN_RIGHT:
56   ++ball_x;   /* mo move
ve th
thee ba
ball
ll to th the
e ri
righ
ght
t */
57    ++ball_y;   /* mo move
ve th
thee ba
ball
ll do
downwn */
58   break;
59   case   UP_RIGHT:
60   ++ball_x;   /* mo move
ve th
thee ba
ball
ll to th the
e ri
righ
ght
t */
61   --ball_y;   /* mo move
ve th
thee ba
ball
ll up */
62   break;
63   case   DOWN_LEFT:
64   --ball_x;   /* mo move
ve th
thee ba
ball
ll to th the
e le
left
ft */
65   ++ball_y;   /* move
mo ve the
th e ball
ba ll down
do wn */
66   break
67    ;
case   UP_LEFT :
68   --ball_x;   /* mo move
ve th
thee ba
ball
ll to th the
e le
left
ft */
69   --ball_y;   /* mo move
ve th
thee ba
ball
ll up */
70   break;
71   }   /* enend
d swswit
itch
ch */
72
73   /* mamake
ke sure
sure the
the ballball does
doesn’
n’t
t go off
off the scr scree
een
n */
74
75   /* ifif the
the ball
ball isis goin
goingg off
off the
the top
top or bottbottom
om ...
... */
*/
76   if   ( ba
ball
ll_y_y <=   30   || ba
ball _y >=   440   )
ll_y
77    reverseVerticalDirection();
78
79   /* ifif the
the ball
ball isis goin
goingg off
off the
the left
left or or righ
right
t ...
... */
80   if   ( ba
ball
ll_x_x <=   0   || ba
ball _x >=   600   )
ll_x
81   reverseHorizontalDirection();
82   }   /* end fun
functi
ction
on mov
moveBa
eBall
ll */
83
84   void   reverseVerticalDirection()   /* rev revers
ersee the bal
ball’s
l’s up-
up-dow
down
n dir
direct
ection
ion */
85   {
86   if   ( ( di
dire
rect
ction %   2   ) ==   0   )   /* "do
ion "down"
wn" dir
direct
ection
ions
s are eve
evenn num
number
bers
s */
87    ++direction;   /* ma
makeke th
the e baballll st
star
art
t mo
movi
ving
ng up */
88   else   /* "u
"up"
p" di
dire
rectctio
ionsns ar
are e ododd d nu
numb
mber
erss */
89   --direction;   /* ma
makeke th
the e baballll st
star
art
t mo
movi
ving
ng do
down
wn */
90   }   /* end funct
function
ion rever
reverseVe
seVertica
rticalDire
lDirection
ction */
91
92   void  reverseHorizontalDirection()   /* rev revers
erses
es the hor
horizo
izonta
ntall dir
direct
ection
ion */
93   {
94   di
dire
rect
ctio
ion
n = ( di
dire
rect
ction +   2   ) %   4;   /* rev
ion revers
erse
e hor
horizo
izonta
ntal
l dir
direct
ection
ion */
95   }   /* end funct
function
ion rever
reverseHo
seHorizon
rizontalDi
talDirecti
rectionon */

Fig. E.7   |  Using double buffering. (Part 2 of 3.)

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

XVI   Appen
Appendix
dix E Game Progra
Programming
mming with the Allegro C Librar
Library
y

Fig. E.7   |  Using double buffering. (Part 3 of 3.)

E.6 Import
Importing
ing and
and Playing
Playing Sounds
Sounds
 While a game with only graphics is fun to play, a game that uses sounds to enhance the
player’s experience is much more interesting. We now discuss importing sounds and play-
ing sound files in Allegro programs, which we will use to “juice up” our game by having a 
“boing” sound play whenever the ball hits a wall.
Sound files are handled similarly to bitmaps—just as the  allegro.h  header defines
several types that are used to hold image data, it defines several types that are used to hold
sound data, as well. With images, the most basi
basicc of these types is  BITMAP*. With sounds,
the most basic of these types is the type  SAMPLE*—Allegro refers to sound files as “digital
samples.” Like  BITMAP*, the  SAMPLE*  type is a pointer.
The Allegro functions used to import and play sounds are analogous to those used for
import
imp orting
ing and dis
displa
playin
yingg bit
bitmap
maps.
s. Fig
Figure
ure E.8 sho
showsws the mos
mostt imp
import
ortant
ant All
Allegr
egroo fun
functi
ctions
ons
for manipulating sound files.
The  install_sound function must be called before Allegro can play any sound files.
Its prototype is:
int   install_sound(int   digi,   int   midi,   cons
const
t cha
char
r   *cfg_path);

The function returns an  int  for error-checking purposes—0 if the function is successful,
and
and a no
non-
n-ze
zerro va
valu
luee if it is no
not.
t. Th
Thee digi and midi pa
para
rame
mete
ters
rs spe
speci
cify
fy th
thee soun
sound
d card
card dr
driv
iv--

ers
ers,used for playing
the newer digital
versions of samples
Allegro and MIDI
provide files, respectively.
so-called As with
“magic drivers” theautomatically 
that graphic driv-
specify the audio drivers to use—DIGI_AUTODETECT and  MIDI_AUTODETECT. These are the
only values that you should pass to the first two parameters.

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.6 Impo
Importing
rting and Playin
Playing
g Sounds
Sounds   XVII

Function prototype Description

SAMPLE *load_sa
*load_sample(co
mple(const
nst Loads and returns a pointer to a sound file
char   *filename)  with the specified filename. The file must be in
.wav  format. Returns  NULL (with no error) if 
the specified file cannot be loaded.
int   play_sample(const   SAMPLE
SAMPLE *spl, Plays the specified sample at the specified vol-
int   vol,   int   pan,   int   freq, ume, pan position, and frequency. The sample
int   loop)  will loop
l oop continuously if  loop
  loop is non-zero.
void   adjust_sample(const   SAMPLE
SAMPLE *spl,
*spl,  Adjusts a currently playing sample’s
sample’s parameters
int   vol,   int   pan,   int   freq, to the ones specified.
specified. Can be called on any 
int   loop) sample without causing errors, but will affect
only ones that are currently playing.
void   stop_sample(con
stop_sample(const
st SAMPLE *spl)   Stops a sample that is currently playing.
void   destroy_sample(SAMPL
destroy_sample(SAMPLE
E *spl)   Destroys a sample and frees the memory allo-
cated to it. If the sample is currently playing or
looping, it will stop immediately.

Fig. E.8   |  Important SAMPLE functions.


The   cfg_path  parameter has no effect on the program. Older versions of Allegro
required that you specify a  .cfg
 .cfg file that told the program how to play sound files, but this
is no longer necessary in the current version.
Now let
let’s
’s ad
add
d sou
sound
ndss to the bou
bounci
ncing
ng ba
ball
ll pro
progr
gram.
am. As wit
with
h bi
bitma
tmaps,
ps, we must
must pro
provi
vide
de
the program with an external sound file to load, so copy the  boing.wav sound file from the
appendix’s examples
examples folder and save it in the same folder as your pong project. Then we can
use the code in Fig. E.9 to make our ball emit a “boing” sound whenever it bounces off a 
side of the screen. The highlighted lines mark the changes from the previous section.

1   /* Fig. E.9:
E.9: figE_09
figE_09.c
.c
2   Uti
Utiliz
lizing
ing sou
sound
nd fil
files
es */
3   #include   <allegro.h>
4
5   /* sym
symbol
bolicic con
consta
stants
nts for the ball’s
ball’s pos
possib
sible
le dir
direct
ection
ions
s */
6   #define   DOWN_RIG
DOWN_RIGHT
HT 0
7    #define   UP_RIGH
UP_RIGHTT 1
8   #define   DOWN_LEF
DOWN_LEFTT 2
9   #define   UP_LEF
UP_LEFT
T 3
10
11   /* functio
function n pro
protot
totype
ypes s */
12   void   moveBall(   void   );
13   void   reverseVerticalDirection(   void   );
14   void  reverseHorizontalDirection(   void   );
15
16   int   ball_x;   /* the bal
ball’s
l’s x-c
x-coor
oordin
dinate
ate */
17    int   ball_y;   /* the bal
ball’s
l’s y-c
y-coor
oordin
dinate
ate */
18   int   direction;   /* the bal
ball’s
l’s directio
direction
n */

Fig. E.9   |   Utilizi


Utilizing
ng sound files. (Part
(Part 1 of 3.)

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

XVIII   Append
Appendix
ix E Game Progra
Programming
mming with the Allegro C Librar
Library
y

19   BITM
BITMAP
AP *ball;
*ball;   /* po
poin
inte
ter
r to ba
ball
ll’s
’s im
imag
age
e bi
bitm
tmap
ap */
20   BITM
BITMAP
AP *buffer;
*buffer;   /* po
poin
inte
terr to th
the
e bu
buff
ffer
er */
21 SAMPLE
SAMPLE   *boing;
*boing; /* popoin
inte
terr to so
soun
und
d fi
file
le */
22
23   int   main(   void   )
24   {
25   /* firs
first,t, set
set up Alle
Allegrgro
o and thethe grap
graphi
hics
cs mode
mode */
*/
26   allegro_init();   /* ini initia
tializ
lize
e All
Allegr
egroo */
27    install_keyboard();   /* in inststal
alll th
the
e ke
keyb
yboa
oard
rd fo
forr Al
Alle
legr
groo to us
usee */
28 install_sound(   DIGI_AUTODETECT,   MIDI_AUTODETECT,   NULL   );
29   set_color_depth(   16   );   /* se set
t th
the
e co
colo
lor
r dedept
pth
h to 1616-b
-bit
it */
30   set_gfx_mode(   GFX_AUTODETECT,   640,   480,   0,   0   );   /* se set
t gr
grap
aphi
hics
cs mo
mode
de */
31   ball
ball = load_b
load_bitm ap(   "ball.bmp",   NULL   );   /* lo
itmap( load
ad th
thee ba
ball
ll bi
bitm
tmap
ap */
32   buffer
buffer = create_bi
create_bitmap
tmap( (SCREEN_W,   SCREEN_H);/*);/* cr
crea
eate
te bu
buff
ffer
er */
33 boing = load_sampl   e(   "boing.wav"   ); /* lo
load_sample( load
ad th
thee so
soun
und
d fi
file
le */
34   ball_x =   SCREEN_W   /   2;   /* giv
ball_x givee the bal
ball
l its initial
initial x-c
x-coor
oordin
dinate
ate */
35   ball_y =   SCREEN_H   /   2;   /* giv
ball_y givee the bal
ball
l its initial
initial y-c
y-coor
oordin
dinate
ate */
36 srand( time(   NULL   ) );   /* se
  srand( seed
ed th
the
e ra
rand
ndom
om fu
func
ncti
tion
on ..
...
. */
37    direct
direction rand() %   4;   /* an
ion = rand() andd th
then
en ma
make
ke a rarand
ndom
om in
init
itia
ial
l di
dire
rect
ctio
ion
n */
38   while   ( !k!key
ey[ [KEY_ESC] )/* un unti
till th
thee es
esca
capepe ke
key
y is prpres
esse
sed
d ..
...
. */
39   {
40
41    moveBall();
/* now
now, , per   /*mmo
perfor
form move
veble
double
dou the
thebufball
ball
buffer */
fering
ing */
42   clear_to_
clear_to_colorcolor( ( buffer, makecol(   255,   255,   255   ) );
buffer, makecol(
43   blit(
blit( ball,
ball, buffer
buffer,,   0,   0, bal
ball_x
l_x, , ball_y
ball_y,, bal
ball->
l->w,w, bal
ball->
l->h
h );
44   blit(
blit( buffer, screen,   0,   0,   0,   0, buffer
buffer, screen, buffer->w
->w, , buf
buffer
fer->h
->h );
45   clear_bit
clear_bitmap( map( buffer
buffer );
46   }   /* enendd wh
whilile
e loloop
op */
47    destroy_bi
destroy_bitmap tmap(( ball );   /* de dest
stro
roy
y ththe
e ba
ball
ll bi
bitmtmap
ap */
48   destroy_bi
destroy_bitmap(tmap( buffer
buffer );   /* de dest
stro
roy y th
thee bu
buff
ffer
er bi
bitmtmap
ap */
49 destroy_sa
destr   mple( boing
oy_sample( boing ); /* de dest
stro
roy y th
thee bo
boin
ing
g sosoun
und d fi
file
le */
50   return   0;
51   }   /* en
end
d fu
func
ncti tion
on mamain
in */
52   END_OF_MAIN()   /* do don’
n’t
t fo
forg
rgetet ththis
is!! */
53
54   void   moveBall()   /* mo
move
ves
s th
the
e ba
ball
ll */
55   {
56   switch   ( di
dire
rect
ctio
ion
n ) {
57    case   DOWN_RIGHT:
58   ++ball_x;   /* mo
move
ve the ba
the ball
ll to th
the
e ri
righ
ght
t */
59   ++ball_y;   /* mo
move
ve the
the ba
ball
ll do
down
wn */
60   break;
61   case   UP_RIGHT:
62   ++ball_x;   /* mo
move
ve the ba
the ball
ll to th
the
e ri
righ
ght
t */
63   --ball_y;   /* mo
move
ve the
the ba
ball
ll up */
64   break;
65   case   DOWN_LEFT:
66   --ball_x;   /* mo
move
ve the ba
the ball
ll to th
the
e le
left
ft */
67    ++ball_y;   /* mo
move
ve the
the ba
ball
ll do
down
wn */
68   break;
69   case   UP_LEFT:
70   --ball_x;   /* mo
move
ve th
the
e ba
ball
ll to th
the
e le
left
ft */
71   --ball_y;   /* mo
move
ve th
the
e ba
ball
ll up */

Fig. E.9   |   Utilizi


Utilizing
ng sound files. (Part
(Part 2 of 3.)

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.6 Impo
Importing
rting and Playing Sounds   XIX

72   break;
73   }   /* end
end sw
swit
itch
ch */
74
75   /* mak
make
e sure
sure the
the bal
ball
l does
doesn’
n’t
t go off
off scr
scree
een
n */
76
77    /* ifif the
the ball
ball isis goin
going
g off
off the
the top
top or bott
bottom
om ...
... */
*/
78   if   ( ba
ball _y <=   30   || ba
ll_y ball _y >=   440   )
ll_y
79   reverseVerticalDirection();
80
81   /* ifif the
the ball
ball isis goin
going
g off
off the
the left
left or
or righ
right
t ...
... */
82   if   ( ba
ball _x <=   0   || ba
ll_x ball_x >=   600   )
ll_x
83   reverseHorizontalDirection();
84   }   /* end fun
functi
ction
on mov
moveBa
eBall
ll */
85
86   void   reverseVerticalDirection()   /* rev revers
erse e the bal
ball’s
l’s up-
up-dow
down
n dir
direct
ection
ion */
87    {
88   if   ( ( di
dire
rect
ction %   2   ) ==   0   )   /* "do
ion "down"
wn" dir
direct
ection
ions
s are eve
evenn num
number
bers
s */
89   ++direction;   /* ma
make
ke th
the e baballll st
star
art
t momovi
ving
ng up */
90   else   /* "u
"up"
p" di
dire
rectctio
ions
ns ar
are e ododd d nu
numb
mber
ers s */
91   --direction;   /* ma
make
ke th
the e baballll st
star
art
t momovi
ving
ng do
down
wn */
92 play_sample( boing,     255,   128,   1000,   0   ); /* pl
play
ay "b
"boi
oing
ng"
" so
soun
und
d on
once
ce */
93
94   }   /* end funct
function
ion rever
reverseVe
seVertica
rticalDire
lDirection
ction */
95   void  reverseHorizontalDirection()   /* rev revers
erses
es the hor
horizo
izonta
ntall dir
direct
ection
ion */
96   {
97    di
dire
rect
ctio
ion
n = ( di
dire
rect
ctio n +   2   ) %   4;   /* rev
ion revers
erse
e hor
horizo
izonta
ntal
l dir
direct
ection
ion */
98     255,   128,   1000,   0   ); /* pl
play_sample( boing, play
ay "b
"boi
oing
ng"
" so
soun
und
d on
once
ce */
99   }   /* end funct
function
ion rever
reverseHo
seHorizon
rizontalDi
talDirecti
rectionon */

Fig. E.9   |   Utilizi


Utilizing
ng sound files. (Part
(Part 3 of 3.)

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

XX   Appendix
Appendix E Game Progra
Programming
mming with the Allegro C Libra
Library
ry

Because we placed the call to the   play_sample  function inside our functions that
reverse the ball’s direction, the “boing” sound will play whenever the ball’s direction is
reversed—in other words, whenever the ball hits the boundary of the screen. Consider the
prototype of function  play_sample:

int   play_sample(const   SAMPLE *sample,


*sample,   int   volume,   int   pan,
int   frequency,   int   loop)

The  volume and  pan  parameters determine the volume and pan position of the sample be-
ing played,
played, and the value
valuess passed to them can range from 0 to 255. A volume of 0 means
the sound will be muted, while a volume of 255 plays the sound at full volume. A pan po-
siti
sition
on of 12
1288 wi
will
ll pl
play
ay the
the soun
soundd ou
outt of bo
both
th sp
spea
eake
kers
rs equa
equall
lly,
y, wh
whil
ilee a lowe
lowerr or hi
high
gher
er va
valu
luee
 will play the sound more towards
t owards the left or right, respectively. The  frequency parameter,
 which specifies the frequency at which the sample will be played, is a parameter whose val-
ue is relative rather than absolute. A  frequency
  frequency  value of 1000 will play the sound at the
frequency at which it was recorded, while a value of 2000 will play a sample at twice its
normal frequency, which produces a much higher pitch, a value of 500 will play the sam-
ple at half its normal frequency, which produces a lower pitch and so on. Finally, as ex-
plained in Fig. E.8, the  loop  parameter will cause the sample to loop continuously if its
value is not 0. Otherwise, the sample will play only once.

E.7 Key
Keyboa
board
rd Inp
Input
ut
 A game cannot
c annot be called a game unless the user can interact with it in some way. We have
already used some keyboard input methods in this appendix; now we discuss keyboard in-
put in Allegro in more detail.
The first thing we must do to allow Alleg Allegro
ro to recog
recognize
nize and use the keyboard
keyboard is call
the  install_keyboard  function, which takes no parameters. Allegro does not need any 
driver information to install the keyboard.
Recall that Allegro defines an array of  int  int s called  key . This array enables us to deter-
mine when keys are pressepressed.d. In addi
addition
tion to the array, the  allegro.h header defines sym-
bolic constants that correspond to the keys on a standard keyboard. For example, the
constant
consta nt for the
the A
 A key
 key is  KEY_A, and the constant for the spacebar is  KEY_SPACE. The full
list of these constants is available at  www.allegro.cc/manual/key. These constants are
used in tandem with the  key  array to determine if the key to which a given constant cor-
responds is being pressed at any given time.
Each symbolic constant corresponds to an index in the  key  array that keeps track of 
 whether that key is being pressed or not. If the key is not being pressed, the array will hold
0 at that index, whil
whilee if it is, the valu
valuee at that index will be non-zero
non-zero.. Thus, if we want to
see if the A
the  A key
 key is being press
pressed,
ed, we look at the value return
returneded by  key[KEY_A]
 key[KEY_A]. If it is not
zero, then we know the user is pressingpressing the
the A
 A key.
 key.
In our Pong game, we use this array to control the paddles on the sides of the screen.
If the A
the A or
 or Z 
 Z  keys
 keys are being pressed, the paddle on the left side should move up and down,
respectively. Likewise, if the user presses the up or down arrow keys, the paddle on the
right side should move in the corresponding direction. For this purpose, we add a new 
function,  respondToKeyboard, to our program that checks if any of these four keys are
being pressed and moves the paddles accordingly.

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.7 Key
Keyboa
board
rd Inp
Input
ut   XXI

Of course, we have not yet drawn the paddles in our program, so the first thing we
need is a bitmap file that contains the image data for them. As with the ball bitmap, you
can find the bitmap file for a paddle in this appendix’s examples folder. Save the file as
bar.bmp in the same folder as your Pong project (the bitmap is 20 by 100 pixels—we will
use this information in the program). Once you have done that, you can use the code in
Fig. E.10 to allow the user to move the paddles with the keyboard. As usual, new lines in
the program are highlighted.
Lines 101–109 in Fig. E.10 show how we use the  key array to determine whether cer-
tain keys are being pressed. In C, any statement that returns a non-zero value is considered
“true” if used in the condition of an  if  statement, so Allegro’s  key  array makes it easy to
check for keypresses. Note, however, that the call to the   respondToKeyboard
respondToKeyboard  function is
inside the  while loop in our  main (line 49)—this is needed for the keyboard input to work 
correctly. Though the  if  statements in lines 101–109 are all that is necessary to check if 
certain keys have been pressed, each statement checks only once per call. Since we want to
have our program check  constantly 
 constantly  for
  for keyboard input, we must place the  respondToKey-
board  function inside some sort of loop that ensures the program will call it repeatedly.
This holds true for most games besides Pong, as well.

1   /* Fig. E.10:
E.10: figE_1
figE_10.c
0.c
2   Add
Adding
ing pad
paddle
dles
s and
and keyb
keyboar
oard
d input
input.
. */
*/
3   #include   <allegro.h>
4
5   /* sym
symbol
bolicic con
consta
stants
nts for the ball’s
ball’s pos
possib
sible
le dir
direct
ection
ions
s */
6   #define   DOWN_RIG
DOWN_RIGHT
HT 0
7    #define   UP_RIGH
UP_RIGHTT 1
8   #define   DOWN_LEF
DOWN_LEFTT 2
9   #define   UP_LEF
UP_LEFT
T 3
10
11   /* functio
function n pro
protot
totype
ypes s */
12   void   moveBall(   void   );
13 void   respondToKeyboard(   void   );
14   void   reverseVerticalDirection(   void   );
15   void  reverseHorizontalDirection(   void   );
16
17    int   ball_x;   /* the bal
ball’s
l’s x-c
x-coor
oordin
dinate
ate */
18   int   ball_y;   /* the bal
ball’s
l’s y-c
y-coor
oordin
dinate
ate */
19 int   barL_y;
  /* y-y-co
coor
ordi
dina
nate
te of th
the
e le
left
ft pa
padd
ddle
le */
20 int   barR_y;
  /* y-y-co
coor
ordi
dina
nate
te of th
the
e ri
righ
ght
t pa
padd
ddle
le */
21   int   direction;   /* the bal
ball’s
l’s directio
directionn */
22   BITM
BITMAPAP *ball;
*ball;   /* po
poin
inte
ter
r to ba
ball
ll’s
’s im
imag
age
e bi
bitm
tmap
ap */
23 BITMAP
BITM AP   *bar; /* poi
pointe
nter
r to pad
paddle
dle’s
’s ima
image
ge bit
bitmap
map */
24   BITM
BITMAPAP *buffer;
*buffer;   /* po
poin
inte
terr to th
the
e bu
buff
ffer
er */
25   SAMP
SAMPLELE *boing;
*boing;   /* po
poin
inte
terr to so
soun
und
d fi
file
le */
26
27    int   main(   void   )
28   {
29   /* firs
first,t, set
set up Alle
Allegr
gro
o and the
the grap
graphi
hics
cs mode
mode */
*/
30
31    allegro_init();   /* ini
install_keyboard(); initia
  /*tializ
lize
inst
in elAll
stal
allAllegr
egro
the
th oyboa
e ke */
keyboard
rd fo
for
r Al
Alle
legr
gro
o to us
use
e */

Fig. E.10   |  Adding paddles and keyboard input. (Part 1 of 5.)

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

XXII   Appen
Appendix
dix E Game Progra
Programming
mming with the Allegr
Allegro
o C Librar
Library
y

32   install_sound(   DIGI_AUTODETECT,   MIDI_AUTODETECT,   NULL   );


33   set_color_depth(   16   );   /* se set t th
thee co
colo
lorr de
dept
pth
h to 1616-b
-bit
it */
34   set_gfx_mode(   GFX_AUTODETECT,   640,   480,   0,   0   );   /* se sett gr
grap
aphi
hics
cs mo
mode
de */
35   ball
ball = load_b
load_bitm ap(   "ball.bmp",   NULL   );   /* lo
itmap( load
ad th
the
e ba
ball
ll bi
bitm
tmap
ap */
36 bar = load_b
load_bitm     "bar.bmp",   NULL); /* lo
itmap(
ap( load
ad th
the
e ba
bar
r bi
bitm
tmap
ap */
37    buffer
buffer = create_bi
create_bitmap
tmap( (SCREEN_W,   SCREEN_H);/* );/* cr
crea
eate
te bu
buff
ffer
er */
38   boing = load_sampl
load_sample( e(   "boing.wav"   );   /* lo load
ad th
thee so
soun
undd fi
file
le */
39   ball_x =   SCREEN_W   /   2;   /* giv
ball_x give e the bal
balll its initial
initial x-cx-coor
oordin
dinate
ate */
40   ball_y =   SCREEN_H   /   2;   /* giv
ball_y give e the bal
balll its initial
initial y-cy-coor
oordin
dinate
ate */
41 bar L_y =   SCREEN_H   /   2; /* giv
barL_y give e lef
leftt pad
paddle
dle its ini
initia
tiall y-c
y-coor
oordin
dinate
ate */
42 bar R_y =   SCREEN_H   /   2; /* giv
barR_y give e rig
right
ht pad
paddle
dle its ini
initia
tiall y-c
y-coor
oordin
dinate
ate */
43 srand( time(   NULL   ) );   /* se
  srand( seed ed th
thee ra
rand
ndom
om fu
func
ncti
tion
on ..
.... */
44   direct
direction rand() %   4;   /* an
ion = rand() and d th
then
en ma
make
ke a ra
rand
ndom
om in
init
itia
ial
l di
dire
rect
ctio
ion
n */
45
46   while   ( !k
!key [KEY_ESC] )   /* un
ey[ unti til
l th
thee es
esca
cape
pe ke
keyy is pr
pres
esse
sed
d ..
...
. */
47    {
48   moveBall();   /* mo moveve th the e ba
ball ll */
49 respondToKeyboard();
  /* re resp spon
ondd to kekeyb
yboa
oard
rd in
inpu
put
t */
50   /* now
now, , per
perfor
formm dou
double ble buf buffer fering
ing */
51   clear_to_
clear_to_color
color( ( buffer,
buffer, makecol( makecol(   255,   255,   255   ) );
52   blit(
blit( ball,
ball, buffer
buffer, ,   0,   0, bal ball_x
l_x,, ball_y
ball_y, , bal
ball->
l->w,
w, bal
ball->
l->hh );
53
54 blit(
bli t(
t( bar,
blit(
bli bar
bar,
bar,, buffer
buf
buffer,
buffer
fer, ,    0
, 0,,    0,    0
0, , bar
620 barL_y
L_y,
, barR_y
bar , bar->w
R_y,bar
, ->w,
bar , bar
bar->w
->w,bar->h
->h
, bar
bar->h););
->h
55   blit(
blit( buffer, screen,   0,   0,   0,   0, buffer
buffer, screen, buffer->w
->w,, buf
buffer
fer->h
->h );
56   clear_bit
clear_bitmap(map( buffer
buffer );
57    }   /* enend
d whwhil
ile
e */
58
59   destroy_bi
destroy_bitmap tmap(( ball );   /* de dest stro
royy th
the
e ba
ball
ll bi
bitm
tmap
ap */
60 destroy_bi
destr   tmap( bar ); /* de
oy_bitmap( dest stro
royy th
thee ba
barr bi
bitm
tmap
ap */
61   destroy_bi
destroy_bitmap(tmap( buffer
buffer );   /* de dest
stro
royy th
thee bu
buff
ffer
er bi
bitm
tmap
ap */
62   destroy_sa
destroy_sample(mple( boing );   /* de dest
stro
roy
y th
thee bo
boin
ing
g so
soun
und
d fi
file
le */
63   return   0;
64   }   /* en
end
d fu
func
nctition
on ma
main
in */
65   END_OF_MAIN()   /* do don’
n’t
t foforg rget
et th this is!
! */
66
67    void   moveBall()   /* mo move
ves s th thee ba ball ll */
68   {
69   switch   ( di
dire
rect
ctio
ion n ) {
70   case   DOWN_RIGHT:
71   ++ball_x;   /* momove
ve the ba
the ball
ll to th
the
e ri
righ
ght
t */
72   ++ball_y;   /* momove
ve the
the ba
ball
ll do
down
wn */
73   break;
74   case   UP_RIGHT:
75   ++ball_x;   /* momove
ve the ba
the ball
ll to th
the
e ri
righ
ght
t */
76   --ball_y;   /* momove
ve the
the ba
ball
ll up */
77    break;
78   case   DOWN_LEFT:
79   --ball_x;   /* momove
ve the ba
the ball
ll to th
the
e le
left
ft */
80   ++ball_y;   /* move
move the
the ba
ball
ll do
down
wn */
81   break;
82   case   UP_LEFT:
83   --ball_x;   /* mo
move
ve th
the
e ba
ball
ll to th
the
e le
left
ft */

Fig. E.10   |  Adding paddles and keyboard input. (Part 2 of 5.)

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.7 Key
Keyboa
board
rd Inp
Input
ut   XXIII

84   --ball_y;   /* mo
move
ve th
the
e ba
ball
ll up */
85   break;
86   }   /* end
end sw
swit
itch
ch */
87 
88   /* mak
make
e sure
sure the
the bal
ball
l does
doesn’
n’t
t go off
off scr
scree
een
n */
89
90   /* ifif the
the ball
ball isis goin
going
g off
off the
the top
top or bott
bottom
om ...
... */
*/
91   if   ( ba
ball _y <=   30   || ba
ll_y ball _y >=   440   )
ll_y
92   reverseVerticalDirection();
93
94   /* ifif the
the ball
ball isis goin
going
g off
off the
the left
left or
or righ
right
t ...
... */
95   if   ( ba
ball _x <=   0   || ba
ll_x ball_x >=   600   )
ll_x
96   reverseHorizontalDirection();
97    }   /* end fun
functi
ction
on mov
moveBa
eBall
ll */
98
99 void   respondToKeyboard()   /* res
respon
ponds
ds to key
keyboa
board
rd inp
input
ut */
100 {
101 if   ( key[KEY_A] )   /* if A is be
key[ bein
ing
g pr
pres
esse
sed.
d...
.. */
102 L_y -=   3;   /* ..
barL_y
bar ...
. mo
move
ve th
the
e le
left
ft pa
padd
ddle
le up */
103 if   ( key[KEY_Z] )   /* if Z is be
key[ bein
ing
g pr
pres
esse
sed.
d...
.. */
104 barL_y +=   3;   /* ..
barL_y ...
. mo
move
ve th
the
e le
left
ft pa
padd
ddle
le do
down
wn */

105
106 if   ( key[KEY_UP] )   /* if th
key[ the
e up ar
arro
row
w ke
key
y is be
bein
ing
g pr
pres
esse
sed.
d...
.. */
107  barR_y -=   3;   /* ..
barR_y ...
. mo
move
ve th
the
e ri
righ
ght
t pa
padd
ddle
le up */
108 if   ( key[KEY_DOWN] )   /* if th
key[ the
e do
down
wn ar
arro
row
w ke
key
y is be
bein
ing
g pr
pres
esse
sed.
d...
.. */
109 barR_y +=   3;   /* ..
barR_y ...
. mo
move
ve th
the
e ri
righ
ght
t pa
padd
ddle
le do
down
wn */
110
111 /* mamake
ke su
sure
re ththee pa
paddddle
les
s dodon’
n’t
t go of
offs
fscr
cree
een
n */
112 if   ( ba
barL_y <   30   )   /* if le
rL_y left
ft paddl
paddle
e is go
goin
ing
g of
off
f th
the
e to
top
p */
113 barL_y =   30;
barL_y
114 else
else if   ( ba
barL _y >   380   )   /*
rL_y /* if le
left
ft pa
padd
ddle
le is go
goin
ingg of
offf th
thee bo
bott
ttom
om */
115 barL_y =   380;
barL_y
116 if   ( ba
barR_y <   30   )   /* if ri
rR_y righ
ght
t pa
padd
ddle
le is go
goin
ingg of
off
f th
the
e to
top
p */
117  barR_y =   30;
barR_y
118 else
else if   ( ba
barR _y >   380   )   /* if ri
rR_y righ
ght
t pa
padd
ddle
le is go
goin
ingg of
offf th
thee bo
bott
ttom
om */
119 barR_y =   380;
barR_y
120 }   /* end funct
function
ion respo
respondTo
ndToKeybo
Keyboard
ard */
121
122   void   reverseVerticalDirection()   /* rev revers
ersee the bal
ball’s
l’s up-
up-dow
down
n dir
direct
ection
ion */
123   {
124   if   ( ( didire
rect
ction %   2   ) ==   0   )   /* "do
ion "down"
wn" dir
direct
ection
ions
s are eve
evenn num
number
bers
s */
125   ++direction;   /* ma
makeke th
the e baballll st
star
art
t mo
movi
ving
ng up */
126   else   /* "u"up"
p" di
dire
rectctio
ionsns ar
are e ododd d nu
numb
mber
erss */
127    --direction;   /* ma
makeke th
the e baballll st
star
art
t mo
movi
ving
ng do
down
wn */
128   play_
play_sampl
sample( boing,   255,   128,   1000,   0   );   /* pl
e( boing, play
ay "b
"boi
oing
ng"
" so
soun
und
d on
once
ce */
129   }   /* end funct
function
ion rever
reverseVe
seVertica
rticalDire
lDirection
ction */
130
131   void  reverseHorizontalDirection()   /* rev revers
erses
es the hor
horizo
izonta
ntall dir
direct
ection
ion */
132   {
133   di
dire
rect
ctio
ion
n = ( dir
direc
ecti
tionon +   2   ) %   4;   /* rev
revers
erse
e hor
horizo
izonta
ntal
l dir
direct
ection
ion */
134   play_sample(   boing,   255,   128,   1000,   0   );   /* pl
play
ay "b
"boi
oing
ng"
" so
soun
und
d on
once
ce */
135   }   /* end funct
function
ion rever
reverseHo
seHorizon
rizontalDi
talDirecti
rection
on */

Fig. E.10   |  Adding paddles and keyboard input. (Part 3 of 5.)

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

XXIV    Appendix
Appendix E Game Progra
Programming
mming with the Allegro C Librar
Library
y

Fig. E.10   |  Adding paddles and keyboard input. (Part 4 of 5.)

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.8 Fonts and Displ


Displaying
aying Text   XXV 

Fig. E.10   |  Adding paddles and keyboard input. (Part 5 of 5.)

 You may no notice


tice that we did no nott keep track of the paddles’  x -coordinates
paddles’ x  -coordinates in this pro-
gram. Since the paddles cannot move horizontally, this is not necessary. Each paddle only 
has one 
one   x -coordinate
-coordinate for the duration of the game, so we do not need a variable that
re
reco
cord
rdss tho
those
se valu
valueses.. Al
Also
so,, as with
with the
the ba
ball
ll,, the
the ma
maxiximu
mumm y -coor
- coordi
dina
natete allo
allowe
wed d for
for th
thee pa
pad-
d-
dles is not 480 (the height of the screen); rather, it is 380. This is because the paddles are
100 pixels high, and a   y  y -coordinate
-coordinate of 380 means that the bottom of the paddle is at the
 y -coordinate
-coordinate 480—the bottom of the screen.
Onee ot
On othe
herr th
thin
ingg to no
notitice
ce is th
that
at thou
though gh we lo
loadaded
ed th
thee  bar bi
bitm
tmapap on
onlyly on
once
ce,, we we
were
re
ablee to draw it to the sc
abl scree
reenn in two differ
different
ent pl place
acess sim
simult
ultane
aneousously.
ly. All
Allegr
egroo allows
allows the sam
samee
bitmap to be drawn in many different places, a feature that is useful if you need two iden-
tical bitmaps on the screen at once.
However, at this point, while the paddles can be moved with the keyboard, they do
not have any effect on the ball—it will keep bouncing around the screen regardless of 
 whether or o r no
nott the paddles are in its way. We will deal with this p problem
roblem in Section E.9,
 when we code this feature into our game. For now, we take a look at another Allegro capa-
bility—displaying text on the screen.

E.8 Font
Fontss and Displa
Displaying
ying Text
Text
In almost all games, even the simplest ones, it is necessary for the game to communicate
 with the user in some way. This can range from giving the user instructions while the game
is running, to simply telling the user how many points he or she has scored so far. To do
this, the game developer needs some way of displaying text on the screen so that the player

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

XXVI   Append
Appendix
ix E Game Progra
Programming
mming with the Allegro C Librar
Library
y

can read it. In Allegro, displaying text is handled in a similar way to displaying bitmaps
and playing sounds.
To display text in Allegro, the most important thing we must specify—aside from the
actual text to be displayed, of course—is the font in which it should be displayed. As with
bitmaps and sounds, Allegro can load fonts from external files, and defines a type which
points to the place in memory where these files are stored— FONT*. Loading fonts is done
 with the  load_font  function, which works the same as  load_bitmap  and  load_sample.
Li
Like
kewi
wise
se,, on
once
ce yo
you
u are
are do
done
ne wi
with
th a fo
font
nt,, it mu
must
st be de
dest
stro
roye
yed
d wi
with
th th
thee destroy_font func-
tion to prevent memory leaks. If you wish to load a font from a file, it must be in  .fnt,
.bmp, or  .pcx  format. The parameters of  load_font  are slightly different from those of 
load_bitmap and  load_sample, so we consider its prototype:

FONT *load_fon
*load_font( const
t(   const cha
char
r   *filename
*filename,
, RGB *pal
*palette,
ette,
void   *parameter
*parameter );

The first parameter is, obviously, the filename of the font file that is being loaded. The
second parameter is something we have seen before—a palette. However, as with bitmaps,
if the color depth is not 8-bit,
8-bit, we do not actual
actually
ly have to pass a palette to the function. It
can safely be  NULL  without consequence.
consequence. We will not use the third parame
parameter—i
ter—itt is used
to tell Allegro to load fonts in different ways, which we do not need to do. Like the second
parameter, it can be set to  NULL without causing any problems. Once a font has been load-
ed, you can use the functio
functions
ns in Fig. E.11 to draw text onto a bitmap
bitmap or the screen.

Function prototype Description

void   textprintf_ex(BITMAP
textprintf_ex(BITMAP *bmp, Draws the format control string specified by  fmt
 fmt
const   FONT
FONT *f,   int   x,   int   y, and the parameters following it onto  bmp  at the
int   color,   int   bgColor, specified coordinates. The text is drawn in the
const
const char   *fmt,
char *fmt, ...) specified font and colors, and is left justified.
void   textprintf_centre_ex(  Works
 W orks the same way as   textprintf_ex, but the
BITMAP
BITMAP *bmp,   const   FONT
*bmp, FONT *f, text drawn is center justified
justified at the specified
int   x,   int   y,   int   color, coordinates.
int   bgColor,   const
const char   *fmt,
...)
void   textprintf_right_ex(  Works the same way as   textprintf_ex, but the
 Works
BITMAP
BITMAP *bmp,   const   FONT
*bmp, FONT *f, text drawn is right justified at the specified coor-
int   x,   int   y,   int   color, dinates.
int   bgColor,   const
const char   *fmt,
...)
int   text_length(const   FONT
FONT *f, Returns the width (in pixels) of the specified
Returns specified
cons
const
t char   *string)
char string when drawn in the specified font. Useful
 when aligning
al igning multiple text outputs.
out puts.
int   text_height(const   FONT
FONT *f, Returns the height (in pixels) of the specified
const
const char   *string)
char string when drawn in the specified font. Useful
 when aligning
al igning multiple text outputs.
out puts.

Fig. E.11   |   Functions that are useful for drawing text onto a bitmap.

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.8 Fon
Fonts
ts and
and Displ
Displayi
aying
ng Text
Text   XXVII

(The   allegro.h  header defines a global variable,   font, that contains the data for
 Allegro’s “default” font. This font can be used if you do not have a font file from which to
load. We provide a font file for our Pong game, but this is still a useful feature to know.)
 As you can see, the text output functions have quite a number of parameters. It may 
be useful to take a look at an example of a function call to understand how the function
 works.
textprintf_ex(
textprintf_ex( buffer, font,   0,   0, makeco
buffer, font, l(   0,   0,   0   ),   -1,
makecol(
"Hello!"   );

This function call displays the string  "Hello!"


 "Hello!" at the top-left corner of a buffer (which can
later be drawn onto the screen), using the default font. The text is displayed in black, with
a transparent background color.
The string we pass to the  textprintf_ex  function is a format control string. This
means that we can use any of the conversion specifiers discussed in Chapter 9 to print
ints,  doubles and other variables. This is very useful if, for example, we want to print a 
player’s score, as we will need to do in our Pong game.
 We passed the  bgColor  parameter a value of   -1  in the example call. Allegro cannot
create this color with a call to  makecol, as it interprets the value of   -1  as “no color” or
“transparent.” This means that the text displayed will have no background color and that
anything “behind” the text will be visible.
Normally the default Allegro font is fine when displaying text, but we have provided
the  pongfont.pcx  font file with the appendix examp
examples
les for use with our program. In our
Pong game, we use the functions described above to display the scores of each of the
players. For this reason, we add the  int s,  scoreL and  scoreR, to this itera
iteration
tion of the pro-
gram. Note, however, that since the paddles do not yet do anything, we cannot yet keep
score in the game
game,, and so the valu
values
es of scoreL and scoreR will remain at 0 for the duration
of the program. Nevertheless, Fig. E.12 shows how to use the functions explained previ-
ously to display text on the screen using the font provided on our website.

1   /* Fig. E.12:
E.12: figE_1
figE_12.c
2.c
2   Dis
Displa
playin
ying
g tex
text
t on
on the
the scr
screen
een.
. */
3   #include   <allegro.h>
4
5   /* sym
symbol
bolicic con
consta
stants
nts for the ball’s
ball’s pos
possib
sible
le dir
direct
ection
ions
s */
6   #define   DOWN_RIG
DOWN_RIGHT
HT 0
7    #define   UP_RIGH
UP_RIGHTT 1
8   #define   DOWN_LEF
DOWN_LEFTT 2
9   #define   UP_LEF
UP_LEFT
T 3
10
11   /* functio
function n pro
protot
totype
ypes s */
12   void   moveBall(   void   );
13   void   respondToKeyboard(   void   );
14   void   reverseVerticalDirection(   void   );
15   void  reverseHorizontalDirection(   void   );
16
17    int   ball_x;   /* the bal
ball’s
l’s x-c
x-coor
oordin
dinate
ate */
18   int   ball_y;   /* the ball’s
ball’s y-c
y-coor
oordin
dinate
ate */

Fig. E.12   |   Displa


Displaying
ying text on the screen. (Part 1 of 4.)

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

XXVIII   Append
Appendix
ix E Game Progra
Programming
mming with the Allegro C Librar
Library
y

19   int   barL_y;   /* y- y-co


coor
ordi
dina
nate
te of th
the
e le
left
ft pa
padd
ddle
le */
20   int   barR_y;   /* y- y-co
coor
ordi
dina
nate
te of th
the
e ri
righ
ght
t pa
padd
ddle
le */
21 int   scoreL;
  /* scscor
ore
e of th
the
e le
left
ft pl
play
ayer
er */
22 int   scoreR;
  /* scscor
ore
e of th
the
e ri
righ
ght
t pl
play
ayer
er */
23   int   direction;   /* the bal ball’s
l’s directio
directionn */
24   BITM
BITMAPAP *ball;
*ball;   /* po
poin
inte
ter
r to ba
ball
ll’s
’s im
imag
age
e bi
bitm
tmap
ap */
25   BITM
BITMAPAP *bar;
*bar;   /* poi
pointe
nter
r to pad
paddle
dle’s
’s ima
image
ge bit
bitmap
map */
26   BITM
BITMAPAP *buffer;
*buffer;   /* po
poin
inte
terr to th
the
e bu
buff
ffer
er */
27    SAMP
SAMPLELE *boing;
*boing;   /* po
poin
inte
terr to so
soun
und
d fi
file
le */
28 FONT *pongFont;
*pong
  Font; /* popoin
inte
terr to fo
font
nt fi
file
le */
29
30   int   main(   void   )
31   {
32   /* firs
first,t, set
set up Alle
Allegrgro
o and the
the grap
graphi
hics
cs mode
mode */
*/
33   allegro_init();   /* ini initia
tializ
lize
e All
Allegr
egroo */
34   install_keyboard();   /* in inst
stal
alll th
the
e ke
keyb
yboa
oardrd fo
for
r Al
Alle
legr
gro
o to us
use
e */
35   install_sound(   DIGI_AUTODETECT,   MIDI_AUTODETECT,   NULL   );
36   set_color_depth(   16   );   /* se set
t ththe
e co
colo
lorr dedept
pth
h to 1616-b
-bit
it */
37    set_gfx_mode(   GFX_AUTODETECT,   640,   480,   0,   0   );   /* se sett gr
grap
aphi
hics
cs mo
mode
de */
38   ball
ball = load_b
load_bitm ap(   "ball.bmp",   NULL   );   /* lo
itmap( load
ad th
thee ba
ball
ll bi
bitm
tmap
ap */
39   bar = load_b
load_bitm ap(   "bar.bmp",   NULL);   /* lo
itmap( load
ad th
the
e babar
r bi
bitm
tmap
ap */
40    buffer
buffer==load_sampl
create_bi
creasample(
te_bitmap
tmap( (SCREEN_W,    SCREEN_H );/*
);
41 boing load_ e(   "boing.wav" );   /* lo ad/*
load crea
cr
e eate
the
th soun
so tedbu
undbuff
ffer
er*/
file
file */
42 pongFont
pongF ont = load_font
load_font( "pongfont
(   "pongfont.pcx"
  .pcx", , NULL,   NULL   ); /* lo
load
ad th
the
e fo
font
nt */
43   ba
ball
ll_x
_x = SCSCRE
REEN_W /   2;   /* giv
EN_W give
e the bal
ball l its initial
initial x-c
x-coor
oordin
dinate
ate */
44   ba
ball
ll_y
_y = SCSCRE
REEN_H /   2;   /* giv
EN_H give
e the bal
ball l its initial
initial y-c
y-coor
oordin
dinate
ate */
45   ba
barL
rL_y
_y = SCSCRE
REEN_H /   2;   /* giv
EN_H give
e lef
left t pad
paddle
dle its ini
initia
tial
l y-c
y-coor
oordin
dinate
ate */
46   ba
barR
rR_y
_y = SCSCRE
REEN_H /   2;   /* giv
EN_H give
e rig
rightht pad
paddle
dle its ini
initia
tiall y-c
y-coor
oordin
dinate
ate */
47   
scoreL
scoreL =   0; /* se
set
t le
leftft plplay
ayer
er’s
’s scscor
ore e to 0 */
48 scoreR
scoreR
  =   0; /* se
set
t ri
righghtt pl
play
ayer
er’s
’s scscorore
e to 0 */
49   srand( time(   NULL   ) );   /* se
srand( seed
ed th
the e ra
randndom
om fu
func
ncti
tion
on .....
. */
50   direct
direction rand() %   4;   /* an
ion = rand() and
d th
thenen mamake
ke a ra
rand
ndom
om ininit
itia
ial
l di
dire
rect
ctio
ion
n */
51
52   while   ( !k
!key[KEY_ESC] )   /* un
ey[ unti
til
l th
the
e es
esca
cape
pe ke
key
y is pr
pres
esse
sed
d ..
...
. */
53   {
54   moveBall();   /* mo
move
ve th
the e ba
ball
ll */
55   respondToKeyboard();   /* re respspon
ond
d to kekeyb
yboa
oard
rd ininpu
put t */
56   /* now
now,, per
perfor
form
m dou
double
ble buf
buffer
fering
ing */
57    clear_to_
clear_to_color
color(( buffer, makecol(   255,   255,   255   ) );
buffer, makecol(
58   blit(
blit( ball,
ball, buffer
buffer,,   0,   0, bal
ball_x
l_x,, ball_y
ball_y,, bal
ball->
l->w,w, bal
ball->
l->h h );
59   blit(
blit( bar,
bar, buffer
buffer,,   0,   0,   0, bar
barL_y
L_y,
, bar->w
bar->w,
, bar
bar->h
->h );
60   blit(
blit( bar,
bar, buffer
buffer,,   0,   0,   620, barR_y
barR_y, , bar->w
bar->w, , bar
bar->h
->h );
61   /* dr
draw
aw te
text
xt on
onto
to th
the e bubuff
fferer */
62 textprint
textprintf_ex(
f_ex( buffer, pongFont,   75,   0, mak
buffer, pongFont, makeco l(   0,   0,   0   ),
ecol(
63 -1,   "Left
"Left Pla
Player
yer Sco
Score:
re: %d", sc scor
oreL
eL );
64 textprint
textprintf_ex(
f_ex( buffer, pongFont,   400,   0, mak
buffer, pongFont, makeco
ecol(l(   0,   0,   0   ),
65 -1,   "Right
"Right Pla
Player
yer Sco
Score:
re: %d", scor
scoreR
eR );
66   blit(
blit( buffer, screen,   0,   0,   0,   0, buffer
buffer, screen, buffer->w
->w, , buf
buffer
fer->h
->h );
67    clear_bit
clear_bitmap(
map( buffer
buffer );
68   }   /* en
end
d wh
whil
ile
e */
69
70   destroy_bi
destroy_bitmap
tmap(
( ball );   /* de
dest
stro
roy
y th
the
e ba
ball
ll bi
bitm
tmap
ap */

Fig. E.12   |   Displa


Displaying
ying text on the screen. (Part 2 of 4.)

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.8 Fon
Fonts
ts and
and Displ
Displayi
aying
ng Text
Text   XXIX

71   destroy_bi
destroy_bitmap(
tmap( bar );   /* de
dest
stro
royy th
thee ba
barr bi
bitm
tmap
ap */
72   destroy_bi
destroy_bitmap(
tmap( buffer
buffer );   /* de
dest
stro
royy th
thee bu
buff
ffer
er bi
bitm
tmap
ap */
73   destroy_sa
destroy_sample(
mple( boing );   /* de
dest
stro
roy
y th
the
e bo
boin
ing
g so
soun
und
d fi
file
le */
74 destroy_fo
destr oy_font(
nt(
  pongFont
pongFont ); /* dedest
stro
royy th
thee fo
font
nt */
75   return   0;
76   }   /* en
end
d fu
func
ncti
tion
on ma
main
in */
77    END_OF_MAIN()   /* dodon’
n’t
t fo
forg
rgetet th
this
is!
! */
78
79   void   moveBall()   /* mo
move
ves
s th
the
e ba
ball
ll */
80   {
81   switch   ( di
dire
rect
ctio
ion
n ) {
82   case   DOWN_RIGHT:
83   ++ball_x;   /* mo
move
ve th
the
e ba
ball
ll to th
the
e ri
righ
ght
t */
84   ++ball_y;   /* mo
move
ve th
the
e ba
ball
ll do
down
wn */
85   break;
86   case   UP_RIGHT:
87    ++ball_x;   /* mo
move
ve th
the
e ba
ball
ll to th
the
e ri
righ
ght
t */
88   --ball_y;   /* mo
move
ve th
the
e ba
ball
ll up */
89   break;
90   case   DOWN_LEFT:
91   --ball_x;   /* mo
move
ve th
the
e ba
ball
ll to th
the
e le
left
ft */
92   
++ball_y;   /* mo
move
ve th
the
e ba
ball
ll down
down */
93 break;
94   case   UP_LEFT:
95   --ball_x;   /* momove
ve th
the
e ba
ball
ll to the
the le
left
ft */
96   --ball_y;   /* momove
ve th
the
e ba
ball
ll up */
97    break;
98   }   /* en
end
d swswit
itch
ch */
99
100   /* make
make sure
sure the
the ball
ball doesn
doesn’t
’t go off
off the scre
screen
en */
101
102   /* if the
the ball
ball is goi going
ng off
off the
the top or or botto
bottom
m ...
... */
103   if   ( ba
ball_y <=   30   || ba
ll_y ball_y >=   440   )
ll_y
104   reverseVerticalDirection();
105
106   /* if the
the ball
ball is goi
going
ng off
off the
the left
left or righ
right
t ... */
107    if   ( ba
ball_x <=   0   || ba
ll_x ball_x >=   600   )
ll_x
108   reverseHorizontalDirection();
109   }   /* end funfuncti
ction
on mov
moveBa
eBall
ll */
110
111   void   respondToKeyboard()   /* res
respon
ponds
ds to key
keyboa
board
rd inp
input
ut */
112   {
113   if   ( ke y[KEY_A] )   /* if A is be
key[ bein
ing
g pr
pres
esse
sed.
d...
.. */
114   barL_y -=   3;   /* ..
barL_y ...
. mo
move
ve th
the
e le
left
ft pa
padd
ddle
le up */
115   if   ( ke y[KEY_Z] )   /* if Z is be
key[ bein
ing
g pr
pres
esse
sed.
d...
.. */
116   barL_y +=   3;   /* ..
barL_y ...
. mo
move
ve th
the
e le
left
ft pa
padd
ddle
le do
down
wn */
117 
118   if   ( key[KEY_UP] )   /* if th
key[ the
e up ar
arro
row
w ke
key
y is be
bein
ing
g pr
pres
esse
sed.
d...
.. */
119   barR_y -=   3;   /* ..
barR_y ...
. mo
move
ve th
the
e ri
righ
ght
t pa
padd
ddle
le up */
120   if   ( ke y[KEY_DOWN] )   /* if th
key[ the
e do
down
wn ar
arro
row
w ke
key
y is be
bein
ing
g pr
pres
esse
sed.
d...
.. */
121   barR_y +=   3;   /* ..
barR_y ...
. mo
move
ve th
the
e ri
righ
ght
t pa
padd
ddle
le do
down
wn */
122

Fig. E.12   |   Displa


Displaying
ying text on the screen. (Part 3 of 4.)

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

XXX   Appe
Appendix
ndix E Game Progra
Programming
mming with the Allegro C Librar
Library
y

123   /* make
make sure
sure the
the paddl
paddleses don’
don’tt go offsc
offscre
reen
en */
124   if   ( ba
barL_y <   30   )   /* if le
rL_y left
ft paddl
paddle
e is go
goin
ing
g of
off
f th
thee to
topp */
125   barL_y =   30;
barL_y
126   el else
se if   ( ba
barL _y >   380   )   /*
rL_y /* if le
left
ft pa
padd
ddle
le is go
goin
ingg of
off
f th
thee bo
bott
ttom
om */
127    barL_y =   380;
barL_y
128   if   ( ba barR_y <   30   )   /* if ri
rR_y righ
ght
t pa
padd
ddle
le is go
goin
ingg of
offf th
thee to
top
p */
129   barR_y =   30;
barR_y
130   el else
se if   ( ba
barR _y >   380   )   /* if ri
rR_y righ
ght
t pa
padd
ddle
le is go
goin
ing
g of
offf th
thee bo
bott
ttom
om */
131   barR_y =   380;
barR_y
132   }   /* end funct
function
ion respo
respondTo
ndToKeybo
Keyboardard */
133
134   void   reverseVerticalDirection()   /* rev revers
ersee the bal
ball’s
l’s up-
up-dow
down
n dir
direct
ection
ion */
135   {
136   if   ( ( didire
rect
ction %   2   ) ==   0   )   /* "do
ion "down"
wn" dir
direct
ection
ions
s are eve
evenn num
number
bers
s */
137    ++direction;   /* ma
makeke th
the e baballll st
star
art
t mo
movi
ving
ng up */
138   else   /* "u"up"
p" di
dire
rectctio
ionsns ar
are e ododd d nu
numb
mber
erss */
139   --direction;   /* ma
makeke th
the e baballll st
star
art
t mo
movi
ving
ng do
down
wn */
140   play_
play_sampl
sample( boing,   255,   128,   1000,   0   );   /* pl
e( boing, play
ay "b
"boi
oing
ng"
" so
soun
und
d on
once
ce */
141   }   /* end funct
function
ion rever
reverseVe
seVertica
rticalDire
lDirection
ction */
142
143   void  reverseHorizontalDirection()   /* rev
revers
erses
es the hor
horizo
izonta
ntal
l dir
direct
ection
ion */
144   {  di
145 dire
rect
ctio
ion
n = ( dir
direc
ecti on +   2   ) %   4;   /* rev
tion revers
erse
e hor
horizo
izonta
ntal
l direct
direction
ion */
146   play_
play_sampl
sample( boing,   255,   128,   1000,   0   );   /* pl
e( boing, play
ay "b
"boi
oing
ng"
" so
soun
und
d on
once
ce */
147    }   /* end funct
function
ion rever
reverseHo
seHorizon
rizontalDi
talDirecti
rectionon */

Fig. E.12   |   Displa


Displaying
ying text on the screen. (Part 4 of 4.)

© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.9 Imple
Implementin
menting
g the Game of Pong   XXXI

E.9 Implem
Implementing
enting the Game
Game of
of Pong 
 We now have all of the elements of our Po Pong
ng game in our program—a ball, moving pad-
dles, sounds and a scoreboard. However, these elements are not yet capable of interacting 
 with each other. In this section we tie up the loose ends in our program to make it run like
an actual Pong game.
The weakness
the ball—it in the current
keeps moving version
regardless of our program
of whether or not theis paddles
that theare
paddles
in its don’t yetaddi-
way. In stop
tion, when the ball hits the left or right edge of the screen, it simply bounces instead of 
going off the screen, and the player is not awarded a point.
The method that we use to fix these problems is surprisingly simple. Allegro does not
have any functions that determine whether or not two bitmaps are touching, but since we
know the dimensions of the  ball  and   bar bitmaps, we can easily test if the ball has hit a 
paddle. Since we need to check only whether the paddle is in the way of the ball if the ball
is moving off the left or right of the screen, we can make this check inside the  if  statement
that checks the ball’s x 
ball’s  x -coordinate.
-coordinate.
The only other issue we face is the fact that while we have created a boundary near the
top of the screen that ensures the ball doesn’t move into the scoreboard, there is no visual
indi
in dica
cati
tion
on tha
thatt th
thee bo
boun
undadary
ry is ther
there—
e—the
the ba
ball
ll just
just ap
appea
pears
rs to bou
bouncncee for
for no reas
reason
on.. Wh
Whil
ilee
 we know why this is happening, it may confuse the players.
 We mentioned earlier in the appendix that Allegro can draw simple graphics. In addi-
tion to being able to draw rectangles, circles, and polygons, Allegro has a  line function to
draw a line from one point to another. We can use this function to draw a line where our
boundary is. The prototype for this function follows:
line(BITMAP *bitmap,   int   x1,   int   y1,   int   x2,   int   y2,   int   color)
void   line(BITMAP

This function draws a straight line onto the specified bitmap from the coordinates (x1, y1)
to the coordi
coordinates
nates (x2,  y2 ). The line will be drawn in the given color, which can be spec-
ified by using the  makecol  function. We can now put the finishing touches on our Pong 
game with the code in Fig. E.13.

1   /* Fig. E.13:
E.13: figE_1
figE_13.c
3.c
2   Fi
Fini
nish
shining
g up
up the
the Po
Pong
ng ga
game
me.
. */
*/
3   #include   <allegro.h>
4
5   /* sym
symbol
bolicic con
consta
stants
nts for the ball’s
ball’s pos
possib
sible
le dir
direct
ection
ions
s */
6   #define   DOWN_RIG
DOWN_RIGHT
HT 0
7    #define   UP_RIGH
UP_RIGHTT 1
8   #define   DOWN_LEF
DOWN_LEFTT 2
9   #define   UP_LEF
UP_LEFT
T 3
10
11   /* functio
function n pro
protot
totype
ypes s */
12   void   moveBall(   void   );
13   void   respondToKeyboard(   void   );
14   void   reverseVerticalDirection(   void   );
15
16   void  reverseHorizontalDirection(   void   );

Fig. E.13   |   Finish


Finishing
ing up the Pong game. (Part
(Part 1 of 7.)
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

XXXII   Appen
Appendix
dix E Game Progra
Programming
mming with the Allegro C Librar
Library
y

17    int   ball_x;   /* the bal


ball’s
l’s x-c
x-coor
oordin
dinate
ate */
18   int   ball_y;   /* the bal
ball’s
l’s y-c
y-coor
oordin
dinate
ate */
19   int   barL_y;   /* y-
y-co
coor
ordi
dina
nate
te of th
the
e le
left
ft pa
padd
ddle
le */
20   int   barR_y;   /* y-
y-co
coor
ordi
dina
nate
te of th
the
e ri
righ
ght
t pa
padd
ddle
le */
21   int   scoreL;   /* sc
scor
ore
e of th
the
e le
left
ft pl
play
ayer
er */
22   int   scoreR;   /* sc
scor
ore
e of th
the
e ri
righ
ght
t pl
play
ayer
er */
23   int   direction;   /* the bal
ball’s
l’s directio
directionn */
24   BITM
BITMAPAP *ball;
*ball;   /* po
poin
inte
ter
r to ba
ball
ll’s
’s im
imag
age
e bi
bitm
tmap
ap */
25   BITM
BITMAPAP *bar;
*bar;   /* poi
pointe
nter
r to pad
paddle
dle’s
’s ima
image
ge bit
bitmap
map */
26   BITM
BITMAPAP *buffer;
*buffer;   /* po
poin
inte
terr to th
the
e bu
buff
ffer
er */
27    SAMP
SAMPLELE *boing;
*boing;   /* po
poin
inte
terr to so
soun
und
d fi
file
le */
28   FONT *pongFont;
*pongFont;   /* po
poin
inte
terr to fo
font
nt fi
file
le */
29
30   int   main(   void   )
31   {
32   /* firs
first,t, set
set up Alle
Allegr
groo and the
the grap
graphi
hics
cs mode
mode */ */
33   allegro_init();   /* iniinitia
tializ
lize
e All
Allegr
egroo */
34   install_keyboard();   /* in inst
stal
alll th
the
e ke
keyb
yboa
oard
rd fofor r AlAlle
legr
groo to us
use
e */
35   install_sound(   DIGI_AUTODETECT,   MIDI_AUTODETECT,   NULL   );
36   set_color_depth(   16   );   /* se
set
t th
the
e co
colo
lor
r de
dept
pth h to 16 16-b
-bit
it */
37    set_gfx_mode(   GFX_AUTODETECT,   640,   480,   0,   0   );   /* se
set
t gr
grap
aphi
hics
cs mo
mode
de */
38    ball
bal   "ball.bmp" ,   NULL
39 barl==load_b
load_b
loa
loa d_bitm
d_bitmitmap(
ap(  "bar.bmp"
itmap(
ap( ,   NULL );    );
/*   /* load
lo
load
load adeth
the
th the
erba
bar
ba ball
ll
bitm
bi bitm
bi
aptmap
tmap ap */
*/
40   buffer
buffer = create_bi
create_bitmap
tmap( (SCREEN_W,   SCREEN_H);/* );/* cr
crea
eate
te bu
buff
ffer
er */
41   boing = load_sampl
load_sample( e(   "boing.wav"   );   /* lo load
ad th
the
e so
soun
undd fi
file
le */
42   pongFont load_font(   "pongfon
pongFont = load_font( "pongfont.pcx
t.pcx",", NULL,   NULL   );   /* lo
load
ad th
the
e fo
font
nt */
43   ball_x =   SCREEN_W   /   2;   /* giv
ball_x give
e bal
ball l its ini initia
tial
l x-c
x-coor
oordin
dinate
ate */
44   ball_y =   SCREEN_H   /   2;   /* giv
ball_y give
e bal
ball l its ini initia
tial
l y-c
y-coor
oordin
dinate
ate */
45   barL_y =   SCREEN_H   /   2;   /* giv
barL_y give
e lef
left t pad
paddledle its ini
initia
tiall y-c
y-coor
oordin
dinate
ate */
46   barR_y =   SCREEN_H   /   2;   /* giv
barR_y give
e rig
rightht padpaddle
dle its ini
initia
tiall y-c
y-coor
oordin
dinate
ate */
47    scoreL =   0;   /* se
scoreL set
t leleft
ft pl
play
ayer
er’s’s scscor
ore e to 0 */
48   scoreR =   0;   /* se
scoreR set
t ririgh
ghtt pl
play
ayer
er’s’s scscor
ore e to 0 */
49   srand( time(   NULL   ) );   /* se
srand( seed
ed ththe e ra
rand ndom
om fu
func
ncti
tion
on ..
.... */
50   direct
direction rand() %   4;   /* an
ion = rand() and
d ththenen ma
makeke a rarand
ndom
om in
init
itia
ial
l di
dire
rect
ctio
ion
n */
51
52   while   ( !k
!key[KEY_ESC] )   /* un
ey[ unti
til
l th
the
e es
esca
cape
pe ke
key
y is pr
pres
esse
sed
d ..
...
. */
53   {
54   moveBall();   /* momove
ve ththe e ba
ballll */
55   respondToKeyboard();   /* re respspon
ond
d to ke
keyb
yboa
oard
rd ininpuput t */
56   /* now
now,, per
perfor
form
m dou
doubleble buf
buffer
fering
ing */
57    clear_to_
clear_to_color
color(( buffer, makecol(   255,   255,   255   ) );
buffer, makecol(
58   blit(
blit( ball,
ball, buffer
buffer, ,   0,   0, bal
ball_x
l_x,
, ball_y
ball_y, , bal
ball->
l->w,w, bal
ball->
l->h h );
59   blit(
blit( bar,
bar, buffer
buffer, ,   0,   0,   0, bar
barL_y
L_y,, bar->w
bar->w, , bar
bar->h ->h );
60   blit(
blit( bar,
bar, buffer
buffer, ,   0,   0,   620, barR_y
barR_y,, bar->w
bar->w, , bar
bar->h
->h );
61   line( buffer,   0,   30,   640,   30, makeco
line( buffer, l(   0,   0,   0   ) );
makecol(
62   /* dr
draw
aw te
text
xt on
onto
to th
the e bubuff
fferer */
63   textprint
textprintf_ex(
f_ex( buffer, pongFont,   75,   0, mak
buffer, pongFont, makeco
ecol(l(   0,   0,   0   ),
64   -1,   "Left
"Left Pla
Player
yer ScoScore:
re: %d", scscor
oreL
eL );
65   textprint
textprintf_ex(
f_ex( buffer, pongFont,   400,   0, mak
buffer, pongFont, makeco
ecol( l(   0,   0,   0   ),
66   -1,   "Right
"Right Pla
Player
yer Sco
Score:
re: %d", scor
scoreR
eR );
67    blit(
blit( buffer, screen,   0,   0,   0,   0, buffer
buffer, screen, buffer->w
->w, , buf
buffer
fer->h
->h );
68   clear_bit
clear_bitmap(
map( buffer
buffer );
69   }   /* en
end
d wh
whil
ile
e */

Fig. E.13   |   Finish


Finishing
ing up the Pong game. (Part
(Part 2 of 7.)
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.9 Impl
Implement
ementing
ing the
the Game
Game of Pong
Pong   XXXIII

70
71   destroy_bi
destroy_bitmap
tmap(
( ball );   /* de
dest
stro
royy th
the
e ba
ball
ll bi
bitm
tmap
ap */
72   destroy_bi
destroy_bitmap(
tmap( bar );   /* de
dest
stro
royy th
thee ba
bar
r bi
bitm
tmap
ap */
73   destroy_bi
destroy_bitmap(
tmap( buffer
buffer );   /* de
dest
stro
royy th
thee bu
buff
ffer
er bi
bitm
tmap
ap */
74   destroy_sa
destroy_sample(
mple( boing );   /* de
dest
stro
roy
y th
thee bo
boin
ing
g so
soun
und
d fi
file
le */
75   destroy_fo
destroy_font(
nt( pongFont
pongFont );   /* de
dest
stro
royy th
thee fo
font
nt */
76   return   0;
77    }   /* en
end
d fu
funcncti
tion
on ma
main
in */
78   END_OF_MAIN()   /* dodon’
n’t
t fo
forg
rget
et th
this
is!
! */
79
80   void   moveBall()   /* mo
move
ves
s th
the
e ba
ball
ll */
81   {
82   switch   ( di
dire
rect
ctio
ion
n ) {
83   case   DOWN_RIGHT:
84   ++ball_x;   /* mo
move
ve th
the
e ba
ball
ll to th
the
e ri
righ
ght
t */
85   ++ball_y;   /* mo
move
ve th
the
e ba
ball
ll do
down
wn */
86   break;
87    case   UP_RIGHT:
88   ++ball_x;   /* mo
move
ve th
the
e ba
ball
ll to th
the
e ri
righ
ght
t */
89   --ball_y;   /* mo
move
ve th
the
e ba
ball
ll up */
90   break;

91   case   DOWN_LEFT:
92  
--ball_x;   /* move th
move the
e ba
ball
ll to th
the
e le
left
ft */
93  
++ball_y;   /* move
move th
the
e ba
ball
ll do
down
wn */
94  
break;
95   case   UP_LEFT:
96   --ball_x;   /* move th
move the
e ba
ball
ll to th
the
e le
left
ft */
97    --ball_y;   /* move
move th
the
e ba
ball
ll up */
98   break;
99   }   /* en
end
d swswit
itch
ch */
100
101   /* if the
the ball
ball is goi going
ng off
off the
the top or or bot
botto
tom
m ...
... */
102   if   ( ba
ball_y <=   30   || ba
ll_y ball_y >=   440   )
ll_y
103   reverseVerticalDirection();   /* make make it go the the ot
othe
her
r wa
way
y */
104
105 /* if th
the
e ba
ball
ll is in ra
rang
nge
e of th
the
e le
left
ft pa
padd
ddle
le ..
...
. */
106 if   (ball_x
(ball_x <   20   && (direc
(directio
tion n ==   DOWN_LEFT   || direct ion ==   UP_LEFT))
direction
107  {
108 /* is th the
e le
left
ft pa
padd
ddle
le in th the e wa
way?
y? */
109 if   ( ba
bal
ll_
l_yy > ( bar
arL_
L_y y -   39   ) && ball
ball_y
_y < ( barL _y +   99   ) )
barL_
110 reverseHorizontalDirection();
111 else
else if   ( baball _x <=   -20   ) {   /* if th
ll_x the
e ba
ball
ll go
goes
es of
offf th
thee scscre
reen
en */
112 ++scoreR;   /* gi
give
ve ririghght
t plplay
ayer
er a po
poin
int
t */
113 l_x =   SCREEN_W   /   2;   /* pl
ball_x
bal plac
acee th
thee ba
ball
ll in th
thee ..
.... */
114 l_y =   SCREEN_H   /   2;   /
ball_y
bal /*
* ..
...
. ce
cent
nter
er of the scre
screen
en */
115 direct
dir ection rand() %   4;   /* gi
ion = rand() give
ve th
the
e ba
ball
ll a ra
rand
ndom
om di
dire
rectctio
ion
n */
116 }   /* en
end
d el
else
se */
117  }   /* enend
d if */
118
119 /* if ththe
e ba
ball
ll is in ra rang
nge
e of ththe
e ri
righ
ght
t pa
padd
ddle
le ... */
120 if   (ball_x
(ball_x >   580   && (direc
(directio n ==   DOWN_RIGHT   || direct
tion ion ==   UP_RIGHT))
direction
121 {

Fig. E.13   |   Finish


Finishing
ing up the Pong game. (Part
(Part 3 of 7.)
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

XXXIV    Appendix
Appendix E Game Progra
Programming
mming with the Allegr
Allegro
o C Libra
Library
ry

122 /* is th the
e ri
righ
ght
t pa
padd
ddlele in th the
e wa
way?
y? */
123 if   ( ba
bal
ll_
l_yy > ( bar
arR_
R_y y -   39   ) && ball
ball_y
_y < ( barR _y +   99   ) )
barR_
124 reverseHorizontalDirection();
125 else
else if   ( baball _x >=   620   ) {   /* if th
ll_x the
e ba
ball
ll go
goes
es of
offf th
thee scscre
reen
en */
126 ++scoreL;   /* gi
give
ve leleftft plplay
ayer
er a po
poin
int
t */
127  l_x =   SCREEN_W   /   2;   /* pl
ball_x
bal plac
acee th
thee ba
ball
ll in th
thee ..
.... */
128 l_y =   SCREEN_H   /   2;   /
ball_y
bal /*
* ..
...
. ce
cent
nter
er of the scre
screen
en */
129 direct
dir ection rand() %   4;   /* gi
ion = rand() give
ve th
the
e ba
ball
ll a ra
rand
ndom
om di
dire
rectctio
ion
n */
130 }   /* en
end
d el
else
se */
131 }   /* enend
d if */
132   }   /* end fun functi
ction
on mov
moveBa
eBall
ll */
133
134   void   respondToKeyboard()   /* res
respon
ponds
ds to key
keyboa
board
rd inp
input
ut */
135   {
136   if   ( ke y[KEY_A] )   /* if A is be
key[ bein
ing
g pr
pres
esse
sed.
d...
.. */
137    barL_y -=   3;   /* ..
barL_y ...
. mo
move
ve th
the
e le
left
ft pa
padd
ddle
le up */
138   if   ( ke y[KEY_Z] )   /* if Z is be
key[ bein
ing
g pr
pres
esse
sed.
d...
.. */
139   barL_y +=   3;   /* ..
barL_y ...
. mo
move
ve th
the
e le
left
ft pa
padd
ddle
le do
down
wn */
140
141   if   ( key[KEY_UP] )   /* if th
key[ the
e up ar
arro
row
w ke
key
y is bein
being
g pr
pres
esse
sed.
d...
.. */
142   barR_y -=   3;   /* ..
barR_y ...
. mo
move
ve th
the
e ri
righ
ght
t pa
padd
ddle
le up */
143  
144   if   barR_y
( ke
bar y[KEY_DOWN
key[
R_y ] ..
+=   3;   /* ) .
/*mo
... if
veth
movethe
eedo
the
th down
wn
righ
ri arro
ar
t row
ght w
padd
pa key
ke
leydo
ddle is
wnbe
downbein
ing
*/ g pr
pres
esse
sed.
d...
.. */
145
146   /* make
make sure
sure the
the paddl
paddleses don’
don’tt go offsc
offscre
reen
en */
147    if   ( ba
barL_y <   30   )   /* if le
rL_y left
ft paddl
paddle
e is go
goin
ing
g of
off
f th
thee to
topp */
148   barL_y =   30;
barL_y
149   el else
se if   ( ba
barL _y >   380   )   /*
rL_y /* if le
left
ft pa
padd
ddle
le is go
goin
ingg of
off
f th
thee bo
bott
ttom
om */
150   barL_y =   380;
barL_y
151   if   ( ba barR_y <   30   )   /* if ri
rR_y righ
ght
t pa
padd
ddle
le is go
goin
ingg of
offf th
thee to
top
p */
152   barR_y =   30;
barR_y
153   el else
se if   ( ba
barR _y >   380   )   /* if ri
rR_y righ
ght
t pa
padd
ddle
le is go
goin
ing
g of
offf th
thee bo
bott
ttom
om */
154   barR_y =   380;
barR_y
155   }   /* end funct
function
ion respo
respondTo
ndToKeybo
Keyboardard */
156
157    void   reverseVerticalDirection()   /* rev
revers
erse
e the bal
ball’s
l’s up-
up-dow
down
n dir
direct
ection
ion */
158   {
159   if   ( ( di
dire
rect
ction %   2   ) ==   0   )   /* "do
ion "down"
wn" dir
direct
ection
ions
s are eve
even
n num
number
bers
s */
160   ++direction;   /* ma
makeke th
the e baballll st
star
art
t mo
movi
ving
ng up */
161   else   /* "u "up"
p" di
dire
rectctio
ionsns ar
are e ododd d nu
numb
mber
erss */
162   --direction;   /* ma
makeke th
the e baballll st
star
art
t mo
movi
ving
ng do
down
wn */
163   play_
play_sampl
sample( boing,   255,   128,   1000,   0   );   /* pl
e( boing, play
ay "b
"boi
oing
ng"
" so
soun
und
d on
once
ce */
164   }   /* end funct
function
ion rever
reverseVe
seVertica
rticalDire
lDirection
ction */
165
166   void  reverseHorizontalDirection()   /* rev revers
erses
es the hor
horizo
izonta
ntall dir
direct
ection
ion */
167    {
168   di dire
rect
ctio
ion
n = ( dir
direc
ecti on +   2   ) %   4;   /* rev
tion revers
erse
e hor
horizo
izonta
ntal
l dir
direct
ection
ion */
169   play_
play_sampl
sample( boing,   255,   128,   1000,   0   );   /* pl
e( boing, play
ay "b
"boi
oing
ng"
" so
soun
und
d on
once
ce */
170   }   /* end funct
function
ion rever
reverseHo
seHorizon
rizontalDi
talDirecti
rectionon */

Fig. E.13   |   Finish


Finishing
ing up the Pong game. (Part
(Part 4 of 7.)
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.9 Imple
Implementi
menting
ng the
the Game
Game of Pong
Pong   XXXV 

Fig. E.13   |   Finish


Finishing
ing up the Pong game. (Part
(Part 5 of 7.)
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

XXXVI   Appen
Appendix
dix E Game Progra
Programming
mming with the Allegr
Allegro
o C Libra
Library
ry

Fig. E.13   |   Finish


Finishing
ing up the Pong game. (Part
(Part 6 of 7.)
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.1
E.10
0 Tim
Timers
ers in Alle
Allegro
gro   XXXVII

Fig. E.13   |   Finish


Finishing
ing up the Pong game. (Part
(Part 7 of 7.)

 You may wonder why we chose the boundaries that we did for checking if the paddle
is touching the ball. In order for the ball to “bounce” off a paddle, at least 1 pixel of the
ball must be touching (i.e., immediately adjacent to) the paddle. Thus, If  ball_y  is 39
smaller than  barL_y, the bottommost pixel of the ball is touching the bar, and if  ball_y
is 99 greater than  barL_y, the topmost pixel is touching.
 With this version of the program, our Pong game is now fully functional, but there
are still a few improvements we can make. The first of these improvements is using timers
to regulate
regulate the speed of the game, a topic we discuss in the next section.

E.10 Time
Timers
rs in Alle
Allegro
gro
One missing feature of our Pong game is the ability to regulate the game’s speed. At the
moment, the main process of our game in Fig. E.13 is contained in a  while loop. Howev-
er, this is not a good practice, as the speed at which a program executes varies from system
to system based on factors such as the processor speed
speed.. As such our while  loop could op-
erate at varying speeds depending on the system on which we are running our game, mak-
ing our ball and paddles move faster or slower than we may want. In this section, we
Allegro timers to
introduce Allegro timers  to help regulate the speed of our game.
 We install the timer handler for Allegro to use by calling the function install_timer,
 which takes no parameters. Once we have called the  install_timer function, we can add
timerss to our program
timer program.. This is done by calling the  install_int function. The prototype
for this function is:
int   install_int(   void   ( *funct
*function )(),   int   interval
ion )(), interval );
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

XXXVIII   Appen
Appendix
dix E Game Progra
Programming
mming with the Allegro C Libra
Library
ry

 You’ll notice that the  function parameter is a function pointer. Calling the  install_int
function adds a timer to your program that calls the function specified by  function every 
interval  milliseconds. Thus, if we wanted to call a function  timedFunction  once every 
second, we would add the following code:
install_int( timedFunction,   1000   );

There is no need to store a newly-installed timer in a variable—the timer will automatically 


star
startt ru
runn
nniningg in th
thee ba
back
ckgr
grou
ound
nd of the
the prog
progra
ram
m an
and
d will
will rema
remain
in runn
runnin
ingg un
unti
till it is remo
remove
ved
d
or the program ends. Also, Allegro only identifies a timer by the function it is set to call.
Calling  install_timer
  install_timer and passing it a function that already has a timer tied to it does not
create a new timer; instead, it simply changes the old timer’s speed to the one specified by 
the  interval  parameter. Likewise, removing a timer is done by calling the   remove_timer
function and passing it the name of the function to which the timer is tied.
 Allegro allows only 16 timers to be running at once regardless of the system being 
used. If we try to add more, the  install_int  function fails and returns a non-zero value.
Generally, though, you should avoid using an excessive number of timers, as some Allegro
processes also require timers to work, and they take up the same slots as regular timers.
None of the Allegro functions we have discussed so far require timers, but some of the
functions
and MIDIdiscussed in Section
music files—do E.12—specifically,
need them. the functions that play  .fli
 .fli animations

The final step for everything to work correctly is to add the  volatile  qualifier dis-
cussed in Chapte
Chapterr 14 to any varia
variable
ble whose value might be cchange
hangedd by our timer
timers.
s. Becau
Because
se
 Allegro is an external library, compilers ccannot
annot recognize what the  install_int function
does. For this reason, the compiler may not “understand” that a variable can be modified
by a timer, and it may attempt to optimize the main program code by loading the vari-
able’s value into one of the computer’s registers, thus failing to notice when that value
change
cha nges.
s. Add
Adding
ing the volatile quali
qualifier
fier to a vari
variable
able th
that
at can be modifie
modified
d by a time
timerr warns
the compiler that this value may change unexpecte
unexpectedly,
dly, so it must gene
generate
rate code that cor-
rectly reloads the latest value from memory.
 We can now add timers to our Pong game to regulate how quickly our ball and pad-
dles move on the screen (Fig. E.14).

1   /* Fig. E.14:
E.14: figE_1
figE_14.c
4.c
2   Ad
Addi
ding
ng titime
mers
rs to th
the
e Pon
Pong
g game
game.
. */
3   #include   <allegro.h>
4
5   /* sym
symbol
bolicic con
consta
stants
nts for the ball’s
ball’s pos
possib
sible
le dir
direct
ection
ions
s */
6   #define   DOWN_RIG
DOWN_RIGHT
HT 0
7    #define   UP_RIGH
UP_RIGHTT 1
8   #define   DOWN_LEF
DOWN_LEFTT 2
9   #define   UP_LEF
UP_LEFT
T 3
10
11   /* functio
function n pro
protot
totype
ypes s */
12   void   moveBall(   void   );
13   void   respondToKeyboard(   void   );
14   void   reverseVerticalDirection(   void   );
15   void  reverseHorizontalDirection(   void   );

Fig. E.14   |   Adding timers


timers to the Pong game.
game. (Part 1 of 5.)
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.1
E.10
0 Tim
Timers
ers in All
Allegro
egro   XXXIX

16
17  volatile
  int   ball_x;   /* the balball’s
l’s x-c
x-coor
oordin
dinate
ate */
18 volatile
  int   ball_y;   /* the balball’s
l’s y-c
y-coor
oordin
dinate
ate */
19 volatile
  int   barL_y;   /* y- y-co
coor
ordi
dina
nate
te of th
thee le
left
ft pa
padd
ddle
le */
20 volatile
  int   barR_y;   /* y- y-co
coor
ordi
dina
nate
te of th
thee ri
righ
ght
t pa
padd
ddle
le */
21 volatile
  int   scoreL;   /* sc scor
ore
e of th
thee le
left
ft pl
play
ayer
er */
22 volatile
  int
23 volatile
  int    direction;
scoreR;   /*   sc
scor
/*ore
e of
the the
th e ri
ball’s
bal l’srigh
ght
t
direct
dir play
player
ection
ioner
*/*/
24   BITM
BITMAP
AP *ball;
*ball;   /* po
poin
inteter
r to baball
ll’s
’s im
imag
age
e bi
bitm
tmap
ap */
25   BITM
BITMAP
AP *bar;
*bar;   /* poi
pointe
nter r to pad
paddle
dle’s
’s ima
image
ge bit
bitmap
map */
26   BITM
BITMAP
AP *buffer;
*buffer;   /* po
poininte
ter r to th
the
e bu
buff
ffer
er */
27    SAMP
SAMPLE
LE *boing;
*boing;   /* po
poin
inteter r to so
soun
und
d fi
file
le */
28   FONT *pongFont;
*pongFont;   /* po
poininte
ter r to fo
font
nt fi
file
le */
29
30   int   main(   void   )
31   {
32   /* firs
first,t, set
set up Alle
Allegr
gro
o and the
the grap
graphi
hics
cs mode
mode */
*/
33   allegro_init();   /* iniinitia
tializ
lizee All
Allegr
egro
o */
34   install_keyboard();   /* in inst
stal
all
l th
the
e ke
keyb
yboa
oard
rd fo
for
r Al
Alle
legr
gro
o to us
use
e */
35   install_sound(   DIGI_AUTODETECT,   MIDI_AUTODETECT,   NULL   );
36 install_timer();
  /* in
inst
stal
all
l th
the
e ti
time
mer
r ha
hand
ndle
ler
r */
37    set_color_depth(   16   );   /* seset
t th
the
e co
colo
lor
r de
dept
pth
h to 1616-b
-bit
it */
38   set_gfx_mode(   GFX_AUTODETECT,   640,   480,   0,   0   );   /* se
set t gr
grap
aphi
hics
cs mo
mode
de */
39   ball
ball = load_b
load_bitm ap(   "ball.bmp",   NULL   );   /* lo
itmap( load
ad ththe
e baball
ll bi
bitm
tmap
ap */
40   bar = load_b
load_bitm ap(   "bar.bmp",   NULL);   /* lo
itmap( load
ad th
the
e babar
r bibitm
tmap
ap */
41   buffer
buffer = create_bi
create_bitmap
tmap( (SCREEN_W,   SCREEN_H);/*
);/* cr
creaeate
te bubuff
ffer
er */
42   boing = load_sampl
load_sample( e(   "boing.wav"   );   /* lo
load
ad th
the
e sosoun
und d fi
file
le */
43   pongFont load_font(   "pongfon
pongFont = load_font( "pongfont.pcx
t.pcx",
", NULL,   NULL   );   /* lo
load
ad th
the
e fo
font
nt */
44   ball_x =   SCREEN_W   /   2;   /* giv
ball_x give
e bal
ball
l its iniinitia
tial
l x-c
x-coor
oordin
dinate
ate */
45   ball_y =   SCREEN_H   /   2;   /* giv
ball_y give
e bal
ball
l its iniinitia
tial
l y-c
y-coor
oordin
dinate
ate */
46   barL_y =   SCREEN_H   /   2;   /* giv
barL_y give
e lef
left
t pad
paddle
dle its ini
initia
tial l y-c
y-coor
oordin
dinate
ate */
47    barR_y =   SCREEN_H   /   2;   /* giv
barR_y give
e rig
right
ht pad
paddle
dle its ini
initia
tial l y-c
y-coor
oordin
dinate
ate */
48   scoreL =   0;   /* se
scoreL set
t leleft
ft pl
play
ayer
er’s
’s sc
scor
oree to 0 */
49   scoreR =   0;   /* se
scoreR set
t ririgh
ghtt pl
play
ayer
er’s
’s sc
scorore
e to 0 */
50   srand( time(   NULL   ) );   /* se
srand( seed
ed th
the
e ra
rand
ndom
om fu
func
ncti
tionon ..
... . */
51   direct
direction rand() %   4;   /* an
ion = rand() and
d th
then
en mamake
ke a ra
rand
ndom
om ininititia
ial
l di
dire
rect
ctio
ion
n */
52 /* ad
add
d ti
time
mer
r that
that ca
call
lls
s momoveveBa
Ball
ll ev
ever
ery
y 5 mi
mill
llis
isec
econ
onds
ds */
53 install_int( moveBall,   5   );
54 /* add tim
timer
er that
that cal
calls
ls res
responpondTo
dToKey
Keyboa
board
rd eve
every
ry 10 mil
millis
liseco
econds
nds */
55 install_int( respondToKeyboard,   10   );
56
57    while   ( !k
!key [KEY_ESC] )   /* un
ey[ untitil
l th
the
e es
esca
cape
pe ke
key y is pr pres
essesed
d ..... . */
58   {
59   /* now
now,
, per
perfor
form
m dou
doubleble buf
buffer
fering
ing */
60   clear_to_
clear_to_color
color( buffer, (   255,   255,   255   ) );
( buffer,
61   blit(
blit( ball,
ball, buffer
buffer, ,   0,   0, bal
ball_x
l_x,
, ball_y
ball_y, , bal
ball->
l->w,w, bal
ball->
l->h h );
62   blit(
blit( bar,
bar, buffer
buffer, ,   0,   0,   0, bar
barL_y
L_y,
, bar->w
bar->w, , bar
bar->h ->h );
63   blit(
blit( bar,
bar, buffer
buffer, ,   0,   0,   620, barR_y
barR_y,
, bar->w
bar->w, , bar
bar->h
->h );
64   line( buffer,   0,   30,   640,   30, makeco
line( buffer, l(   0,   0,   0   ) );
makecol(
65   /* drdraw
aw tetext
xt on
onto
to th
the e bubuff
fferer */
66   textprint
textprintf_ex(
f_ex( buffer, pongFont,   75,   0, mak
buffer, pongFont, makeco
ecol(l(   0,   0,   0   ),
67    -1,   "Left
"Left Pla
Player
yer ScoScore:
re: %d", sc scor
oreL
eL );

Fig. E.14   |   Adding timers


timers to the Pong game.
game. (Part 2 of 5.)
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

XL    Appendix
Appendix E Game Progra
Programming
mming with the Allegr
Allegro
o C Libra
Library
ry

68   textprint
textprintf_ex(
f_ex( buffer, pongFont,   400,   0, mak
buffer, pongFont, makecol(   0,   0,   0   ),
ecol(
69  
-1,   "Right
"Right Pla
Player
yer Sco
Score:
re: %d", scor scoreR
eR );
70   blit(
blit( buffer, screen,   0,   0,   0,   0, buffer
buffer, screen, buffer->w
->w,
, buf
buffer
fer->h
->h );
71   clear_bit
clear_bitmap(
map( buffer
buffer );
72   }   /* en
end
d wh
whilile
e */
73
74
75 remov
remove_int
remov e_int(
remove_int
e_int((
( moveBall
moveB
respoall
respondTo );   /*ard
ndToKeybo
Keyboardremove
remove  /*
); moveBa
mov eBall
ll tim
remove
rem ove timer
er
respon
res */
pondTo
dToKey
Keyboa
board
rd tim
timer
er */
76   destroy_bi
destroy_bitmap
tmap(
( ball );   /* de
dest
stro
roy y th
the
e ba
ball
ll bi
bitm
tmap
ap */
77    destroy_bi
destroy_bitmap(
tmap( bar );   /* de
dest
stro
royy th
thee ba
bar
r bi
bitm
tmap
ap */
78   destroy_bi
destroy_bitmap(
tmap( buffer
buffer );   /* de
dest
stroroyy th
thee bu
buff
ffer
er bi
bitm
tmap
ap */
79   destroy_sa
destroy_sample(
mple( boing );   /* de
dest
stro
royy th
thee bo
boin
ing
g so
soun
und
d fi
file
le */
80   destroy_fo
destroy_font(
nt( pongFont
pongFont );   /* de
dest
stroroyy th
thee fo
font
nt */
81   return   0;
82   }   /* en
end
d fu
func
ncti
tion
on ma
main
in */
83   END_OF_MAIN()   /* dodon’
n’t
t fo
forg
rgetet th
this
is!
! */
84
85   void   moveBall()   /* mo
move
ves
s th
the
e ba
ball
ll */
86   {
87    switch   ( di
dire
rect
ctio
ion
n ) {
88   case   DOWN_RIGHT:
89   ++ball_x;   /* move th
move the
e ba
ball
ll to th
the
e ri
righ
ght
t */
90   ++ball_y;   /* move
move th
the
e ba
ball
ll do
down
wn */
91   break;
92   case   UP_RIGHT:
93   ++ball_x;   /* move th
move the
e ba
ball
ll to th
the
e ri
righ
ght
t */
94   --ball_y;   /* move
move th
the
e ba
ball
ll up */
95   break;
96   case   DOWN_LEFT:
97    --ball_x;   /* move th
move the
e ba
ball
ll to th
the
e le
left
ft */
98   ++ball_y;   /* move
move th
the
e ba
ball
ll do
down
wn */
99   break;
100   case   UP_LEFT:
101   --ball_x;   /* move th
move the
e ba
ball
ll to th
the
e le
left
ft */
102   --ball_y;   /* move
move th
the
e ba
ball
ll up */
103   break;
104   }   /* en
end
d sw
swit
itch
ch */
105
106   /* if the
the ball
ball is goi going
ng off
off the
the top or or bot
botto
tom
m ...
... */
107    if   ( ba
ball_y <=   30   || ba
ll_y ball_y >=   440   )
ll_y
108   reverseVerticalDirection();   /* make make it go the the ot
othe
her
r wa
way
y */
109
110   /* if the the ball
ball is in in range
range of the the left
left padd
paddle
le ...
... */
111   if   (ball_
(ball_x x <   20   && (direc
(directio
tion n ==   DOWN_LEFT   || direct ion ==   UP_LEFT))
direction
112   {
113   /* is ththe
e leleft
ft papadd
ddle
le in th the
e way
way?? */
114   if   ( ba
ball
ll_y
_y > ( ba barL
rL_y_y -   39   ) && ball_
all_yy < ( barL _y +   99   ) )
barL_y
115   reverseHorizontalDirection();
116   else
else if   ( baball
ll_x_x <=   -20   ) {   /* if th
the
e ba
ball
ll go
goes
es of
offf th
thee scscre
reen
en */
117    ++scoreR;   /* gigive
ve ririgh
ght t pl
playayer
er a po
poin
int
t */
118   ball_x =   SCREEN_W   /   2;   /* pl
ball_x plac
acee th
thee ba
ball
ll in th
the
e ..
.... */
119   ball_y =   SCREEN_H   /   2;   /
ball_y /*
* .....
. ce
cent
nter
er of the scre
screen
en */

Fig. E.14   |   Adding timers


timers to the Pong game.
game. (Part 3 of 5.)
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.1
E.10
0 Tim
Timers
ers in All
Allegr
egro
o   XLI

120   direct
direction rand() %   4;   /* gi
ion = rand() give
ve th
the
e ba
ball
ll a ra
rand
ndom
om di
dire
rect
ctio
ion
n */
121   }   /* en
end
d el
else
se */
122   }   /* enend
d if */
123
124   /* if the
the ball
ball is in range
range of the
the right
right padd
paddle
le ...
... */
125   if   (ball_x >   580   && (direc
(ball_x (direction ==   DOWN_RIGHT   || direct
tion ion ==   UP_RIGHT))
direction
126
127      { /* is th thee ri
righ
ght
t pad
paddl
dlee in th thee way
way?? */
128   if   ( ba
ball
ll_y
_y > ( ba
barR _y -   39   ) && ball_
rR_y all_yy < ( barR _y +   99   ) )
barR_y
129   reverseHorizontalDirection();
130   else
el se if   ( ba
ball_x >=   620   ) {   /* if th
ll_x the
e ba
ball
ll go
goes
es of
offf th
thee scscre
reen
en */
131   ++scoreL;   /* gi
give
ve le
leftft plplay
ayer
er a po
poin
int
t */
132   ball_x =   SCREEN_W   /   2;   /* pl
ball_x plac
acee th
thee ba
ball
ll in th
the
e ..
.... */
133   ball_y =   SCREEN_H   /   2;   /
ball_y /*
* ..
...
. ce
cent
nter
er of the scre
screen
en */
134   direct
direction rand() %   4;   /* gi
ion = rand() give
ve th
thee ba
ball
ll a ra
rand
ndom
om didire
rectctio
ion
n */
135   }   /* en
end
d el
else
se */
136   }   /* en end
d if */
137    }   /* end fun
functi
ction
on mov
moveBa
eBall
ll */
138
139   void   respondToKeyboard()   /* res
respon
ponds
ds to key
keyboa
board
rd inp
input
ut */
140   {
141   if   ( key[KEY_A] )   /* if A is be
key[ bein
ing
g pr
pres
esse
sed.
d...
.. */
142   barL_y -=   3;   /* ..
barL_y ...
. mo
move
ve th
the
e le
left
ft pa
padd
ddle
le up */
143   if   ( ke y[KEY_Z] )   /* if Z is be
key[ bein
ing
g pr
pres
esse
sed.
d...
.. */
144   barL_y +=   3;   /* ..
barL_y ...
. mo
move
ve th
the
e le
left
ft pa
padd
ddle
le do
down
wn */
145
146   if   ( key[KEY_UP] )   /* if th
key[ the
e up ar
arro
row
w ke
key
y is be
bein
ing
g pr
pres
esse
sed.
d...
.. */
147    barR_y -=   3;   /* ..
barR_y ...
. mo
move
ve th
the
e ri
righ
ght
t pa
padd
ddle
le up */
148   if   ( ke y[KEY_DOWN] )   /* if th
key[ the
e do
down
wn ar
arro
row
w ke
key
y is be
bein
ing
g pr
pres
esse
sed.
d...
.. */
149   barR_y +=   3;   /* ..
barR_y ...
. mo
move
ve th
the
e ri
righ
ght
t pa
padd
ddle
le do
down
wn */
150
151   /* make
make sure
sure the
the paddl
paddleses don’
don’tt go offsc
offscre
reen
en */
152   if   ( ba
barL_y <   30   )   /* if le
rL_y left
ft paddl
paddle
e is go
goin
ing
g of
off
f th
the
e to
top
p */
153   barL_y =   30;
barL_y
154   elelse
se if   ( ba
barL _y >   380   )   /*
rL_y /* if le
left
ft pa
padd
ddle
le is go
goin
ing
g of
off
f th
the
e bo
bott
ttom
om */
155   barL_y =   380;
barL_y
156   if   ( ba
barR_y <   30   )   /* if ri
rR_y righ
ght
t pa
padd
ddle
le is go
goin
ing
g of
off
f th
the
e to
top
p */
157    barR_y =   30;
barR_y
158   el else
se if   ( ba
barR _y >   380   )   /* if ri
rR_y righ
ght
t pa
padd
ddle
le is go
goin
ing
g of
off
f th
the
e bo
bott
ttom
om */
159   barR_y =   380;
barR_y
160   }   /* end funct
function
ion respo
respondTo
ndToKeybo
Keyboard
ard */
161
162   void   reverseVerticalDirection()   /* rev revers
ersee the bal
ball’s
l’s up-
up-dow
down
n dir
direct
ection
ion */
163   {
164   if   ( ( didire
rect
ction %   2   ) ==   0   )   /* "do
ion "down"
wn" dir
direct
ection
ions
s are eve
evenn num
number
bers
s */
165   ++direction;   /* ma
makeke th
the e baballll st
star
art
t mo
movi
ving
ng up */
166   else   /* "u"up"
p" di
dire
rectctio
ionsns ar
are e ododd d nu
numb
mber
erss */
167    --direction;   /* ma
makeke th
the e baballll st
star
art
t mo
movi
ving
ng do
down
wn */
168   play_
play_sampl
sample( boing,   255,   128,   1000,   0   );   /* pl
e( boing, play
ay "b
"boi
oing
ng"
" so
soun
und
d on
once
ce */
169   }   /* end funct
function
ion rever
reverseVe
seVertica
rticalDire
lDirection
ction */
170
171   void  reverseHorizontalDirection()   /* rev
revers
erses
es the hor
horizo
izonta
ntal
l dir
direct
ection
ion */
172   {

Fig. E.14   |   Adding timers


timers to the Pong game.
game. (Part 4 of 5.)
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

XLII   Appendix
Appendix E Game Progra
Programming
mming with the Allegro C Libra
Library
ry

173   di dire
rect
ctio
ion
n = ( dir
direc
ecti on +   2   ) %   4;   /* rev
tion revers
erse
e hor
horizo
izonta
ntal
l direct
direction
ion */
174   play_
play_sampl
sample( boing,   255,   128,   1000,   0   );   /* pl
e( boing, play
ay "b
"boi
oing
ng"
" so
soun
und
d on
once
ce */
175   }   /* end funct
function
ion rever
reverseHo
seHorizon
rizontalDi
talDirecti
rectionon */

Fig. E.14   |   Adding timers


timers to the Pong game.
game. (Part 5 of 5.)

The calls to the   moveBall   and  respondToKeyboard  have been removed from the
while loop in the  main  of this version of the program.
 As you can see, timers are simple to implement. With the code in Fig. E.14, the move-
Ball  function is call
called
ed once every 5 mill
millisecon
iseconds,
ds, or 200 times per second
second,, which means
our
our ball
ball will
will mo
moveve as ma
many
ny pi
pixe
xels
ls ev
ever
eryy secon
second.
d. Li
Like
kewi
wise
se,, the prog
progra
ram
m call
callss respondToKey-
board  every 10 milliseconds, or 100 times per second, which means (since the  respond-
ToKeyboard function moves the paddles in intervals of 3 pixels) that the paddles can move
300 pixels in one second. However, while these are the speeds we have suggested for these
two timers, feel free to change them so that the game runs at the speed you desire. Exper-
imentation
iment ation is the only real way to deter
determine
mine a speed that is best for the game.

E.11 The Grabber


Grabber and Allegro
Allegro Datafiles
Datafiles
Because most of Allegro’s graphics and sounds come from external files, it is necessary for
each program to load the files it needs, and to destroy them when the program is finished
to prevent memory leaks. When we have a small number of external files, as we do in our
Pong game, loading and destroying every file is not a difficult task. However, what if we
had a large number of files that we needed to load? Not only would it be difficult to re-
member every single file that we had to load and destroy, but we would also have to dis-
tribute
tribute every one of these exte
external
rnal files with
with our game if we ch
chose
ose to release
release it to the publi
public.
c.
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.11 The Grabb


Grabber
er and
and Allegro
Allegro Dataf
Datafiles
iles   XLIII

Fortunately, the Allegro designers foresaw this problem, and to fix it, they created the
datafile.
datafile. A dataf
datafililee is a si
singl
nglee ex
exter
terna
nall fi
file,
le, cre
create
ated
d by All
Alleg
egro,
ro, tha
thatt holds
holds tthe
he data
data of m
mult
ultipl
iplee
external files in one place. A program can load a datafile and instantly have access to all of 
the files—be they bitmaps, sounds, fonts or anything else—that the datafile contains.
Thee Al
Th Alle
legr
groo dire
directctor
oryy con
conta
tain
inss a too
tool,l, kn own as the grabber , th
known that
at we can
can use
use to imp
mporortt
external files and create datafiles. In this section we use the grabber to create a datafile out
of the bitmaps and sounds we used in our Pong game, then we use that datafile to reduce
the number of lines in our program.
To cre
creat
atee a da data
tafi
file
le,, we must
must fi firs
rstt ope
open
n the
the grab
grabbe
ber.
r. On Wi Windndow
ows,
s, it is the
grabber.exe program in the  tools  directory of the tools and examples zip file. On other
systems, you should just be able to run “ grabber” from the command line. Run the
grabber and the screen in Fig. E.15 should appear.

Fig. E.15   |  Allegro’s grabber utility.

There are four main areas of the grabber program’s window. The top area, which con-
tains several text fields, is the space that displays the properties of the datafile that is cur-
rently being
being modified
modified.. The white box on the left side of the window lists the objects that
make up the datafile being edited; since we haven’t yet created any objects, the box is cur-
rently empty. Once we import images and sounds into our datafile, the right side of the
screen will be used to display the properties of a selected object.
 While there are many items in the grabber’s menus, we need only a few of them to
create a datafile. To add any object to a datafile, we must first tell the grabber to create a 
new space in the datafile for the given object. We do this by selecting   New  in the   Object
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

XLIV    Appendix
Appendix E Game Progra
Programming
mming with the Allegro C Libra
Library
ry

menu. A list of object types appears. The first thing we import is our ball bitmap, so select
Bitmap  and a dialog box appears asking for the object’s name. Name it  BALL  (the reason
 why the name should be in all caps will become clear shortly). Your screen should now 
look like Fig. E.16.

Fig. E.16   |   Adding a bitmap


bitmap to a datafile.

BALL has been added to the list of objects on the left side of the window, and that the
ri
righ
ghtt side
side of th
thee wind
window
ow nonoww conta
containinss in
info
form
rmatatio
ion
n on the ob
obje
ject
ct.. Ho
Howe
weve
ver,
r, our
our ob
obje
ject
ct ha
hass
no image data yet. To import data from a bitmap file, we must first select  Read Bitmap
from the File menu. The program asks where the bitmap file is located, so navigate to your
Pongg pr
Pon proje
oject
ct fold
folder
er an
and
d im
impor
portt our
our ball.bmp imag image.
e. When th
this
is is do
done,
ne, the imag
imagee appear
appearss
in the window to confirm that it was loaded correctly.
Click anywhere in the window and the screen in Fig. E.16 reappears. The   Read
Bitmap menu item did not actually give our  BALL object any image data—it merely loaded
the image into the grabber’s internal memory. To actually apply the bitmap data to our
object, make
make sur
suree that the BALL object is selected on the left side of the window, then select
Grab  from the  Object menu. The screen in Fig. E.17 appears.
Thee prog
Th progra
ramm no
noww as
asks
ks us wh
whic
ich
h pa
partrt of the
the bitm
bitmap
ap we wa
want
nt th
thee ob
obje
ject
ct to cont
contai
ain.
n. Th
This
is
feature is useful if we want our object to contain only part of an image, but right now we
 want the entirety of the ball bitmap. Move the cursor to the top-left corner of the image,
then click and drag a box over the entire bitmap. The screen in Fig. E.18 should appear.
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.11 The Grabbe


Grabberr and Allegro Dataf
Datafiles
iles   XLV 

Fig. E.17   |  Applying an imported bitmap to an object.

Fig. E.18   |  A complete imported object.


© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

XLVI   Appen
Appendix
dix E Game Progra
Programming
mming with the Allegro C Libra
Library
ry

 With this done, we have finished importing our ball image into the datafile. Create a 
new bitmap in the grabber called  BAR  and repeat the process with the  bar.bmp  bitmap to
import the paddle image as well. Both the  BALL and  BAR  objects should now be in the list
of items on the left side of the window.
Now that we have imported our bitmaps, we must also import our sound and font
files. First, use the  Object menu to create a new object of type  Sample named BOING. Then,
simply select  Grab from the  Object menu. The program asks for the location of the file, so
locate our  boing.wav file and double-click on it. The grabber then imports the sound file
and applies its data to the  boing object.
 We use the same process to create our font object—create a new font called PONGFONT,
and then use   Grab  to import the  pongfont.pcx  file. Once you have imported all the
objects, your screen should look like Fig. E.19.

Fig. E.19   |  The grabber window after importing all of our objects.

Now that we’ve imported all our objects into the grabber, there is still one final step
 we must perform before we can use the datafile effectively. You will notice that we have
not yet done anything with the text fields at the top of the grabber window. However, the
Header   field
field is of interest to us. Filling in this field with a filename will make the grabber
save a header file alongside the datafile that we are currently creating. This header file can
be used to make it easier to access individual datafile objects in a program. We will discuss
the header file in more detail shortly, but for now just enter  pong.h in the text field. Then
select   Save  from the   File  menu and save the datafile as  pongdatafile.dat  in the folder
 where your Pong proj project
ect is located.
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.11 The Grabbe


Grabberr and Allegr
Allegro
o Datafile
Datafiless   XLVII

Now we face the task of loading the datafile into our program, which is not difficult.
 Just as Allegro defines BITMAP*,  SAMPLE*, and  FONT* pointer types for bitmaps, sounds and
fonts, it also defines the  DATAFILE* type
 type that
 that points to datafiles. Likewise, to load a datafile
datafile
into a program, we call the function load_datafile and pass it the filename of the datafile
 we have created. Note,
Note, though, that Allegr
Allegroo does not define a function  destroy_datafile.
To free the memory allocated to a datafile, one must call the function   unload_datafile.
Once a datafile is loaded into a program, Allegro considers it to be an array of objects,
 with each object having a specific index in the array. If we have a  DATAFILE*
  DATAFILE*  variable in
our program called  myDatafile, accessing a specific object in the datafile is done with the
code  myDatafile[i].dat, where   i  is the object’s index in the array. Normally, Allegro
assigns indexes to the objects in a datafile by the order in which the objects were imported,
so in our datafile, our  BALL object has index 0, our  BAR  object has index 1, and so on.
It is easy for us to remember the indexes of the objects in our datafile, as it contains
only four objects. However, with a large datafile, remembering the indexes of each and
every object can be difficult. Fortunately, even with our small datafile, we do not have to
memorize each object’s index, as the  pong.h header file we saved takes care of that for us.
If you open the header file in your IDE, you will see the code in Fig. E.20.

1   /* Allegro
Allegr o dat
datafi
afile
le obj
object
ect indexes,
indexes, produced
produced by gra
grabbe
bber
r v4.
v4.2.2
2.2,
, Min
MinGW3
GW32
2 */
2   /* Datafile:
Datafile: c:\ex
c:\example
amples\ap
s\appE\po
pE\pongdat
ngdatafile
afile.dat
.dat */
3   /* Date: Mon Aug 10 16:59:
Date: 16:59:35
35 2009
2009 */
4   /* Do not
not hand
hand edit!
edit! */
5
6   #define   BALL 0   /* BMP */
7    #define   BAR 1   /* BMP */
8   #define   BOING 2   /* SAMP
SAMP */
9   #define   PONGFONT 3   /* FONT
FONT */

Fig. E.20   |   The  pong.h header file.

By including the header file in our program, we eliminate the need to memorize the
indexes of the objects in our datafile, as the header file assigns a symbolic constant to each
index. The symbolic constant for any given object is the name we gave that object in the
grabber when we imported it, which explains why we chose to name our objects in all
caps—the convention for symbolic constants in C is to give them names with only capital
letters. The Pong program in Fig. E.21 loads and accesses a datafile

1   /* Fig. E.21:
E.21: figE_2
figE_21.c
1.c
2   Usi
Using
ng dat
datafi
afiles
les.
. */
3   #include   <allegro.h>
4 #include   "pong.h"
5
6   /* sym
symbol
bolicic con
consta
stants
nts for the ball’s
ball’s pos
possib
sible
le dir
direct
ection
ions
s */
7   #define   DOWN_RIG
DOWN_RIGHT
HT 0
8   #define   UP_RIGH
UP_RIGHTT 1
9   #define   DOWN_LEF
DOWN_LEFTT 2
10   #define   UP_LEF
UP_LEFT
T 3

Fig. E.21   |  Using datafiles. (Part 1 of 5.)


© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

XLVIII   Appen
Appendix
dix E Game Progra
Programming
mming with the Allegro C Libra
Library
ry

11
12   /* functio
function n pro
protot
totype
ypes s */
13   void   moveBall(   void   );
14   void   respondToKeyboard(   void   );
15   void   reverseVerticalDirection(   void   );
16   void  reverseHorizontalDirection(   void   );

17 
18   volatile int   ball_x;   /* the bal
volatile ball’s
l’s x-c
x-coor
oordin
dinate
ate */
19   volatile
volatile int   ball_y;   /* the bal
ball’s
l’s y-c
y-coor
oordin
dinate
ate */
20   volatile
volatile int   barL_y;   /* y-
y-co
coor
ordi
dina
nate
te of th
thee le
left
ft pa
padd
ddle
le */
21   volatile
volatile int   barR_y;   /* y-
y-co
coor
ordi
dina
nate
te of th
thee ri
righ
ght
t pa
padd
ddle
le */
22   volatile
volatile int   scoreL;   /* sc
scor
ore
e of th
the
e le
left
ft pl
play
ayer
er */
23   volatile
volatile int   scoreR;   /* sc
scor
ore
e of th
the
e ri
righ
ght
t pl
play
ayer
er */
24   volatile
volatile int   direction;   /* the bal
ball’s
l’s dir
direct
ection
ion */
25   BITM
BITMAP
AP *buffer;
*buffer;   /* po
poininte
ter
r to ththe
e bu
buff
ffer
er */
26 DATAFILE  *pongData; /* po poin
inte
ter
r to th
thee da
data
tafi
file
le */
27 
28   int   main(   void   )
29   {
30   /* firs
first,t, set
set up Alle
Allegr
gro
o and the
the grap
graphi
hics
cs mode
mode */
*/
31   allegro_init();   /* iniinitia
tializ
lize
e All
Allegr
egro
o */
32   install_keyboard();   /* in inst
stal
all
l th
the
e ke
keyb
yboa
oard
rd fo
for r Al
Alle
legr
groo to us
use
e */
33   install_sound(   DIGI_AUTODETECT,   MIDI_AUTODETECT,   NULL   );
34   install_timer();   /* in inst
stalalll th
the
e ti
time
merr ha
hand
ndle
ler
r */
35   set_color_depth(   16   );   /* se set
t th
the
e co
colo
lorr de
dept
pth
h to 1616-b
-bit
it */
36   set_gfx_mode(   GFX_AUTODETECT,   640,   480,   0,   0   );   /* se
set
t gr
grap
aphi
hics
cs mo
mode
de */
37    buffer
buffer = create_bi
create_bitmap
tmap( (   SCREEN_W,   SCREEN_H   );   /* cre
create
ate buf
buffer
fer */
38 pongData
pongData = load_data
load_datafile(
file(
    "pongdatafile.dat"   ); /* lo load
ad th
thee da
data
tafi
file
le */
39   ball_x =   SCREEN_W   /   2;   /* giv
ball_x give
e bal
ball
l its ini
initia
tial l x-c
x-coor
oordin
dinate
ate */
40   ball_y =   SCREEN_H   /   2;   /* giv
ball_y give
e bal
ball
l its ini
initia
tial l y-c
y-coor
oordin
dinate
ate */
41   barL_y =   SCREEN_H   /   2;   /* giv
barL_y give
e lef
left
t pad
paddle
dle its ini
initia
tial
l y-c
y-coor
oordin
dinate
ate */
42   barR_y =   SCREEN_H   /   2;   /* giv
barR_y give
e rig
right
ht pad
paddle
dle its ini
initia
tiall y-c
y-coor
oordin
dinate
ate */
43   scoreL =   0;   /* se
scoreL set
t le
left
ft pl play
ayer
er’s
’s sc
scor
ore
e to 0 */
44   scoreR =   0;   /* se
scoreR set
t ri
righ
ght t pl
play
ayer
er’s
’s sc
scor
oree to 0 */
45   srand( time(   NULL   ) );   /* se
srand( seed
ed th
the
e ra
rand
ndom
om fu
func
nctition
on ..
...
. */
46   direct
direction rand() %   4;   /* an
ion = rand() and
d th
then
en ma
make
ke a ra
rand
ndom
om in
init
itia
ial
l di
dire
rect
ctio
ion
n */
47    /* add
add timer
timer that
that call
calls s moveB
moveBal
alll every
every 5 milli
milliseseco
cond
nds
s */
48   install_int( moveBall,   5   );
49   /* add timer
timer that
that calls
calls respon
respondTo
dToKey
Keyboa
board
rd every
every 10 millis
milliseco
econds
nds */
50   install_int( respondToKeyboard,   10   );
51
52   while   ( !k
!key [KEY_ESC] )   /* un
ey[ unti
til l th
the
e es
escacape
pe kekey y is pr presessesed
d .....
. */
53   {
54   /* now
now,
, per
perfor
formm dou
double
ble buf buffer
fering
ing */
55   clear_to_
clear_to_color
color(( buffer, makecol(   255,   255,   255   ) );
buffer, makecol(
56 blit(
blit pongData[BALL].dat
( pongData[ ].dat, buffer,   0,   0, bal
, buffer, ball_x
l_x, , ball_y
ball_y, ,   40,   40   );
57  blit(
blit pongData[BAR].dat
( pongData[ ].dat, buffer,   0,   0,   0, bar
, buffer, barL_y
L_y, ,   20,   100   );
58 blit(
blit pongData[BAR].dat
( pongData[ ].dat, buffer,   0,   0,   620, bar
, buffer, barR_y R_y, ,   20,   100   );
59   line( buffer,   0,   30,   640,   30, makeco
line( buffer, makecol(l(   0,   0,   0   ) );
60   /* drdraw
aw te
text
xt on
ontoto ththe e bu
buffffer
er */
61 textprint
text printf_ex(
f_ex( buffer, pongData[PONGFONT].dat,   75,   0,
buffer, pongData[
62 makecol(   0,   0,   0   ),   -1,   "Left
"Left Pla
Player
yer Sco
Score:
re: %d", scor scoreLeL );

Fig. E.21   |  Using datafiles. (Part 2 of 5.)


© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.11 The Grabbe


Grabberr and Allegr
Allegro
o Datafile
Datafiless   XLIX

63 textprintf_ex(
textprintf_ex( buffer, pongData[PONGFONT].dat,   400,   0,
buffer, pongData[
64 makecol(   0,   0,   0   ),   -1,   "Right
"Right Pla
Player
yer Sco
Score:
re: %d", scor
scoreR
eR );
65   blit(
blit( buffer, screen,   0,   0,   0,   0, buffer
buffer, screen, buffer->w
->w,
, buf
buffer
fer->h
->h );
66   clear_bit
clear_bitmap(
map( buffer
buffer );
67    }   /* en
end
d wh
whil
ile
e */
68

69
70    remove_int
remov
remove_int(
remove_int
e_int((
( moveBall
moveB
respoall );
respondToK   /* rd
ndToKeyboa
eyboardremove
remove  /*
); moveBa
mov eBall
ll tim
remove
remove timer
er
respon
res */
pondTo
dToKey
Keyboa
board
rd tim
timer
er */
71   destroy_bi
destroy_bitmap(
tmap( buffer
buffer );   /* de
dest
stroroyy th
the
e bu
buff
ffer
er bi
bitm
tmap
ap */
72 unload_dat
unloa  
d_datafile
afile( pongData ); /* unl
( pongData unload
oad the dat
datafi
afile
le */
73   return   0;
74   }   /* en
end
d fu
func
ncti
tionon ma
main
in */
75   END_OF_MAIN()   /* do don’
n’t
t fo
forg
rgetet th
this
is!
! */
76
77    void   moveBall()   /* mo
move
ves
s th
the
e ba
ball
ll */
78   {
79   switch   ( di
dire
rect
ctio
ion
n ) {
80   case   DOWN_RIGHT:
81   ++ball_x;   /* mo
move
ve th
the
e ba
ball
ll to th
the
e ri
righ
ght
t */
82   ++ball_y;   /* mo
move
ve th
the
e ba
ball
ll do
down
wn */
83   break;
84  
case   UP_RIGHT:
85  
++ball_x;   /* move th
move the
e ba
ball
ll to th
the
e ri
righ
ght
t */
86  
--ball_y;   /* move
move th
the
e ba
ball
ll up */
87  break;  
88   case   DOWN_LEFT:
89   --ball_x;   /* move th
move the
e ba
ball
ll to th
the
e le
left
ft */
90   ++ball_y;   /* move
move th
the
e ba
ball
ll do
down
wn */
91   break;
92   case   UP_LEFT:
93   --ball_x;   /* move th
move the
e ba
ball
ll to th
the
e le
left
ft */
94   --ball_y;   /* move
move th
the
e ba
ball
ll up */
95   break;
96   }   /* en
end
d swswit
itch
ch */
97 
98   /* ifif the
the ball
ball isis goin
going
g off
off the
the top
top or bott
bottom
om ...
... */
*/
99   if   ( ba
ball _y <=   30   || ba
ll_y ball _y >=   440   )
ll_y
100   reverseVerticalDirection();   /* make make it go th
the
e ot
othe
her
r wa
way
y */
101
102   /* if the the ball
ball is in in range
range of the the left
left padd
paddle
le ...
... */
103   if   (ball_
(ball_x x <   20   && (direc
(directio
tion n ==   DOWN_LEFT   || direct ion ==   UP_LEFT))
direction
104   {
105   /* is th thee le
left
ft papadd
ddle
le in th the
e way
way?? */
106   if   ( ba
ball
ll_y
_y > ( ba barL
rL_y_y -   39   ) && ball_
all_yy < ( barL _y +   99   ) )
barL_y
107    reverseHorizontalDirection();
108   else
el se if   ( ba
ball
ll_x_x <=   -20   ) {   /* if th
the
e ba
ball
ll go
goes
es of
offf th
thee scscre
reen
en */
109   ++scoreR;   /* gi give
ve ririgh
ght t pl
playayer
er a po
poin
int
t */
110   ball_x =   SCREEN_W   /   2;   /* pl
ball_x plac
acee th
thee ba
ball
ll in th
the
e ..
.... */
111   ball_y =   SCREEN_H   /   2;   /
ball_y /*
* .....
. ce
cent
nter
er of the scre
screen
en */
112   direct
direction rand() %   4;   /* gi
ion = rand() give
ve th
thee ba
ball
ll a ra
rand
ndom
om didire
rectctio
ion
n */
113   }   /* en
end
d el
else
se */
114   }   /* enend
d if */
115

Fig. E.21   |  Using datafiles. (Part 3 of 5.)


© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

L    Appendix
Appendix E Game Progra
Programming
mming with the Allegr
Allegro
o C Libra
Library
ry

116   /* if the the ball


ball is in range
range of the
the right
right padd
paddle
le ...
... */
117    if   (ball_
(ball_x x >   580   && (direc
(directio
tion n ==   DOWN_RIGHT   || direction ==   UP_RIGHT))
direction
118   {
119   /* is ththe
e ririgh
ght t pad
paddl
dle
e in ththe e way
way?
? */
120   if   ( ba
ball
ll_y
_y > ( ba barR_y -   39   ) && ball_
rR_y all_y
y < ( barR _y +   99   ) )
barR_y
121   reverseHorizontalDirection();
122
123     el
elsese if   ( ba
++scoreL; ball
ll_x_xgi
  /* ve  620
>=
give  ) {
left
left   /*
play
pl ifath
ayer
er the
eint
poin
po ball
ba
tll
*/go
goes
es of
offf th
thee sc
scre
reen
en */
124   ball_x =   SCREEN_W   /   2;   /* pl
ball_x plac
acee th
thee ba
ball
ll in th
the
e ..
...
. */
125   ball_y =   SCREEN_H   /   2;   /
ball_y /** ..
...
. ce
cent
nter
er of the scre
screen
en */
126   direct
direction rand() %   4;   /* gi
ion = rand() give
ve th
thee ba
ball
ll a ra
rand
ndom
om di
dire
rect
ctio
ion
n */
127    }   /* en
end
d elelse
se */
128   }   /* en end
d if */
129   }   /* end fun
functi
ctionon mov
moveBa
eBall
ll */
130
131   void   respondToKeyboard()   /* res
respon
ponds
ds to key
keyboa
board
rd inp
input
ut */
132   {
133   if   ( ke y[KEY_A] )   /* if A is be
key[ bein
ing
g pr
pres
esse
sed.
d...
.. */
134   barL_y -=   3;   /* ..
barL_y ...
. mo
move
ve th
the
e le
left
ft pa
padd
ddle
le up */
135   if   ( ke y[KEY_Z] )   /* if Z is be
key[ bein
ing
g pr
pres
esse
sed.
d...
.. */
136   barL_y +=   3;   /* ..
barL_y ...
. mo
move
ve th
the
e le
left
ft pa
padd
ddle
le do
down
wn */
137 
138   if   ( key[KEY_UP] )   /* if th
key[ the
e up ar
arro
row
w ke
key
y is be
bein
ing
g pr
pres
esse
sed.
d...
.. */
139   barR_y -=   3;   /* ..
barR_y ...
. mo
move
ve th
the
e ri
righ
ght
t pa
padd
ddle
le up */
140   if   ( ke y[KEY_DOWN] )   /* if th
key[ the
e do
down
wn ar
arro
row
w ke
key
y is be
bein
ing
g pr
pres
esse
sed.
d...
.. */
141   barR_y +=   3;   /* ..
barR_y ...
. mo
move
ve th
the
e ri
righ
ght
t pa
padd
ddle
le do
down
wn */
142
143   /* make
make sure
sure the
the paddl
paddleses don’
don’tt go offsc
offscre
reen
en */
144   if   ( ba
barL_y <   30   )   /* if le
rL_y left
ft paddl
paddle
e is go
goin
ing
g of
off
f th
thee to
topp */
145   barL_y =   30;
barL_y
146   el else
se if   ( ba
barL _y >   380   )   /*
rL_y /* if le
left
ft pa
padd
ddle
le is go
goin
ingg of
off
f th
thee bo
bott
ttom
om */
147    barL_y =   380;
barL_y
148   if   ( ba barR_y <   30   )   /* if ri
rR_y righ
ght
t pa
padd
ddle
le is go
goin
ingg of
offf th
thee to
top
p */
149   barR_y =   30;
barR_y
150   el else
se if   ( ba
barR _y >   380   )   /* if ri
rR_y righ
ght
t pa
padd
ddle
le is go
goin
ing
g of
offf th
thee bo
bott
ttom
om */
151   barR_y =   380;
barR_y
152   }   /* end funct
function
ion respo
respondTo
ndToKeybo
Keyboardard */
153
154   void   reverseVerticalDirection()   /* rev revers
ersee the bal
ball’s
l’s up-
up-dow
down
n dir
direct
ection
ion */
155   {
156   if   ( ( didire
rect
ction %   2   ) ==   0   )   /* "do
ion "down"
wn" dir
direct
ection
ions
s are eveevenn num
number
bers
s */
157    ++direction;   /* ma
makeke th
the e baballll st
star
art
t mo
movi
ving
ng up */
158   else   /* "u"up"
p" di
dire
rectctio
ionsns ar
are e ododd d nu
numb
mber
erss */
159   --direction;   /* ma
makeke th
the e baballll st
star
art
t mo
movi
ving
ng do
down
wn */
160 play_sample( pongData[BOING   ].dat,   255,   128,   1000,   0   ); /* pl
play
ay so
soun
undd */
161   }   /* end funct
function
ion rever
reverseVe
seVertica
rticalDire
lDirection
ction */
162
163   void  reverseHorizontalDirection()   /* rev revers
erses
es the hor
horizo
izonta
ntall dir
direct
ection
ion */
164   {
165   di dire
rect
ctio
ion
n = ( dir
direc
ection +   2   ) %   4;   /* rev
tion revers
erse
e hor
horizo
izonta
ntal
l dir
direct
ection
ion */
166 play_sample( pongData[BOING
  ].dat,   255,   128,   1000,   0   ); /* pl
play
ay so
soun
und
d */
167    }   /* end funct
function
ion rever
reverseHo
seHorizon
rizontalDi
talDirecti
rectionon */

Fig. E.21   |  Using datafiles. (Part 4 of 5.)


© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

E.12 Other Allegr


Allegro
o Capab
Capabilitie
ilitiess   LI

Fig. E.21   |  Using datafiles. (Part 5 of 5.)

 A downside of datafiles can be seen in lines 56–58. When we blitted our ball and
paddle onto the screen, we had to pass the last two parameters (the  width  and  height  of 
the source bitmap) explicitly. Allegro considers objects loaded from a datafile to be of type
void *, which cannot be dereferenced. As such, trying to pass these parameters   pong-
Data[BALL].dat->w and  pongData[BALL].dat->h  is a syntax error. Still, since we know 
the exact dimensions of our bitmaps, this is not a problem.
Using our datafile had no effect on the game itself—it runs exactly the same as the
program of Fig. E.14. However, this program requires fewer lines of code for the same
functionali
functionality.
ty. While it is only 8 lines in this case, a game with a larg
larger
er number of object
objectss
in a datafile would most likely have a much larger difference. If you create a game with
many bitmaps, sounds, and other files, make sure to use a datafile to reduce your pro-
gram’s length.

E.12 Other Allegr


Allegro
o Capabilit
Capabilities
ies
 We mentioned several times in this appendix that Allegro is capable of drawing simple
graphics; we used  line  functions to draw a line in our game. Allegro can also draw many 
other shapes, such as triangles
triangles,, circles, arcs and polygons with an arbitrary number of sides.
The full list of these functions is at   www.allegro.cc/manual/api/drawing-primitives/.
 Allegro also has a set of functions devoted solely to playing music using MIDI files. It
defines a   MIDI*   type that points to MIDI files, and uses the   load_midi,   play_midi,
stop_midi and  destroy_midi functions to manipulate them. A full list of these functions
is at   www.allegro.cc/manual/api/music-routine s-(midi)/.
www.allegro.cc/manual/api/music-routines-(midi)/
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

LII   Append
Appendix
ix E Game Progra
Programming
mming with the Allegr
Allegro
o C Libra
Library
ry

If you have any  .fli


  .fli format animations that you would like to include in your game,
 Allegro can play them, as well. Allegro does not define a type that points to animations,
but it can draw an animation directly onto a bitmap using the  play_fli  function. The
documentation for this capability is at   www.allegro.cc/manual/api/flic-routines/
www.allegro.cc/manual/api/flic-routines/.

E.13 Allegro Resou


Resource rce Cente
Center  r 
For more information on Allegro, visit the Allegro and C Game Programming section of 
our C resource center at   www.deitel.com/allegro/
www.deitel.com/allegro/.

Summary 
Section E.3 A Simple Allegro Program
• Every Allegro
Allegro program
program must
must include
include the  allegro.h  header, call the  allegro_init function, and
must have a call to the   END_OF_MAIN  macro immediately following the closing brace of the pro-
gram’s  main  function.
• The   allegro_init  function initializes the Allegro library. It must be called before any other Al-
legro functions, or the program will not work correctly.
• The   allegro_message function is used to give the user a message when there is no graphical way 
of doing so.
• Windows
Windows,, some
some Unix systems,
systems, and Mac OS X cannot
cannot run Allegro
Allegro program
programss wit
withou
houtt the
END_OF_MAIN  macro. If it is missing, compilers on those systems will not be able to compile an
 Allegro program. Make sure to include the  END_OF_MAIN macro to ensure compatibility with sys-
tems that require it.

Section E.4 Simple Graphics: Importing Bitmaps and Blitting 


• Most of Allegro’s graphics
graphics come from external files. Allegro defi
defines
nes several different variabl
variablee
types that point to image data in memory.
• The  BITMAP*  type is the most basic type defined by Allegro
Allegro for pointing
pointing to stored image
image data in
memory.
• The   set_color_depth  function is used to set the color depth of an Allegro program. The color
depth can be set to 8-, 15-, 16-, 24-, or 32-bit.
32-bit. A lower color depth
depth requires less memory, but a 
higher color depth results in a better-looking program.
• The  set_gfx_mode  function is used to set the graphics mode of an Allegro program. In addition
to setting how the program is displayed (i.e., fullscreen mode or windowed mode), it also sets
how many pixels are in the width and height of the screenscreen or window.
window.
• Allegro
Allegro defines five “magic
“magic drivers”
drivers” that can be passed to the   set_gfx_mode  function to specify 
 whether the program should be run in fullscreen or windowed mode—GFX_AUTODETECT,
GFX_AUTODETECT_FULLSCREEN ,   GFX_AUTODETECT_WINDOWED,  GFX_SAFE, and  GFX_TEXT.
• Most
Most Allegro
Allegro functio
functions
ns that can fail
fail return
return   ints for error-checking purposes. Generally these
functions
functio ns will return 0 if they succeed, and a non-zero value if they do not.
• An Allegro program must set the color depth and graphics mode of a program before attempting 
to do anything else with graphics.
• The  create_bitmap  function creates a new, blank bitmap.
• Use
Use the  load_bitmap function to load an image from an external
external bitmap file. If the color depth
is set to 8-bit, you must pass this function
function the bitmap’s
bitmap’s palette in addition to the image itself.
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

Summary   LIII

• If the
the  load_bitmap function fails, it returns  NULL. It does not cause an error.
• The  blit  function is one of the most important functions in Allegro. It is used to draw a block 
from one bitmap onto another bitmap.
• A larger
larger x 
 x -coordinate
-coordinate corresponds to further to the right in Allegro, but a larger y 
larger y -coordinate
-coordinate cor-
responds to further down, not up.
  BITMAP*  struct   int  w  h
• The
the width and type is aof
height pointer to a  in pixels,
the bitmap . This structure
vely. contains two
respectively.
respecti s,  and , that store
• Use
Use the destroy_bitmap function to destroy a bitmap and free the memory allocated to it to pre-
vent memory leaks.

Section E.5 Animation with Double Buffering 


• Animation
Animation in Allegro is done by blitting an object
object onto the screen in different plac
places
es at regular
intervals.
• The symbolic
symbolic constants
constants   SCREEN_W  and   SCREEN_H  are reserved by Allegro, and correspond to the
 width and height of the screen in pixels,
pixel s, respectively.
• Use
Use the
the  clear_to_color function to make the entirety of a bitmap a certain color. This is useful
for setting a background color for a program.
• The  makecol  function is used to return  int s that Allegro recognizes as various colors.
• The “double buffering”
buffering” technique
technique is a method that produces smooth
smooth animation. The techn
technique
ique
consists of drawing everything onto an intermediary bitmap known as the buffer, and then draw-
ing the entirety of the buffer onto the screen.

Section E.6 Importing and Playing Sounds 


• Allegro
Allegro defines
defines the
the type
type  SAMPLE*  that points to sound file data stored in memory.
memory.
• Before any
any sounds
sounds can be played
played in Allegro,
Allegro, the  install_sound function must be called.
• Allegro
Allegro defines two “magic
“magic drivers”
drivers” that should be passed
passed to the   install_sound function so that
 Allegro can determine which sound card drivers it should use for playing sounds. These “magic
drivers” are  DIGI_AUTODETECT  and   MIDI_AUTODETECT.
 load_sample
• The  function is used to load an external sound file.
• Use
Use the
the  play_sample function to play a digital sample, and the  stop_sample function to stop it.
• The  volume  parameter in the  play_sample  function determines the volume at which the sample
should
shou ld be played
played.. A value
value of 0 mutes
mutes the sampl
sample,
e, while
while a value
value of 255 plays
plays it at maximu
maximum
m volum
volume.
e.
• The  pan  parameter in the  play_sample function determines the pan position at which the sample
should be played. A value of 128 plays the sample out of both speakers equally. A value lower
than this will shift the sound towards the left speaker, while a greater value (up to a maximum of 
255) will shift the sound towards the right speaker.
• The  frequency  parameter in the  play_sample  function determines the frequency (and therefore
the pitch) at which the sample should be played. A value of 1000 will play the sample at normal
frequency. A value of 2000 will play it at double the normal frequency, a value of 500 will play 
it at half, and so on.
 loop   play_sample
• only
Passin
Passing
g thebefore parameter
once of the it any other  function
stopping. Passing value will acause
valuethe
of sample
0 will make theindefinitely.
to loop sample play 
• Use
Use the destroy_sample function to destroy a sample and free the memory allocated to it to pre-
vent memory leaks.
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

LIV    Appendix
Appendix E Game Progra
Programming
mming with the Allegro C Librar
Library
y

Section E.7 Keyboard Input 


• Yo
You u must
must call
call the
the install_keyboard fun funct
ctio
ion
n to allo
allow
w Al
Alle
legr
groo to re
reco
cogn
gniz
izee and
and use
use the keyb
keyboa
oard
rd..
• Allegro
Allegro defines
defines an array of  int
 int s called  key  which contains an index for each key on the keyboard.
If a key is not being pressed, its respective index in the array will contain 0, while if the key is
being pressed, the index will contain a non-zero number.
• Allegro
Allegro defines several symbolic
symbolic constants
constants that correspond
correspond to keys on the keyboard.
keyboard. These con-
stants are used in tandem with the  key  array to determine if specific keys are being pressed. The
value stored at  key[KEY_A] determines whether or not the A the  A key
 key is being pressed, the value stored
at   key[KEY_SPACE] determines whether the spacebar is being pressed, and so on.
• Any program
program that checks
checks the keyboard for input input using the   key  array should do so repeatedly.
Otherwise, keypresses may be missed.

Section E.8 Fonts and Displaying Text 


• Allegro
Allegro defines
defines the  FONT* type that points to stored font data in memory.
• The symbol
symbolic
ic constant
constant font  corresponds to Allegro’s default font.
• Use
Use the load_font function to load font data from external files. If the color depth is set to 8-bit,
you must pass this function the font’s palette in addition to the font itself.
• The   textprintf_ex  function prints text on the screen. Functions   textprintf_centre_ex   and
textprintf_right_ex  do the same thing, but justify
justify the printed
printed text at different positions.
positions.
• When Allegro
Allegro is expecting
expecting an  int  that corresponds to a color as a parameter, passing the param-
eter a value of -1 will make Allegro interpret that color as “transparent.”
• Use
Use the  destroy_font  function to destroy a font and free the memory
memory allocated to it to prevent
memory leaks.

Section E.10 Timers in Allegro


• Any program
program that uses
uses timers must
must call the   install_timer  function before attempting to add
any timers.
• Allegro
Allegro can have up to 16
16 timers running
running at once.
once.
• Timers are added
added by calling
calling the  install_int  function, and removed by calling the  remove_int
function.

• A timer
timer in calls a given
any type function
function at regular intervals
of variable. intervals until it is removed. There is no need to store a 
• Allegro
Allegro identifies
identifies a timer by the function
function it is programmed
programmed to call.
• Any variable
variable whose value
value is modified by a function
function that a timer calls
calls must be given the volatile
qualifier to ensure the program works correctly.

Section E.11 The Grabber and Allegro Datafiles 


• An Allegro datafile
datafile is a single external file that holds the data of many extern
externalal files in one place.
• Allegro
Allegro provides the grabber
grabber utility for the creation
creation and editing of datafiles.
datafiles.
• The grabber
grabber can create header files
files that make it simple to access objects
objects contained
contained in a datafile.
datafile.
• Loading
Loading a datafile
datafile into a program
program is done with the load_datafile function, and removing them
is done with the   unload_datafile function.

• Once
of eacha object
datafileinisthe
loaded
arrayin a program,
program,on
is dependent Allegro considers
consin
the order iders it tothe
which beobjects
an array of objects.
were objects. The
imported index 
into the
datafile. The first object added to the datafile has index 0, the second one has index 1, and so on.
• Allegro
Allegro considers
considers objects
objects loaded from
from a datafile to be of type  vvoi
oidd *.
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

Terminology   LV 

 Terminology 
 Terminology 
 Allegro II grabber XLII, XLIII, XLVI
BITMAP*  type IV, VIII SAMPLE  type XVI
blit  VII set_gfx_mode  VI
datafile XLIII timers in Allegro XXXVII
DATAFILE*  type XLVII virtual screen VII
FONT*  type XXVI

Self-Review Exercises
E.1   Fill in the blanks in each
each of the following
following statements:
statements:
a) Ever
Everyy Alleg
llegro
ro pro
roggram must
must inincclude
lude the
the head
headerer..
b) The
The func
functi
tion
on must
must be call
called
ed befo
before
re an
anyy othe
otherr Al
Alle
legr
groo func
functition
on..
c) Addi
Adding
ng the
the macr
macroo en
ensu
sure
ress co
comp
mpatatib
ibil
ilit
ityy wi
with
th syst
system
emss that
that re
requ
quiriree it.
it.
d) Befo
Before
re Al
Alle
legr
groo can
can disp
displa
layy any
any gr
grap
aphic
hics,
s, a pr
prog
ograram
m must
must call
call bo
both
th the and
and
functions.
e) The
The func
functi
tion
on is us
used
ed to draw
draw a bloc
blockk of ononee bitm
bitmap ap on
onto
to an
anot
othe
her.r.
f) The
The main
main type
type defi
define
nedd by AlAlle
legr
groo fo
forr poin
pointi
ting
ng to soun
sound d file
file da
data
ta is the
the type
type..

g)
h) Alle
Allegr
The
Th egroo defi
define
ness func
the
thncti
fu e tion
on is ussy
symb
mbol
used
ed olic
to ic
re co
cons
returnsta
n tant
turn anntinte
inthat
that
gercorr
tegeco rres
espo
r that
tha tpond
Alnds
Alleg sro
legro tointer
Al
Alle
intlegr
gro’
erpr o’s
etss de
prets defa
asfaul
a ult
cotlor.
colofont
for.nt..
i) All
lleegro can have up to tim
timers running at once.
 j) The function is i s used to add a timer to a program.
k) The
The util
utilit
ityy is used
used to cr
crea
eate
te an
andd ed
edit
it Al
Alle
legr
groo da
data
tafi
file
les.
s.
E.2   State whether each of the following
following is
is true 
 true   or false 
or  false . If  false 
  false , explain why.
a) The  screen bitmap is the only bitmap visible
visible to the user.
b) The coordinates
coordinates (0,
(0, 0) refer to the bottom-left
bottom-left corner
corner of a bitmap.
c) If Allegro
Allegro attempts
attempts to load
load an
an external
external file that does not exist,
exist, a runtime
runtime error will occur.
occur.
d) The double buffering
buffering technique requires two intermediary bitmaps, or buffers, to work 
correctly.
e) Passin
Passingg a value
value of
of 2 to the  loop  parameter in the   play_sample  function will cause the
sound file to play twice before stopping.
f) The  install_keyboard function must be passed a parameter that gives Allegro the driv-
er information of the system’s keyboard.
g) A program
program that draws
draws text on the screen mustmust specify a font
font in which that text should
be drawn.
h) An Allegro
Allegro program
program can have up to 32 timers running running at once.
once.
i) The
The fu func
ncti
tion
on usused
ed fo
forr fr
free
eein
ingg the
the memor
emoryy that
that is stor
storin
ingg a da
data
tafi
file
le is the
the
destroy_datafile  function.

E.3   Write statements to accomplish each of the following:


a) Set the graphics
graphics mode of an Allegro
Allegro program
program to a window
window that
that is 640 p
pixels
ixels wide by 480
480
pixels high.
b) Draw
Draw the
the bitma
bitmap p  bmp  onto the top left corner of the bitmap  buffer.
c) Play the digital
digital sample
sample  sample at maximum volume, centered pan position, and normal
frequency without looping.
d) If the spacebar
spacebar is being
being pressed,
pressed, set the value
value of the int number to 0.
e) Draw
Draw the string 
string  "Hello!"
  "Hello!" onto the top-left corner of the bitmap  buffer, using Allegro’s
default font with a blue foreground color and transparent background color.
f) Add a timer
timer that
that calls
calls the
the function
function timedFunction  four times every second.
g) Load the datafile
datafile with thethe filename
filename  datafile.dat.
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

LVI   Appen
Appendix
dix E Game Progra
Programming
mming with the Allegro C Librar
Library
y

E.4   Find the error


error iin
n each
each of the following:
following:
a)   BITMAP bmp;
b)   set
set_gfx
_gfx_mo
_mode(
de( WINDOWED,
WINDOWED, 640, 480, 0, 0 );
c)   ma
makec
kecol
ol(
( 0, 0, 25
256
6 );

Answers to Self-Review Exercises


E.1   a)   allegro.h. b)   allegro_init. c)   END_OF_MAIN. d)   set_color_depth   and   set_gfx_mode.
e)  blit. f)  SAMPLE*. g)  font. h)  makecol. i) 16. j)   install_int. k) grabber.
E.2   a) True
True..
b) False. The
The coordinates
coordinates (0, 0) refer
refer to the top-left corner
corner of a bitmap.
bitmap.
c) False. The
The function
function that returns
returns the pointer
pointer to the external
external file will return
return NULL, but no
error will occur on that line.
d) False. Double
Double buffering
buffering requires only one intermedia
intermediaryry bitmap.
e) Fals
False.
e. Pass
Passin
ingg an
anyy va
valu
luee othe
otherr than
than 0 to the
the loop pa
para
rame
meteterr wi
will
ll make
make the sound
sound fi
file
le loop
loop
indefinitely.
f) Fa
Fals
lse.
e. The  install_keyboard function does not take any parameters.
g) True
True..
h) False. An Allegro
Allegro program
program can
can have only 16 timers running
running at once.
 unload_datafile  destroy_datafile
i) False.
Fal se. defined
is not This
This ffunc
unction
bytion is the
Allegro.  function. The  function
E.3   a)   set
set_gfx
_gfx_mo
_mode(
de( GFX_
GFX_AUTO
AUTODET
DETECT_
ECT_WIND
WINDOWED
OWED,
, 640, 480, 0, 0 );
b)   bl
blit(
it( bmp
bmp,
, buffer
buffer,
, 0, 0, 0, 0, bmp-
bmp->w,
>w, bmp->h
bmp->h );
c)   pla
play_sa
y_sampl
mple(
e( sample,
sample, 255, 128, 100
1000,
0, 0 );
d)   if ( key
key[KE
[KEY_SP
Y_SPACE
ACE]
] )
numbe
number
r = 0;
e)   te
textp
xtpri
rint
ntf_
f_ex(
ex( bu
buff
ffer,
er, font,
font, 0, 0, mak
makec
ecol(
ol( 0, 0, 25
255
5 ), -1, "H
"Hel
ello
lo!"
!" );
f)   install
install_int(
_int( timedFunc
timedFunction,
tion, 250 );
g)   load_da
load_datafile(
tafile( "datafile.
"datafile.dat"
dat" );

E.4   a) The variab


variable
le bmp  should instead be declared as a pointer to a  BITMAP
  BITMAP. All of Allegro’s bit-
map functions either take a pointer as a parameter or return a pointer. A  BITMAP that is
not a pointer is essentially useless.
b) Allegro
Allegro does
does not define a  WINDOWED
not define   WINDOWED  “magic driver.” Use the   GFX_AUTODETECT_WINDOWED
“magic driver” instead.
c) The  makecol function can only accept parameters with values between 0 and 255.

Exercises
E.5   (Moving an Image Via the Arrow Keys) Write
Keys)  Write a program that draws the bitmap  ball.bmp
in the center of the screen. When the user presses one of the arrow keys, the bitmap should move
ten pixels in that direction.
E.6   (Moving an Image Via the Arrow Keys) Modify
Keys)  Modify the program from Exercise E.5 so that the
ball will only move once for each time an arrow key is pressed. If the user holds down an arrow key,
the ball should move once and then stop until the user releases and presses the key again.
E.7   (Moving
(Moving an Image Via the Arrow Keys) Modify
Keys) Modify the program from Exercise E.5 so that if 
the user holds down an arrow key, the ball will only move once every second.
E.8   (Ending
(Ending the Pong Game at 21) Modify
21) Modify the Pong game from Fig. E.21 so that when a player
reaches 21 points, the game ends and displays a message that the left or right player has won.
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
 

Exercises   LVII

E.9   (Moving
(Moving the
the Ball
Ball Faster
Faster in a Long Rally) In
Rally) In most Pong games, when a rally between the
two players lasts for a long time, the ball begins to speed up in order to prevent a stalemate. Modify 
the Pong game from Fig. E.21 so that the ball’s speed increases
increases for every ten times that it is hit in a 
rally. When either player scores, the ball should return to its original speed.
E.10   (Alter
(Altering
ing the Paddle
Paddle Speeds
Speeds)) So
Some
me Pong
Pong game
gamess also
also modi
modify
fy the
the sp
spee
eed
d of on
onee or both
both pl
play
ayer
er’s
’s
paddles in an effort to keep the game balanced. Modify the Pong game from Fig. E.21 so that when
one player has a lead of at least 5 points, his or her paddle begins to slow down. The greater that
player’s lead, the slower his or her paddle should move. If the player’s lead falls to under 5 points,
his or her paddle should return to normal speed.
E.11   (Adding a Pause Feature) Video
Feature) Video games often have a “pause” feature that allows a player to
interrupt a game in progress and then resume it later. Modify the Pong game from Fig. E.21 so that
pressing the P 
the  P  key
 key will pause the game and halt the movement of the ball and paddles. Paus
Pausing
ing the
game should also make the message   "PAUSED"  appear in the center of the screen. If the game is
paused, pressing the R 
the R  key
 key should clear the  "PAUSED" message from the screen and resume the game.
E.12   (Playing
(Playing a Sound
Sound When
When a Ball
Ball Hits
Hits a Paddle)
Paddle) Modify
 Modify the Pong game from Fig. E.21 so
that when the ball bounces off a wall or paddle, the word   "BOING!"  appears in blue at the point
 where the ball bounced and then
t hen fades away. The text should not simply vanish—it
vanish —it should gradu-
ally fade to white.

E.13   (Providing Ball and Paddle Speed Options) Modify


Options) Modify the Pong game from Fig. E.21 so that
before the game begins, a menu appears on the screen that allows the players to choose from several
different ball and paddle speeds. This is tougher than it sounds! Allegro does not have any text input
methods. You will have to find another method of solving this problem.

You might also like