Game Programming All in One 2 nd Edition phần 7 pot

74 241 0
Game Programming All in One 2 nd Edition phần 7 pot

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Modifying 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. SPRITE mytanks[2]; SPRITE *tanks[2]; SPRITE mybullets[2]; SPRITE *bullets[2]; SPRITE *explosions[2]; Next, modify the tank_bmp array, 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_bmp array—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. //sprite bitmaps BITMAP *tank_bmp[2][8][8]; BITMAP *bullet_bmp; BITMAP *explode_bmp; Now scroll down a little further in tankwar.h to the function prototypes and add the fol- lowing three function definitions noted in bold: //function prototypes void 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 the code 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) { if (++tanks[num]->framecount > tanks[num]->framedelay) { tanks[num]->framecount = 0; tanks[num]->curframe += tanks[num]->animdir; if (tanks[num]->curframe > tanks[num]->maxframe) tanks[num]->curframe = 0; 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 the new animated frames in the tank_bmp array. Make the changes noted in bold. (You’ll notice that the only changes are made to draw_sprite function calls.) void drawtank(int num) { int dir = tanks[num]->dir; int x = tanks[num]->x-15; int y = tanks[num]->y-15; Chapter 11 ■ Timers, Interrupt Handlers, and Multi-Threading416 draw_sprite(buffer, tank_bmp[num][tanks[num]->curframe][dir], x, y); //what about the enemy tank? x = scrollx[!num] + SCROLLW/2; y = scrolly[!num] + SCROLLH/2; if (inside(x, y, scrollx[num], scrolly[num], scrollx[num] + SCROLLW, scrolly[num] + SCROLLH)) { //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 movetank function 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 if (speed > 0) { tanks[num]->animdir = 1; tanks[num]->framedelay = MAXSPEED - speed; } else if (speed < 0) { tanks[num]->animdir = -1; tanks[num]->framedelay = MAXSPEED - abs(speed); } else tanks[num]->animdir = 0; //update tank position switch(dir) Enhancing Tank War 417 { case 0: scrolly[num] -= speed; break; case 1: scrolly[num] -= speed; scrollx[num] += speed; break; case 2: scrollx[num] += speed; break; case 3: scrollx[num] += speed; scrolly[num] += speed; break; case 4: scrolly[num] += speed; break; case 5: scrolly[num] += speed; scrollx[num] -= speed; break; case 6: scrollx[num] -= speed; break; case 7: scrollx[num] -= speed; scrolly[num] -= speed; break; } //keep tank inside bounds if (scrollx[num] < 0) { scrollx[num] = 0; tanks[num]->xspeed = 0; } else if (scrollx[num] > scroll->w - SCROLLW) { scrollx[num] = scroll->w - SCROLLW; tanks[num]->xspeed = 0; } if (scrolly[num] < 0) Chapter 11 ■ Timers, Interrupt Handlers, and Multi-Threading418 { scrolly[num] = 0; tanks[num]->xspeed = 0; } else if (scrolly[num] > scroll->h - SCROLLH) { scrolly[num] = scroll->h - SCROLLH; tanks[num]->xspeed = 0; } } That is the last change to tank.c. Now you can move on to the setup.c file. Updating setup.c You 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 loadsprites function and a lot of changes to setuptanks . First, add the new loadsprites function to the top of the setup.c file. I won’t use bold because you need to add the whole function to the program. void loadsprites() { //load explosion image if (explode_bmp == NULL) { explode_bmp = load_bitmap(“explode.bmp”, NULL); } //initialize explosion sprites explosions[0] = malloc(sizeof(SPRITE)); explosions[1] = malloc(sizeof(SPRITE)); } 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. void setuptanks() { BITMAP *temp; int anim; int n; //configure player 1’s tank tanks[0] = &mytanks[0]; Enhancing Tank War 419 tanks[0]->x = 30; tanks[0]->y = 40; tanks[0]->xspeed = 0; tanks[0]->dir = 3; tanks[0]->curframe = 0; tanks[0]->maxframe = 7; tanks[0]->framecount = 0; tanks[0]->framedelay = 10; tanks[0]->animdir = 0; scores[0] = 0; //load first tank temp = load_bitmap(“tank1.bmp”, NULL); for (anim=0; anim<8; anim++) { //grab animation frame tank_bmp[0][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[0][anim][n] = create_bitmap(32, 32); clear_to_color(tank_bmp[0][anim][n], makecol(255,0,255)); rotate_sprite(tank_bmp[0][anim][n], tank_bmp[0][anim][0], 0, 0, itofix(n*32)); } } destroy_bitmap(temp); //configure player 2’s tank tanks[1] = &mytanks[1]; tanks[1]->x = SCREEN_W-30; tanks[1]->y = SCREEN_H-30; tanks[1]->xspeed = 0; tanks[1]->dir = 7; tanks[1]->curframe = 0; tanks[1]->maxframe = 7; tanks[1]->framecount = 0; tanks[1]->framedelay = 10; tanks[1]->animdir = 0; scores[1] = 0; Chapter 11 ■ Timers, Interrupt Handlers, and Multi-Threading420 //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], 0, 0, itofix(n*32)); } } destroy_bitmap(temp); //load bullet image if (bullet_bmp == NULL) bullet_bmp = load_bitmap(“bullet.bmp”, NULL); //initialize bullets for (n=0; n<2; n++) { bullets[n] = &mybullets[n]; bullets[n]->x = 0; bullets[n]->y = 0; bullets[n]->width = bullet_bmp->w; bullets[n]->height = bullet_bmp->h; } //center tanks inside scroll windows tanks[0]->x = 5 + SCROLLW/2; tanks[0]->y = 90 + SCROLLH/2; tanks[1]->x = 325 + SCROLLW/2; tanks[1]->y = 90 + SCROLLH/2; } 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 Updating bullet.c Now you can make the necessary changes to the bullet.c source file to accommodate the new friendly explosions. (How’s that for a contradiction of terms?) What I mean by friendly is that the explosions will no longer use the rest function to draw. This is really bad because it causes the whole game to hiccup every time there is an explosion to be drawn. There weren’t many bullets flying around in this game, or I never would have got- ten away with this quick solution. Now let’s correct the problem. Open the bullet.c file. You’ll be adding a new function called updateexplosion and modify- ing the existing explode function. Here is the new updateexplosion you should add to the top of the bullet.c file. //new function added in chapter 11 void updateexplosion(int num) { int x, y; if (!explosions[num]->alive) return; //draw explosion (maxframe) times if (explosions[num]->curframe++ < explosions[num]->maxframe) { x = explosions[num]->x; y = explosions[num]->y; //draw explosion in enemy window rotate_sprite(buffer, explode_bmp, x + rand()%10 - 20, y + rand()%10 - 20, itofix(rand()%255)); //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)); Chapter 11 ■ Timers, Interrupt Handlers, and Multi-Threading422 } } else { explosions[num]->alive = 0; explosions[num]->curframe = 0; } } Now modify explode so 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) { //initialize the explosion sprite explosions[num]->alive = 1; explosions[num]->x = x; explosions[num]->y = y; explosions[num]->curframe = 0; explosions[num]->maxframe = 20; } 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 animatetank and updateexplosion ). The only changes to be made will be to the main function. You need to add a line that creates a new variable and calls loadsprites and animatetank , and finally, you need a call to updateexplosion . Be careful to catch the changes to tank_bmp and note the cleanup code at the end. Make the changes noted in bold. //main function void main(void) { int anim; //initialize the game allegro_init(); install_keyboard(); install_timer(); srand(time(NULL)); Enhancing Tank War 423 setupscreen(); setuptanks(); loadsprites(); //game loop while(!gameover) { //move the tanks and bullets for (n=0; n<2; n++) { movetank(n); animatetank(n); movebullet(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++) Chapter 11 ■ Timers, Interrupt Handlers, and Multi-Threading424 [...]... stored inside the map file rather than in the source code) Figure 12. 12 shows the TestMappy program running #include #include #include #include “allegro.h” “mappyal.h” Loading and Drawing Mappy Level Files Figure 12. 12 The TestMappy program demonstrates how to load a native Mappy file #define #define #define #define MODE GFX_AUTODETECT_FULLSCREEN WIDTH 640 HEIGHT 480 WHITE makecol (25 5 ,25 5 ,25 5)... horizontal and vertical scrolling games T Here is a breakdown of the major topics in this chapter: I I Creating the game world 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... again and paste 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 your map files I’ll explain how to store game resources (such as map files) inside an encrypted/ compressed data file in Chapter 16, “Using... level 4 37 438 Chapter 12 I Creating a Game World: Editing Tiles and Levels If 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 \chapter 12\ ArrayMapTest folder #include “allegro.h” //define some convenient constants #define MODE GFX_AUTODETECT_FULLSCREEN #define WIDTH 640 #define HEIGHT 480 #define STEP... for (n=0; n . ■ Timers, Interrupt Handlers, and Multi-Threading 428 429 Creating a Game World: Editing Tiles and Levels chapter 12 T he game world defines the rules of the game and presents the player with all of. changes noted in bold. //main function void main(void) { int anim; //initialize the game allegro_init(); install_keyboard(); install_timer(); srand(time(NULL)); Enhancing Tank War 423 setupscreen(); setuptanks(); loadsprites(); / /game. explosions[num]->y; //draw explosion in enemy window rotate_sprite(buffer, explode_bmp, x + rand()%10 - 20 , y + rand()%10 - 20 , itofix(rand() %25 5)); //draw explosion in “my” window if enemy is visible x

Ngày đăng: 12/08/2014, 19:20

Mục lục

  • CH 12 Creating a Game World: Editing Tiles and Levels

  • CH 13 Vertical Scrolling Arcade Games

Tài liệu cùng người dùng

Tài liệu liên quan