PDF Appendix e Game Programming With The Allegro Library DL
PDF Appendix e Game Programming With The Allegro Library DL
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 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
© 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 */
© 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
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
© 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.
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 */
© 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);
© 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
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.
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.
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
© 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;
© 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 */
© 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.
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),
© 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 */
© 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 */
© 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
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
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.
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 */
© 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 */
© 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 */
© 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:
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 */
© 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
© 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 */
© 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
© 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.
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.
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!" );
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 */
© 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
© 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
© 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 */
© 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 );
XXXII Appen
Appendix
dix E Game Progra
Programming
mming with the Allegro C Librar
Library
y
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 {
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 */
E.9 Imple
Implementi
menting
ng the
the Game
Game of Pong
Pong XXXV
XXXVI Appen
Appendix
dix E Game Progra
Programming
mming with the Allegr
Allegro
o C Libra
Library
ry
E.1
E.10
0 Tim
Timers
ers in Alle
Allegro
gro XXXVII
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 );
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 );
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 );
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 */
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 {
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 */
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.
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.
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.
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.
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.
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 */
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
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 );
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
L Appendix
Appendix E Game Progra
Programming
mming with the Allegr
Allegro
o C Libra
Library
ry
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.
LII Append
Appendix
ix E Game Progra
Programming
mming with the Allegr
Allegro
o C Libra
Library
ry
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.
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.
LIV Appendix
Appendix E Game Progra
Programming
mming with the Allegro C Librar
Library
y
• 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.
• 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.
LVI Appen
Appendix
dix E Game Progra
Programming
mming with the Allegro C Librar
Library
y
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.