Here is a breakdown of the major topics in this chapter: I Creating the game world I Loading and drawing Mappy level files Creating the Game World Mappy is an awesome map editing program
Trang 1Modifying the Tank War Project
The complete new version of Tank War is available in \chapter11\tankwar on the CD-ROM;
you can load up the project or simply run the game from that location if you want I recommend you follow along and make the changes yourself because it is a valuable learn-
ing experience To do so, you’ll want to open the Tank War project from Chapter 10 to
make the following changes Be sure to copy the tank1.bmp and tank2.bmp files off the
CD-ROM so the new version of the game will work, because these bitmap files contain the new animated tanks
Updating tankwar.h
First, you need to make a few minor changes to the tankwar.h header file Look for the
sec-tion of code that defines the sprites and add the new line of code shown in bold
Next, modify the tank_bmparray, which contains the bitmap images for the tanks Scroll
down in tankwar.h a little further to find the sprite bitmap definitions and make the
change noted in bold (It’s a small change to the tank_bmparray—just add another dimension
to the array as shown.)
Enhancing Tank War 415
Figure 11.8 Tank War now draws animated explosions in the
game loop without pausing the game
Trang 2void animatetank(int num);
void updateexplosion(int num);
void loadsprites();
void drawtank(int num);
void erasetank(int num);
void movetank(int num);
Updating tank.c
Now you can make some changes to the tank.c source code file, which contains all thecode for loading, moving, and drawing the tanks Add a new function to the top of tank.c
to accommodate the new animated tanks
//new function added in chapter 11
void animatetank(int num)
else if (tanks[num]->curframe < 0) tanks[num]->curframe = tanks[num]->maxframe;
}
}
Now you have to make some changes to drawtank, the most important function in tank.c,because it is responsible for actually drawing the tanks You need to add support for thenew animated frames in the tank_bmparray Make the changes noted in bold (You’ll noticethat the only changes are made to draw_spritefunction calls.)
void drawtank(int num)
{
int dir = tanks[num]->dir;
int x = tanks[num]->x-15;
int y = tanks[num]->y-15;
Trang 3draw_sprite(buffer, tank_bmp[num][tanks[num]->curframe][dir], x, y);
//what about the enemy tank?
//draw enemy tank, adjust for scroll
draw_sprite(buffer, tank_bmp[!num][tanks[!num]->curframe][tanks[!num]->dir],
startx[num]+x-scrollx[num]-15, starty[num]+y-scrolly[num]-15);
}
}
Next, you need to make some changes to the movetankfunction to accommodate the new
animated tanks The way this works now is that the tank is animated only when it is
mov-ing You need to determine when the tank is moving by looking at the speed of the tank,
and then update the sprite frame accordingly You also need to make some changes to the
code that keeps the tanks inside the bounds of the map so that when a tank reaches the
edge, it will stop animating Make the changes noted in bold
void movetank(int num)
{
int dir = tanks[num]->dir;
int speed = tanks[num]->xspeed;
//animate tank when moving
Trang 5You must make extensive changes to setup.c to load the new animation frames for the tanks
and initialize the new explosion sprites You’ll end up with a new loadspritesfunction and
a lot of changes to setuptanks First, add the new loadspritesfunction to the top of the
setup.c file I won’t use bold because you need to add the whole function to the program
Next up, the changes to setuptanks There are a lot of changes to be made in this function
to load the new tank1.bmp and tank2.bmp files, and then extract the individual
anima-tion frames Make all changes noted in bold
Trang 6//load first tank
temp = load_bitmap(“tank1.bmp”, NULL);
for (anim=0; anim<8; anim++)
clear_to_color(tank_bmp[0][anim][n], makecol(255,0,255));
rotate_sprite(tank_bmp[0][anim][n], tank_bmp[0][anim][0],
Trang 7//load second tank
temp = load_bitmap(“tank2.bmp”, NULL);
for (anim=0; anim<8; anim++)
{
//grab animation frame
tank_bmp[1][anim][0] = grabframe(temp, 32, 32, 0, 0, 8, anim);
//rotate image to generate all 8 directions
for (n=1; n<8; n++)
{
tank_bmp[1][anim][n] = create_bitmap(32, 32);
clear_to_color(tank_bmp[1][anim][n], makecol(255,0,255));
rotate_sprite(tank_bmp[1][anim][n], tank_bmp[1][anim][0],
That wasn’t so bad because the game was designed well and the new code added in
Chapter 10 was highly modifiable It always pays to write clean, tight code right from the
start
Enhancing Tank War 421
Trang 8Open the bullet.c file You’ll be adding a new function called updateexplosionand ing the existing explodefunction Here is the new updateexplosionyou should add to thetop of the bullet.c file.
modify-//new function added in chapter 11
void updateexplosion(int num)
//draw explosion in “my” window if enemy is visible
x = scrollx[!num] + SCROLLW/2;
y = scrolly[!num] + SCROLLH/2;
if (inside(x, y, scrollx[num], scrolly[num], scrollx[num] + SCROLLW, scrolly[num] + SCROLLH)) {
//but only draw if explosion is active
if (explosions[num]->alive) rotate_sprite(buffer, explode_bmp, startx[num]+x-scrollx[num] + rand()%10 - 20, starty[num]+y-scrolly[num] + rand()%10 - 20, itofix(rand()%255));
Trang 9Now modify explodeso it will properly set up the explosion, which is actually drawn by
updateexplosion later on in the animation process of the game loop Make the changes
noted in bold The entire function has been rewritten, so simply delete existing code and
add the new lines to explode
void explode(int num, int x, int y)
That’s the end of the changes to bullet.c Now you can make the last few changes needed
to update the game Next you’ll turn to the main.c file
Updating main.c
The last changes will be made to main.c to call the new functions (such as animatetankand
updateexplosion) The only changes to be made will be to the mainfunction You need to
add a line that creates a new variable and calls loadspritesandanimatetank, and finally, you
need a call to updateexplosion Be careful to catch the changes to tank_bmpand note the
cleanup code at the end Make the changes noted in bold
Trang 10movebullet(n);
} //draw background bitmap blit(back, buffer, 0, 0, 0, 0, back->w, back->h);
//draw scrolling windows for (n=0; n<2; n++) blit(scroll, buffer, scrollx[n], scrolly[n], startx[n], starty[n], SCROLLW, SCROLLH);
//update the radar rectfill(buffer,radarx+1,radary+1,radarx+99,radary+88,BLACK);
rect(buffer,radarx,radary,radarx+100,radary+89,WHITE);
//draw mini tanks on radar for (n=0; n<2; n++) stretch_sprite(buffer, tank_bmp[n][tanks[n]->curframe][tanks[n]->dir],
radarx + scrollx[n]/10 + (SCROLLW/10)/2-4, radary + scrolly[n]/12 + (SCROLLH/12)/2-4,
8, 8);
//draw player viewport on radar for (n=0; n<2; n++)
rect(buffer,radarx+scrollx[n]/10, radary+scrolly[n]/12, radarx+scrollx[n]/10+SCROLLW/10,
radary+scrolly[n]/12+SCROLLH/12, GRAY);
//display score for (n=0; n<2; n++)
Trang 11textprintf(buffer, font, startx[n], HEIGHT-10,
BURST, “Score: %d”, scores[n]);
//draw the tanks and bullets
//free tank bitmaps
for (anim=0; anim<8; anim++)
Trang 12//free explosion sprites
Future Changes to Tank War
I must admit that this game is really starting to become fun, not only as a very playablegame, but also as an Allegro game project It is true that if you design and program a game
that you find interesting and fun, others will be attracted to the game as well I did just
that, and I have enjoyed sharing the vision of this game with you What do you think ofthe result so far? It needs a little bit more work (such as sound effects), but otherwise it isvery playable If you have any great ideas to make the game even better, by all means, goahead and try them!
You can use this example game as a basis for your own games Are you interested in RPGs?
Go ahead and convert it to a single scrolling window and replace the tank with your owncharacter sprite, and you almost have an RPG framework right there As for futurechanges, the next chapter adds customizable levels to the game with a level-editing pro-gram called Mappy
Summary
This was an advanced chapter that dealt with the intriguing subjects of timers, interrupts,
and threads I started with a TimerTest program that animated several sprites on the
screen to demonstrate how to calculate and display the frame rate You then modified theprogram to use an interrupt handler to keep track of the frame rate outside of the main
loop (InterruptTest) This was followed by another revision that demonstrated how to set
a specific frame rate for the program (TimedLoop) The last section of the chapter was
devoted to multi-threading, with a tutorial on the Posix Threads library and Red Hat’s
Pthreads-Win32 project The result was an interesting program called MultiThread that
demonstrated how to use threads for sprite control The potential for increased frame-rateperformance in a game is greatly encouraged with the use of threads to delegate func-tionality from a single loop because this provides support for multiple-processor systems
Chapter Quiz
You can find the answers to this chapter quiz in Appendix A, “Chapter Quiz Answers.”
Trang 131 Why is it important to use a timer in a game?
A To maintain a consistent frame rate
B To include support for interrupts
C To make the program thread-safe
D To delegate code to multiple threads
2 Which Allegro timer function slows down the program using a callback function?
6 What is a process that runs within the memory space of a single program but is
executed separately from that program?
Trang 147 What helps protect data by locking it inside a single thread, preventing that datafrom being used by another thread until it is unlocked?
Trang 15The game world defines the rules of the game and presents the player with all of the
obstacles he must overcome to complete the game Although the game world is the
most important aspect of a game, it is not always given proper attention when a
game is being designed This chapter provides an introduction to world building—or
more specifically, map editing Using the skills you learn in this chapter, you will be able
to enhance Tank War and learn to create levels for your own games This chapter provides
the prerequisite information you’ll need in the next two chapters, which discuss
horizon-tal and vertical scrolling games
Here is a breakdown of the major topics in this chapter:
I Creating the game world
I Loading and drawing Mappy level files
Creating the Game World
Mappy is an awesome map editing program, and it’s freeware so you can download and
use it to create maps for your games at no cost If you find Mappy to be as useful as I have,
I encourage you to send the author a small donation to express your appreciation for his
hard work The home page for Mappy is http://www.tilemap.co.uk
Why is Mappy so great, you might ask? First of all, it’s easy to use In fact, it couldn’t be
any easier to use without sacrificing features Mappy allows you to edit maps made up of
the standard rectangular tiles, as well as isometric and hexagonal tiles! Have you ever
played hexagonal games, such as Panzer General, or isometric games, such as Age of
Empires ? Mappy lets you create levels that are similar to the ones used in these games.
Mappy has been used to create many retail (commercial) games, some of which you might
Trang 16have played I personally know of several developers who have used Mappy to create els for retail games for Pocket PC, Game Boy Advance, Nokia N-Gage, and wireless (cell
lev-phones) MonkeyStone’s Hyperspace Delivery Boy (created by Tom Hall, John Romero,
and Stevie Case) for Pocket PC and Game Boy Advance is one example
Suffice it to say, Mappy is an unusually great map editor released as freeware, and I willexplain how to use it in this chapter You’ll also have an opportunity to add Mappy sup-
port to Tank War at the end of the chapter.
Installing Mappy
Mappy is included in the \mappy folder on the CD-ROM that accompanies this book Youcan run Mappy directly without installing it, although I would recommend copying themapwin.exe file to your hard drive Mappy is so small (514 KB) that it’s not unreasonable
to copy it to any folder where you might need it If you want to check for a newer version
of Mappy, the home page is located at http://www.tilemap.co.uk In addition to Mappy,there are sample games available for download and the Allegro support sources forMappy (See the “Loading and Drawing Mappy Level Files” section later in this chapter formore information.) If you do copy the executable without the subfolders, INI file, and so
on, you’ll miss out on the Lua scripts and settings, so you might want to copy the wholefolder containing the executable file
Creating a New Map
Now it’s time to fire up Mappy and create a new map Locate mapwin.exe and run it Thefirst time it is run, Mappy displays two blank child windows (see Figure 12.1)
Now open the File menu and select New Map to bring up the New Map dialog box, shown
in Figure 12.2
As the New Map dialog box shows, you must enter the size of each tile in your tile image
file The tiles used in Tank War (and in most of the chapters of this book) are 32×32
pix-els, so I have typed 32 in the width box and 32 in the height box Next you must enter thesize of the map The default 100×100 map probably is too large to be useful as a good
example at this point If you recall from Chapter 10, the GameWorld program used a map
that had an area of 31×33 tiles You should use that program as a basis for testing Mappy
Of course, you can use any values you want, but be sure to modify the source code (in thenext section) to accommodate the dimensions of the map you have created
t i p
Mappy allows you to change the size of the map after it has been created, so if you need more tiles
in your map later, it’s easy to enlarge the map Likewise, you can shrink the map; Mappy has anoption that lets you choose the part of the map you want to resize
Trang 17Figure 12.3 shows the dimensions that Ihave chosen for this new map Note alsothe option for color depth This refers tothe source image containing the tiles; inmost cases you will want to choose theTruecolour option because most sourceartwork will be 16-bit, 24-bit, or 32-bit.
(Any of these will work with Mappy if youselect this option.)
If you click on the Advanced button in theNew Map dialog box, you’ll see the addi-tional options shown in Figure 12.4 Theseadditional options allow you to select theexact color depth of the source tiles (8-bitthrough 32-bit), the map file version to use,and dimensions for non-rectangular maptiles (such as hexagonal and isometric)
Creating the Game World 431
Figure 12.1 Mappy is a simple and unassuming map editor.
Figure 12.2 You can use the New Map dialog
box to configure a new game level
Figure 12.3 Changing the size of the new map
Trang 18When you click on the OKbutton, a new map will becreated and filled with thedefault black tile (tile #0) Atthis point, you must importthe tile images to be used tocreate this map This is wherethings really get interestingbecause you can use multipleimage files containing sourceartwork, and Mappy willcombine all the source tilesinto a new image source with correctly positioned tiles (Saving the tile bitmap file is anoption in the Save As dialog box.)
Importing the Source Tiles
Now open the File menu and select Import The Open File dialog box will appear, ing you to browse for an image file, which can be of type BMP, PCX, PNG, or MAR/P (maparray file—something that can be exported by Mappy) I have created a larger tile imagefile containing numerous tiles from Ari Feldman’s SpriteLib (http://www.arifeldman.com).The maptiles.bmp file is located in the \chapter12\ArrayMapTest folder on the CD-ROM.After you choose this file, Mappy will import the tiles into the tile palette, as shown inFigure 12.5 Recall that you specified the tile size when you created the map file; Mappyused the dimensions provided to automatically read in all of the tiles You must make theimage resolution reasonably close to the edges of the tiles, but it doesn’t need to be perfect
allow-—Mappy is smart enough to account for a few pixels off the right or bottom edges andmove to the next row
Now I’d like to show you a convenient feature that I use often I like to see most of the level
on the screen at once to get an overview of the game level Mappy lets you change thezoom level of the map editor display Open the MapTools menu and select one of thezoom levels to change the zoom Then, select a tile from the tile palette and use the mouse
to draw that tile on the map edit window to see how the chosen zoom level appears I quently use 0.5 (1/2 zoom) Until you have added some tiles to the map window, youwon’t see anything happen after you change the zoom
fre-Now let me show you a quick shortcut for filling the entire map with a certain tile Select
a neutral tile that is good as a backdrop, such as the grass, dirt, or stone tile Open theCustom menu This menu contains scripts that you can run to manipulate a map (Youcan write your own scripts if you learn the Lua language—visit http://www.lua.org formore information.) Select the script called Solid Rectangle, which brings up the dialogbox shown in Figure 12.6
Figure 12.4 The advanced options in the New Map dialog box
Trang 19Modify the width and height parameters for the rectangle,using one less than the value you entered for the map when itwas created (31–1 = 30 and 33–1 = 32) Click on OK, and themap will be filled with the currently selected tile, as shown inFigure 12.7.
Play around with Mappy to gain familiarity with it You canerase tiles using the right mouse button and select tiles in thepalette using the left button You can use the keyboard arrowkeys to scroll the map in any direction, which is very handywhen you want to keep your other hand on the mouse forquick editing Try to create an interesting map, and then I’ll show you how to save the map
in two different formats you’ll use in the sample programs that follow
Saving the Map File as FMP
Have you created an interesting map that can be saved? If not, go ahead and create a map,
even if it’s just a hodgepodge of tiles, because I want to show you how to save and use the
map file in an Allegro program Are you ready yet? Good! As a reference for the figures
that follow in this chapter, the map I created is shown in Figure 12.8
Creating the Game World 433
Figure 12.5 The SpriteLib tiles have been imported into Mappy’s tile palette
for use in creating game levels
Figure 12.6 Mappy
includes scripts that can
manipulate a map, and you
can create new scripts
Trang 20Figure 12.7 The Solid Rectangle script fills a region of the map with a tile.
Figure 12.8 The sample map file used in this chapter
Trang 21I’ll show you how to save the map file first, and then you’ll export the map to a text file
and try to use it in sample programs later For now, open the File menu and select Save As
to bring up the Save As dialog box shown in Figure 12.9
Type a map filename, such
as map1.fmp, and click onSave The interesting thingabout the FMP file format isthat the tile images arestored along with the mapdata, so you don’t need to
load the tiles and the map
file to create your gameworld You might not likelosing control over the tileimages, but in a way it’s ablessing—one less thing toworry about when you’drather focus your time ongameplay
Saving the Map File as Text
Now that you have saved the new level in the standard
Mappy file format, I’d like to show you how to export the
map to a simple text file that you can paste into a program
The result will be similar to the GameWorld program from
Chapter 10, in which the map tile data was stored in an
array in the program’s source code
Open the File menu and select Export Do not select Export
As Text That is an entirely different option used to export a
map to a binary array used for the Game Boy Advance and
other systems Just select Export to bring up the Export
dia-log box shown in Figure 12.10
You can explore the uses for the various formats in the
Export dialog box when you have an opportunity; I will
only explain the one option you need to export the map
data as text You want to select the third check box from the
top, labeled Map Array as Comma Values Only (?.CSV)
435Creating the Game World
Figure 12.9 The Save As dialog box in Mappy is used to save a
map file
Figure 12.10 The Export
dialog in Mappy lets youchoose options for exportingthe map
Trang 22If you want to build an image containing the tiles in the proper order, as they were inMappy, you can also select the check box labeled Graphics Blocks as Picture (?.BMP) Istrongly recommend exporting the image For one thing, Mappy adds the blank tile thatyou might have used in some parts of the map; it also numbers the tiles consecutivelystarting with this blank tile unless you check the option Skip Block 0 Normally, youshould be able to leave the default of 20 in the Blocks a Row input field Click on OK toexport the map.
Mappy outputs the map with the name provided in the Export dialog box as two files—map1.BMP and map1.CSV (Your map name might differ.) The CSV format is recognized
by Microsoft Excel, but there is no point loading it into Excel (even if you have MicrosoftOffice installed) Instead, rename the file map1.txt and open it in Notepad or another texteditor You can now copy the map data text and paste it into a source code file, and youhave the bitmap image handy as well
Loading and Drawing Mappy Level Files
Mappy is far more powerful than you need for Tank War (or the rest of this book, for that
matter) Mappy supports eight-layer maps with animated tiles and has many helpful tures for creating game worlds You can create a map, for instance, with a backgroundlayer, a parallax scrolling layer with transparent tiles, and a surface layer that is drawn oversprites (such as bridges and tunnels) I’m sure you will become proficient with Mappy in
fea-a very short time fea-after you use it to crefea-ate fea-a few gfea-ames, fea-and you will find some of thesefeatures useful in your own games For the purposes of this chapter and the needs of your
Tank War game, Mappy will be used to create a single-layer map.
There are two basic methods of using map files in your own games The first method is toexport the map from Mappy as a text file You can then paste the comma-separated map
tile numbers into an array in your game (Recall the GameWorld program from Chapter
10, which used a hard-coded map array.) There are drawbacks to this method, of course.Any time you need to make changes to a map file, you’ll need to export the map again andpaste the lines of numbers into the map array definition in your game’s source code.However, storing game levels (once completed) inside an array means that you don’t need
to load the map files into your game—and further, this prevents players from editing yourmap files I’ll explain how to store game resources (such as map files) inside an encrypted/compressed data file in Chapter 16, “Using Datafiles to Store Game Resources.”
The other method, of course, is to load a Mappy level file into your game This is a moreversatile solution, which makes sense if your game has a lot of levels and/or is expandable.(Will players be able to add their own levels to the game and make them available fordownload, and will you release expansion packs for your game?)
Trang 23The choice is obvious for large, complex games, such as StarCraft, but for smaller games
like Arkanoid, my personal preference is to store game levels inside the source code Given
the advanced features in Mappy, it is really only practical to export map files if your game
is using a single layer with no animation When your game needs multiple layers and
ani-mated tiles, it is better to load the Mappy level file Why? Because source code is available
to load and draw complex Mappy files (See the “Using a Mappy Level File” section later
in this chapter.) Another consideration you should keep in mind is that Mappy files
include both the map data and the artwork! That’s right; the Mappy file includes the tiles
as well as the data, so you don’t need to load the tiles separately when you’re using a
Mappy file directly This is a great feature, particularly when you are dealing with huge,
complex game world maps
Next, I’ll demonstrate how to load a map that has been exported to a text file, and then
I’ll follow that explanation with another sample program that demonstrates how to load
a Mappy file directly
Using a Text Array Map
I want to write a short program to demonstrate how to load a Mappy level that has been
exported to a text file You’ll recall from the previous section that you exported a map to
a text file with a bitmap file filled with the source tiles that correspond to the values in the
text data I’m going to open the GameWorld program from Chapter 10 and modify it to
demonstrate the text map data that was exported Create a new project and add a
refer-ence to the Allegro library as usual Then, type the following code into the main.c file
Figure 12.11 shows the program running
437Loading and Drawing Mappy Level Files
Figure 12.11 The ArrayMapTest program demonstrates how to
use an exported Mappy level
Trang 24If you are using GameWorld as a basis, just take note of the differences On the CD-ROM,
this project is called ArrayMapTest, and it is located in the \chapter12\ArrayMapTest folder
#include “allegro.h”
//define some convenient constants
#define MODE GFX_AUTODETECT_FULLSCREEN
//20 columns across is the default for a bitmap
//file exported by Mappy
#define COLS 20
//make sure this exactly describes your map data
#define MAP_ACROSS 31
#define MAP_DOWN 33
#define MAPW MAP_ACROSS * TILEW
#define MAPH MAP_DOWN * TILEH
Trang 25//reuse our friendly tile grabber from chapter 9
BITMAP *grabframe(BITMAP *source,
int width, int height, int startx, int starty, int columns, int frame) {
BITMAP *temp = create_bitmap(width,height);
int x = startx + (frame % columns) * width;
int y = starty + (frame / columns) * height;
//set video mode
if (set_gfx_mode(MODE, WIDTH, HEIGHT, 0, 0) != 0)
//create the virtual background
scroll = create_bitmap(MAPW, MAPH);
//load the tile bitmap
//note that it was renamed from chapter 10
Loading and Drawing Mappy Level Files 439
Trang 26tiles = load_bitmap(“maptiles.bmp”, NULL);
//now draw tiles on virtual background
for (tiley=0; tiley < scroll->h; tiley+=TILEH)
} }
x += STEP;
if (x > scroll->w - WIDTH)
x = scroll->w - WIDTH;
} //check left arrow
if (key[KEY_LEFT]) {
x -= STEP;
if (x < 0)
x = 0;
} //check down arrow
if (key[KEY_DOWN]) {
Trang 27//draw the scroll window portion of the virtual buffer
blit(scroll, screen, x, y, 0, 0, WIDTH-1, HEIGHT-1);
//display status info
In case you didn’t catch the warning (with sirens, red alerts, and beseechings), you must
paste your own map data into the source code in the location specified The map data was
exported to a map1.CSV file in the previous section of the chapter, and you should have
renamed the file map1.txt to open it in Notepad Simply copy that data and paste it into
themaparray
This is the easiest way to use the maps created by Mappy for your game levels, and I
encourage you to gain a working knowledge of this method because it is probably the best
option for most games When you have progressed to the point where you’d like to add
some advanced features (such as blocking walls and obstacles on the level), you can move
on to loading and drawing Mappy files directly
Loading and Drawing Mappy Level Files 441
Trang 28Using a Mappy Level File
The Mappy file structure is binary and includes not only the data, but also the tiles Alibrary has been created to support Mappy within Allegro programs and is available fordownload on the Mappy Web site at http://www.tilemap.co.uk The library is calledMappyAL, and the current release at the time of this writing is 11D For distribution andlicensing reasons, I have chosen not to include this library on the book’s CD-ROM(although the author offers it for free on the Web site) When you download MappyAL(which is currently called mapalr11.zip, but that is likely to change), extract the zip file tofind some source code files therein
All you need are the mappyal.c and mappyal.h files from the zip archive to use Mappymap files in your own programs Because I will not be going into the advanced features ofMappy or the MappyAL library, I encourage you to browse the Mappy home page, viewthe tutorials, and download the many source code examples (including many completegames) to learn about the more advanced features of Allegro
The MappyAL library is very easy to use Basically, you call MapLoadto open a Mappy file.MapDrawBGis used to draw a background of tiles, and MapDrawFGdraws foreground tiles (spec-ified by layer number) There is one drawback to the MappyAL library—it was writtenquite a long time ago, back in the days when VGA mode 13h (320×200) was popular.Unfortunately, the MappyAL library only renders 8-bit (256 color) maps correctly.You can convert a true color map to 8-bit color Simply open the MapTools menu andselect Useful Functions, Change Block Size/Depth This will change the color depth of themap file; you can then import 8-bit tiles and the map will be restored Paint Shop Pro caneasily convert the tiles used in this chapter to 8-bit without too much loss of quality.Ideally, I recommend using the simple text map data due to this drawback
Now it’s time to write a short test program to see how to load a native Mappy file ing map data and tiles, and then display the map on the screen with the ability to scroll themap Create a new project, add a reference to the Allegro library, and add the mappyal.cand mappyal.h files to the project (These source code files provide support for Mappy inyour Allegro programs.) Then, type the following code into the main.c file You can usethe map1.FMP file you saved earlier in this chapter—or you can use any Mappy file youwant to test, because this program can render any Mappy file regardless of dimensions(which are stored inside the map file rather than in the source code) Figure 12.12 shows
contain-the TestMappy program running.
#include <conio.h>
#include <stdlib.h>
#include “allegro.h”
#include “mappyal.h”
Trang 29#define MODE GFX_AUTODETECT_FULLSCREEN
Loading and Drawing Mappy Level Files 443
Figure 12.12 The TestMappy program demonstrates how to load a native
Mappy file
Trang 30//create the double buffer and clear it
buffer = create_bitmap(SCREEN_W, SCREEN_H);
//draw map with single layer
MapDrawBG(buffer, xoffset, yoffset, 0, 0, SCREEN_W-1, SCREEN_H-1);
//blit the double buffer blit (buffer, screen, 0, 0, 0, 0, SCREEN_W-1, SCREEN_H-1);
//check for keyboard input
if (key[KEY_RIGHT]) {
xoffset-=4;
if (xoffset < 0) xoffset = 0;
}
if (key[KEY_UP]) {
Trang 31Enhancing Tank War
Now it’s time for an update to Tank War—the seventh revision to the game Chapter 11
provided some great fixes and new additions to the game, including animated tanks and
non-interrupting explosions As you might have guessed, this chapter brings Mappy
sup-port to Tank War It should be a lot of fun, so let’s get started! This is going to be an easy
modification (only a few lines of code) because Tank War was designed from the start to
be flexible However, a lot of code that will be removed from Tank War because MappyAL
takes care of all the scrolling for you
Do you remember the dimensions of the map1.fmp file that was used in this chapter?
They were 100 tiles across by 100 tiles down However, the actual map only uses 30 tiles
across and 32 tiles down This is a bit of a problem for Tank War because MappyAL will
render the entire map, not just the visible portion The reason the map was set to 100×100
was to make the Mappy tutorial easier to explain, and at the time it did not matter Now
you’re dealing with a map that is 3,200×3,200 pixels, which won’t work in Tank War
(Actually, it will run just fine, but the tanks won’t be bounded by the edge of the map.)
To remedy this situation, I have created a new version of the map file used in this chapter
Enhancing Tank War 445
Trang 32It is called map3.fmp, and it is located in \chapter12\tankwar along with the project files
for this new revision of Tank War.
What’s great about this situation? You can create a gigantic battlefield map for Tank War!
There’s no reason why you should limit the game to a mere 30×32 tiles Go ahead and ate a huge map with lots of different terrain so that it isn’t so easy to find the other player
cre-Of course, if you create a truly magnificent level, you’ll need to modify the bullet code Itwasn’t designed for large maps, so you can’t fire again until the bullet reaches the edge ofthe map Just put in a timer so the bullet will expire if it doesn’t hit anything after a fewseconds
Proposed Changes to Tank War
The first thing to do is add mappyal.c and mappyal.h to the project to give Tank War support for the MappyAL library I could show you how to render the tiles directly in Tank War, which is how the game works now, but it’s far easier to use the functions in MappyAL
to draw the two scrolling game windows You can open the completed project from
\chapter12\tankwar, or open the Chapter 11 version of the game and make the followingchanges
How about a quick overview? Figure 12.13 shows Tank War using the map file from the TestMappy program! In Figure 12.14, player two is invading the base of player one!
Figure 12.13 Tank War now supports the use of Mappy files instead of a
hard-coded map
Trang 33Modifying Tank War
Now you can make the necessary changes to Tank War to replace the hard-coded
back-ground with support for Mappy levels
Modifying tankwar.h
First up is the tankwar.h header file Add a new #defineline to include the mappyal.h file
in the project Note the change in bold
/////////////////////////////////////////////////////////////////////////
// Game Programming All In One, Second Edition
// Source Code Copyright (C)2004 by Jonathan S Harbour
// Tank War Enhancement 7 - tankwar.h
Enhancing Tank War 447
Figure 12.14 Support for Mappy levels gives Tank War a lot of new
potential because anyone can create a custom battlefield for the game
Trang 34Next, remove the reference to the hard-coded map array (I have commented out the line
so you will see what to remove.) This line follows the bitmap definitions
//the game map
//extern int map[];
Next, delete the definition for the tilesbitmap pointer Because Mappy levels contain thetiles, your program doesn’t need to load them; it only needs to load the map file (Isn’t thatgreat?)
//bitmap containing source tiles
//BITMAP *tiles;
Finally, delete the reference to the scrollbitmap, which is also no longer needed
//virtual background buffer
//BITMAP *scroll;
You’ve ripped out quite a bit of the game with only this first file! That is one fringe fit to using MappyAL—a lot of source code formerly required to do scrolling is now builtinto MappyAL
bene-Modifying setup.c
Next up is the setup.c source code file Scroll down to the setupscreenfunction and slashthe code that loads the tiles and draws them on the virtual background image You canalso delete the section of code that created the virtual background I’ll list the entire func-tion here with the code commented out that you should delete Note the changes in bold.void setupscreen()
/* REMOVE THIS ENTIRE SECTION OF COMMENTED CODE
//create the virtual background
scroll = create_bitmap(MAPW, MAPH);
Trang 35//load the tile bitmap
tiles = load_bitmap(“tiles.bmp”, NULL);
//now draw tiles on virtual background
for (tiley=0; tiley < scroll->h; tiley+=TILEH)
{
for (tilex=0; tilex < scroll->w; tilex+=TILEW)
{
//use the result of grabframe directly in blitter
blit(grabframe(tiles, TILEW+1, TILEH+1, 0, 0, COLS, map[n++]),
scroll, 0, 0, tilex, tiley, TILEW, TILEH);
//load screen background
back = load_bitmap(“background.bmp”, NULL);
Trang 36//create the double buffer
buffer = create_bitmap(WIDTH, HEIGHT);
Now open up the tank.c file and scroll down to the movetankfunction Down at the bottom
of the function, you’ll see the section of code that keeps the tank inside the boundary of themap This was based on the virtual background bitmap’s width and height, but now itneeds to be based on the Mappy level size instead The mapwidth,mapblockwidth,mapheight,and mapblockheight variables are global and found inside mappyal.h Make the changesnoted in bold
//keep tank inside bounds
Trang 37Now open up the main.c file The first thing you need to do in main.c is remove the huge
map[]array definition (with included map tile values) Just delete the whole array, including
the#define B 39line I won’t list the commented-out code here because the map
defini-tion was quite large, but here are the first three lines (for the speed readers out there who
tend to miss entire pages at a time):
//#define B 39
//int map[MAPW*MAPH] = {
// B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,
Don’t forget to delete the rest of the maparray definition that follows these lines
Next, scroll down to the main function and add the code that loads the Mappy file, as
shown in the bold lines that follow