home *** CD-ROM | disk | FTP | other *** search
/ Game Programming - All in One (3rd Edition) / game_prog_all_in_one_3rd_ed.iso / sources / chapter15 / Warbirds / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  2006-09-15  |  16.7 KB  |  696 lines

  1. /////////////////////////////////////////////////////////
  2. // Game Programming All In One, Third Edition
  3. // Chapter 15 - Warbirds
  4. /////////////////////////////////////////////////////////
  5.  
  6. #include "warbirds.h"
  7.  
  8.  
  9. //reuse our friendly tile grabber from chapter 9
  10. BITMAP *grabframe(BITMAP *source, 
  11.                   int width, int height, 
  12.                   int startx, int starty, 
  13.                   int columns, int frame)
  14. {
  15.     BITMAP *temp = create_bitmap(width,height);
  16.  
  17.     int x = startx + (frame % columns) * width;
  18.     int y = starty + (frame / columns) * height;
  19.  
  20.     blit(source,temp,x,y,0,0,width,height);
  21.  
  22.     return temp;
  23. }
  24.  
  25.  
  26. void loadsprites(void)
  27. {
  28.     int n;
  29.  
  30.     //load progress bar
  31.     temp = load_bitmap("progress.bmp", NULL);
  32.     progress = grabframe(temp,130,14,0,0,1,0);
  33.     bar = grabframe(temp,6,10,130,2,1,0);
  34.     destroy_bitmap(temp);
  35.  
  36.     //load bonus shot
  37.     bonus_shot_image = load_bitmap("bonusshot.bmp", NULL);
  38.     bonus_shot = (SPRITE*)malloc(sizeof(SPRITE));
  39.     bonus_shot->alive=0;
  40.     bonus_shot->x = 0;
  41.     bonus_shot->y = 0;
  42.     bonus_shot->width = bonus_shot_image->w;
  43.     bonus_shot->height = bonus_shot_image->h;
  44.     bonus_shot->xdelay = 0;
  45.     bonus_shot->ydelay = 2;
  46.     bonus_shot->xcount = 0;
  47.     bonus_shot->ycount = 0;
  48.     bonus_shot->xspeed = 0;
  49.     bonus_shot->yspeed = 1;
  50.     bonus_shot->curframe = 0;
  51.     bonus_shot->maxframe = 0;
  52.     bonus_shot->framecount = 0;
  53.     bonus_shot->framedelay = 0;
  54.  
  55.  
  56.     //load player airplane sprite
  57.     temp = load_bitmap("p38.bmp", NULL);
  58.     for (n=0; n<3; n++)
  59.         player_images[n] = grabframe(temp,64,64,0,0,3,n);
  60.     destroy_bitmap(temp);
  61.  
  62.     //initialize the player's sprite
  63.     player = (SPRITE*)malloc(sizeof(SPRITE));
  64.     player->x = 320-32;
  65.     player->y = 400;
  66.     player->width = player_images[0]->w;
  67.     player->height = player_images[0]->h;
  68.     player->xdelay = 1;
  69.     player->ydelay = 0;
  70.     player->xcount = 0;
  71.     player->ycount = 0;
  72.     player->xspeed = 0;
  73.     player->yspeed = 0;
  74.     player->curframe = 0;
  75.     player->maxframe = 2;
  76.     player->framecount = 0;
  77.     player->framedelay = 10;
  78.     player->animdir = 1;
  79.  
  80.     //load bullet images
  81.     bullet_images[0] = load_bitmap("bullets.bmp", NULL);
  82.  
  83.     //initialize the bullet sprites
  84.     for (n=0; n<MAX_BULLETS; n++)
  85.     {
  86.         bullets[n] = (SPRITE*)malloc(sizeof(SPRITE));
  87.         bullets[n]->alive = 0;
  88.         bullets[n]->x = 0;
  89.         bullets[n]->y = 0;
  90.         bullets[n]->width = bullet_images[0]->w;
  91.         bullets[n]->height = bullet_images[0]->h;
  92.         bullets[n]->xdelay = 0;
  93.         bullets[n]->ydelay = 0;
  94.         bullets[n]->xcount = 0;
  95.         bullets[n]->ycount = 0;
  96.         bullets[n]->xspeed = 0;
  97.         bullets[n]->yspeed = -2;
  98.         bullets[n]->curframe = 0;
  99.         bullets[n]->maxframe = 0;
  100.         bullets[n]->framecount = 0;
  101.         bullets[n]->framedelay = 0;
  102.         bullets[n]->animdir = 0;
  103.     }
  104.  
  105.     //load enemy plane sprites
  106.     temp = load_bitmap("enemyplane1.bmp", NULL);
  107.     for (n=0; n<3; n++)
  108.         enemy_plane_images[n] = grabframe(temp,32,32,0,0,3,n);
  109.     destroy_bitmap(temp);
  110.  
  111.     //initialize the enemy planes
  112.     for (n=0; n<MAX_ENEMIES; n++)
  113.     {
  114.         enemy_planes[n] = (SPRITE*)malloc(sizeof(SPRITE));
  115.         enemy_planes[n]->alive = 0;
  116.         enemy_planes[n]->x = rand() % 100 + 50;
  117.         enemy_planes[n]->y = 0;
  118.         enemy_planes[n]->width = enemy_plane_images[0]->w;
  119.         enemy_planes[n]->height = enemy_plane_images[0]->h;
  120.         enemy_planes[n]->xdelay = 4;
  121.         enemy_planes[n]->ydelay = 4;
  122.         enemy_planes[n]->xcount = 0;
  123.         enemy_planes[n]->ycount = 0;
  124.         enemy_planes[n]->xspeed = (rand() % 2 - 3);
  125.         enemy_planes[n]->yspeed = 1;
  126.         enemy_planes[n]->curframe = 0;
  127.         enemy_planes[n]->maxframe = 2;
  128.         enemy_planes[n]->framecount = 0;
  129.         enemy_planes[n]->framedelay = 10;
  130.         enemy_planes[n]->animdir = 1;
  131.     }
  132.  
  133.     //load explosion sprites
  134.     temp = load_bitmap("explosion.bmp", NULL);
  135.     for (n=0; n<6; n++)
  136.         explosion_images[n] = grabframe(temp,32,32,0,0,6,n);
  137.     destroy_bitmap(temp);
  138.  
  139.     //initialize the sprites
  140.     for (n=0; n<MAX_EXPLOSIONS; n++)
  141.     {
  142.         explosions[n] = (SPRITE*)malloc(sizeof(SPRITE));
  143.         explosions[n]->alive = 0;
  144.         explosions[n]->x = 0;
  145.         explosions[n]->y = 0;
  146.         explosions[n]->width = explosion_images[0]->w;
  147.         explosions[n]->height = explosion_images[0]->h;
  148.         explosions[n]->xdelay = 0;
  149.         explosions[n]->ydelay = 8;
  150.         explosions[n]->xcount = 0;
  151.         explosions[n]->ycount = 0;
  152.         explosions[n]->xspeed = 0;
  153.         explosions[n]->yspeed = -1;
  154.         explosions[n]->curframe = 0;
  155.         explosions[n]->maxframe = 5;
  156.         explosions[n]->framecount = 0;
  157.         explosions[n]->framedelay = 15;
  158.         explosions[n]->animdir = 1;
  159.     }
  160.  
  161.     //load explosion sprites
  162.     temp = load_bitmap("bigexplosion.bmp", NULL);
  163.     for (n=0; n<8; n++)
  164.         bigexp_images[n] = grabframe(temp,64,64,0,0,7,n);
  165.     destroy_bitmap(temp);
  166.  
  167.     //initialize the sprites
  168.     bigexp = (SPRITE*)malloc(sizeof(SPRITE));
  169.     bigexp->alive = 0;
  170.     bigexp->x = 0;
  171.     bigexp->y = 0;
  172.     bigexp->width = bigexp_images[0]->w;
  173.     bigexp->height = bigexp_images[0]->h;
  174.     bigexp->xdelay = 0;
  175.     bigexp->ydelay = 8;
  176.     bigexp->xcount = 0;
  177.     bigexp->ycount = 0;
  178.     bigexp->xspeed = 0;
  179.     bigexp->yspeed = -1;
  180.     bigexp->curframe = 0;
  181.     bigexp->maxframe = 6;
  182.     bigexp->framecount = 0;
  183.     bigexp->framedelay = 10;
  184.     bigexp->animdir = 1;
  185.  
  186. }
  187.  
  188. int inside(int x,int y,int left,int top,int right,int bottom)
  189. {
  190.     if (x > left && x < right && y > top && y < bottom)
  191.         return 1;
  192.     else
  193.         return 0;
  194. }
  195.  
  196. void updatesprite(SPRITE *spr)
  197. {
  198.     //update x position
  199.     if (++spr->xcount > spr->xdelay)
  200.     {
  201.         spr->xcount = 0;
  202.         spr->x += spr->xspeed;
  203.     }
  204.  
  205.     //update y position
  206.     if (++spr->ycount > spr->ydelay)
  207.     {
  208.         spr->ycount = 0;
  209.         spr->y += spr->yspeed;
  210.     }
  211.  
  212.     //update frame based on animdir
  213.     if (++spr->framecount > spr->framedelay)
  214.     {
  215.         spr->framecount = 0;
  216.         if (spr->animdir == -1)
  217.         {
  218.             if (--spr->curframe < 0)
  219.                 spr->curframe = spr->maxframe;
  220.         }
  221.         else if (spr->animdir == 1)
  222.         {
  223.             if (++spr->curframe > spr->maxframe)
  224.                 spr->curframe = 0;
  225.         }
  226.     }
  227. }
  228.  
  229. void startexplosion(int x, int y)
  230. {
  231.     int n;
  232.     for (n=0; n<MAX_EXPLOSIONS; n++)
  233.     {
  234.         if (!explosions[n]->alive)
  235.         {
  236.             explosions[n]->alive++;
  237.             explosions[n]->x = x;
  238.             explosions[n]->y = y;
  239.             break;
  240.         }
  241.     }
  242.  
  243.     //launch bonus shot if ready
  244.     if (!bonus_shot->alive)
  245.     {
  246.         bonus_shot->alive++;
  247.         bonus_shot->x = x;
  248.         bonus_shot->y = y;
  249.     }
  250. }
  251.  
  252. void updateexplosions()
  253. {
  254.     int n, c=0;
  255.  
  256.     for (n=0; n<MAX_EXPLOSIONS; n++)
  257.     {
  258.         if (explosions[n]->alive)
  259.         {
  260.             c++;
  261.             updatesprite(explosions[n]);
  262.             draw_sprite(buffer, explosion_images[explosions[n]->curframe],
  263.                 explosions[n]->x, explosions[n]->y);
  264.  
  265.             if (explosions[n]->curframe >= explosions[n]->maxframe)
  266.             {
  267.                 explosions[n]->curframe=0;
  268.                 explosions[n]->alive=0;
  269.             }
  270.         }
  271.     }
  272.     textprintf_ex(buffer,font,0,430,WHITE,-1,
  273.         "explosions %d", c);
  274.  
  275.     //update the big "player" explosion if needed
  276.     if (bigexp->alive)
  277.     {
  278.         updatesprite(bigexp);
  279.         draw_sprite(buffer, bigexp_images[bigexp->curframe], 
  280.             bigexp->x, bigexp->y);
  281.         if (bigexp->curframe >= bigexp->maxframe)
  282.         {
  283.             bigexp->curframe=0;
  284.             bigexp->alive=0;
  285.         }
  286.     }
  287. }
  288.  
  289. void updatebonuses()
  290. {
  291.     int x,y,x1,y1,x2,y2;
  292.  
  293.     //add more bonuses here
  294.  
  295.     //update bonus shot if alive
  296.     if (bonus_shot->alive)
  297.     {
  298.         updatesprite(bonus_shot);
  299.         draw_sprite(buffer, bonus_shot_image, bonus_shot->x, bonus_shot->y);
  300.         if (bonus_shot->y > HEIGHT)
  301.             bonus_shot->alive=0;
  302.  
  303.         //see if player got the bonus
  304.         x = bonus_shot->x + bonus_shot->width/2;
  305.         y = bonus_shot->y + bonus_shot->height/2;
  306.         x1 = player->x;
  307.         y1 = player->y;
  308.         x2 = x1 + player->width;
  309.         y2 = y1 + player->height;
  310.  
  311.         if (inside(x,y,x1,y1,x2,y2))
  312.         {
  313.             //increase firing rate
  314.             if (firedelay>20) firedelay-=2;
  315.  
  316.             bonus_shot->alive=0;
  317.         }
  318.     }
  319.  
  320. }
  321.  
  322. void updatebullet(SPRITE *spr)
  323. {
  324.     int n,x,y;
  325.     int x1,y1,x2,y2;
  326.  
  327.     //move the bullet
  328.     updatesprite(spr);
  329.  
  330.     //check bounds
  331.     if (spr->y < 0)
  332.     {
  333.         spr->alive = 0;
  334.         return;
  335.     }
  336.  
  337.     for (n=0; n<MAX_ENEMIES; n++)
  338.     {
  339.         if (enemy_planes[n]->alive)
  340.         {
  341.             //find center of bullet
  342.             x = spr->x + spr->width/2;
  343.             y = spr->y + spr->height/2;
  344.  
  345.             //get enemy plane bounding rectangle
  346.             x1 = enemy_planes[n]->x;
  347.             y1 = enemy_planes[n]->y - yoffset;
  348.             x2 = x1 + enemy_planes[n]->width;
  349.             y2 = y1 + enemy_planes[n]->height;
  350.  
  351.             //check for collisions
  352.             if (inside(x, y, x1, y1, x2, y2))
  353.             {
  354.                 enemy_planes[n]->alive=0;
  355.                 spr->alive=0;
  356.                 startexplosion(spr->x+16, spr->y);
  357.                 score+=2;
  358.                 break;
  359.             }
  360.         }
  361.     }
  362. }
  363.  
  364. void updatebullets()
  365. {
  366.     int n;
  367.     //update/draw bullets
  368.     for (n=0; n<MAX_BULLETS; n++)
  369.         if (bullets[n]->alive)
  370.         {
  371.             updatebullet(bullets[n]);
  372.             draw_sprite(buffer,bullet_images[0], bullets[n]->x, bullets[n]->y);
  373.         }
  374. }
  375.  
  376. void bouncex_warpy(SPRITE *spr)
  377. {
  378.     //bounces x off bounds
  379.     if (spr->x < 0 - spr->width)
  380.     {
  381.         spr->x = 0 - spr->width + 1;
  382.         spr->xspeed *= -1;
  383.     }
  384.  
  385.     else if (spr->x > SCREEN_W)
  386.     {
  387.         spr->x = SCREEN_W - spr->xspeed;
  388.         spr->xspeed *= -1;
  389.     }
  390.  
  391.     //warps y if plane has passed the player
  392.     if (spr->y > yoffset + 2000)
  393.     {
  394.         //respawn enemy plane
  395.         spr->y = yoffset - 1000 - rand() % 1000;
  396.         spr->alive++;
  397.         spr->x = rand() % WIDTH;
  398.     }
  399.  
  400.     //warps y from bottom to top of level
  401.     if (spr->y < 0)
  402.     {
  403.         spr->y = 0;
  404.     }
  405.  
  406.     else if (spr->y > 48000)
  407.     {
  408.         spr->y = 0;
  409.     }
  410.  
  411. }
  412.  
  413.  
  414. void fireatenemy()
  415. {
  416.     int n;
  417.     for (n=0; n<MAX_BULLETS; n++)
  418.     {
  419.         if (!bullets[n]->alive)
  420.         {
  421.             bullets[n]->alive++;
  422.             bullets[n]->x = player->x;
  423.             bullets[n]->y = player->y;
  424.             return;
  425.         }
  426.     }
  427. }
  428.  
  429. void displayprogress(int life)
  430. {
  431.     int n;
  432.     draw_sprite(buffer,progress,490,15);
  433.     
  434.     for (n=0; n<life; n++)
  435.         draw_sprite(buffer,bar,492+n*5,17);
  436.     
  437. }
  438.  
  439. void updateenemyplanes()
  440. {
  441.     int n, c=0;
  442.  
  443.     //update/draw enemy planes
  444.     for (n=0; n<MAX_ENEMIES; n++)
  445.     {
  446.         if (enemy_planes[n]->alive)
  447.         {
  448.             c++;
  449.             updatesprite(enemy_planes[n]);
  450.             bouncex_warpy(enemy_planes[n]);
  451.  
  452.             //is plane visible on screen?
  453.             if (enemy_planes[n]->y > yoffset-32 && enemy_planes[n]->y < yoffset + HEIGHT+32)
  454.             {
  455.                 //draw enemy plane
  456.                 draw_sprite(buffer, enemy_plane_images[enemy_planes[n]->curframe],
  457.                     enemy_planes[n]->x, enemy_planes[n]->y - yoffset);
  458.             }
  459.         }
  460.         //reset plane
  461.         else
  462.         {
  463.             enemy_planes[n]->alive++;
  464.             enemy_planes[n]->x = rand() % 100 + 50;
  465.             enemy_planes[n]->y = yoffset - 2000 + rand() % 2000;
  466.         }
  467.     }
  468.     textprintf_ex(buffer,font,0,470,WHITE,-1,
  469.         "enemies %d", c);
  470. }
  471.  
  472. void updatescroller()
  473. {
  474.     //make sure it doesn't scroll beyond map edge
  475.     if (yoffset < 5) 
  476.     {
  477.         //level is over
  478.         yoffset = 5;
  479.         textout_centre_ex(buffer, font, "END OF LEVEL",
  480.             SCREEN_W/2, SCREEN_H/2, WHITE, -1);
  481.     }
  482.     if (yoffset > BOTTOM) yoffset = BOTTOM;
  483.  
  484.  
  485.     //scroll map up 1 pixel
  486.     yoffset-=1;
  487.  
  488.     //draw map with single layer
  489.     MapDrawBG(buffer, 0, yoffset, 0, 0, SCREEN_W-1, SCREEN_H-1);
  490.  
  491.  
  492. }
  493.  
  494. void updateplayer()
  495. {
  496.     int n,x,y,x1,y1,x2,y2;
  497.  
  498.     //update/draw player sprite
  499.     updatesprite(player);
  500.     draw_sprite(buffer, player_images[player->curframe], 
  501.         player->x, player->y);
  502.  
  503.     //check for collision with enemy planes
  504.     x = player->x + player->width/2;
  505.     y = player->y + player->height/2;
  506.     for (n=0; n<MAX_ENEMIES; n++)
  507.     {
  508.         if (enemy_planes[n]->alive)
  509.         {
  510.             x1 = enemy_planes[n]->x;
  511.             y1 = enemy_planes[n]->y - yoffset;
  512.             x2 = x1 + enemy_planes[n]->width;
  513.             y2 = y1 + enemy_planes[n]->height;
  514.             if (inside(x,y,x1,y1,x2,y2))
  515.             {
  516.                 enemy_planes[n]->alive=0;
  517.                 if (health > 0) health--;
  518.                 bigexp->alive++;
  519.                 bigexp->x = player->x;
  520.                 bigexp->y = player->y;
  521.                 score++;
  522.             }
  523.         }
  524.     }
  525. }
  526.  
  527. void displaystats()
  528. {
  529.     //display some status information
  530.     textprintf_ex(buffer,font,0,420,WHITE,-1,
  531.         "firing rate %d", firedelay);
  532.     textprintf_ex(buffer,font,0,440,WHITE,-1,
  533.         "yoffset %d",yoffset);
  534.     textprintf_ex(buffer,font,0,450,WHITE,-1,
  535.         "counter %d", counter);
  536.     textprintf_ex(buffer,font,0,460,WHITE,-1,
  537.         "framerate %d", framerate);
  538.  
  539.     //display score
  540.     textprintf_ex(buffer,font,22,22,GRAY,-1,
  541.         "SCORE: %d", score);
  542.     textprintf_ex(buffer,font,20,20,RED,-1,
  543.         "SCORE: %d", score);
  544. }
  545.  
  546. void checkinput()
  547. {
  548.     //check for keyboard input
  549.     if (key[KEY_UP])
  550.     {
  551.         player->y -= 1;
  552.         if (player->y < 100)
  553.             player->y = 100;
  554.     }
  555.     if (key[KEY_DOWN])
  556.     {
  557.         player->y += 1;
  558.         if (player->y > HEIGHT-65)
  559.             player->y = HEIGHT-65;
  560.     }
  561.     if (key[KEY_LEFT])
  562.     {
  563.         player->x -= 1;
  564.         if (player->x < 0)
  565.             player->x = 0;
  566.     }
  567.     if (key[KEY_RIGHT])
  568.     {
  569.         player->x += 1;
  570.         if (player->x > WIDTH-65)
  571.             player->x = WIDTH-65;
  572.     }
  573.  
  574.     if (key[KEY_SPACE])
  575.     {
  576.         if (firecount > firedelay)
  577.         {
  578.             firecount = 0;
  579.             fireatenemy();
  580.         }
  581.     }
  582.  
  583. }
  584.  
  585. //calculate framerate every second
  586. void timer1(void)
  587. {
  588.     counter++;
  589.     framerate = ticks;
  590.     ticks=0;
  591.     rest(2);
  592. }
  593. END_OF_FUNCTION(timer1)
  594.  
  595. void initialize()
  596. {
  597.     //initialize program
  598.     allegro_init();    
  599.     install_timer();
  600.     install_keyboard();
  601.     set_color_depth(16);
  602.     set_gfx_mode(MODE, WIDTH, HEIGHT, 0, 0);
  603.     srand(time(NULL));
  604.  
  605.     //create the double buffer and clear it
  606.     buffer = create_bitmap(SCREEN_W, SCREEN_H);    
  607.     clear(buffer);
  608.  
  609.     //load the Mappy file
  610.     if (MapLoad("level1.fmp") != 0)
  611.     {
  612.         set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
  613.         allegro_message ("Can't find level1.fmp");
  614.         return;
  615.     }
  616.  
  617.     //set palette
  618.     MapSetPal8();
  619.  
  620.     //identify variables used by interrupt function
  621.     LOCK_VARIABLE(counter);
  622.     LOCK_VARIABLE(framerate);
  623.     LOCK_VARIABLE(ticks);
  624.     LOCK_FUNCTION(timer1);
  625.  
  626.     //create new interrupt handler
  627.     install_int(timer1, 1000);
  628. }
  629.  
  630.  
  631. int main (void)
  632. {
  633.     int n;
  634.  
  635.     //init game
  636.     initialize();
  637.     loadsprites();
  638.  
  639.     //main loop
  640.     while (!key[KEY_ESC])
  641.     {
  642.         checkinput();
  643.  
  644.         updatescroller();
  645.  
  646.         updateplayer();
  647.         updateenemyplanes();
  648.  
  649.         updatebullets();            
  650.         updateexplosions();
  651.         updatebonuses();
  652.  
  653.         displayprogress(health);
  654.         displaystats();
  655.  
  656.         //blit the double buffer
  657.         acquire_screen();
  658.         blit (buffer, screen, 0, 0, 0, 0, SCREEN_W-1, SCREEN_H-1);
  659.         release_screen();
  660.  
  661.         ticks++;
  662.         firecount++;
  663.     }
  664.  
  665.     //delete the Mappy level
  666.     MapFreeMem();
  667.  
  668.     //delete bitmaps
  669.     destroy_bitmap(buffer);
  670.     destroy_bitmap(progress);
  671.     destroy_bitmap(bar);
  672.  
  673.     for (n=0; n<6; n++)
  674.         destroy_bitmap(explosion_images[n]);
  675.  
  676.     for (n=0; n<3; n++)
  677.     {
  678.         destroy_bitmap(player_images[n]);
  679.         destroy_bitmap(bullet_images[n]);
  680.         destroy_bitmap(enemy_plane_images[n]);
  681.     }
  682.  
  683.     //delete sprites
  684.     free(player);
  685.     for (n=0; n<MAX_EXPLOSIONS; n++)
  686.         free(explosions[n]);
  687.     for (n=0; n<MAX_BULLETS; n++)
  688.         free(bullets[n]);
  689.     for (n=0; n<MAX_ENEMIES; n++)
  690.         free(enemy_planes[n]);
  691.  
  692.     allegro_exit();
  693.     return 0;
  694. }
  695. END_OF_MAIN()
  696.