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

  1. /////////////////////////////////////////////////////////////////////
  2. // Game Programming All In One, Third Edition
  3. // Chapter 8 - Tank War Game (Enhancement 3)
  4. /////////////////////////////////////////////////////////////////////
  5.  
  6. #include "tankwar.h"
  7.  
  8. /////////////////////////////////////////////////////////////////////
  9. // drawtank function
  10. // display the tank bitmap in the current direction
  11. /////////////////////////////////////////////////////////////////////
  12. void drawtank(int num)
  13. {
  14.     int dir = tanks[num].dir;
  15.     int x = tanks[num].x-15;
  16.     int y = tanks[num].y-15;
  17.     draw_sprite(screen, tank_bmp[num][dir], x, y);
  18. }
  19.  
  20. /////////////////////////////////////////////////////////////////////
  21. // erasetank function
  22. // erase the tank using rectfill
  23. /////////////////////////////////////////////////////////////////////
  24. void erasetank(int num)
  25. {
  26.     int x = tanks[num].x-17;
  27.     int y = tanks[num].y-17;
  28.     rectfill(screen, x, y, x+33, y+33, BLACK);
  29. }
  30.  
  31. /////////////////////////////////////////////////////////////////////
  32. // movetank function
  33. // move the tank in the current direction
  34. /////////////////////////////////////////////////////////////////////
  35. void movetank(int num){
  36.     int dir = tanks[num].dir;
  37.     int speed = tanks[num].speed;
  38.  
  39.     //update tank position based on direction
  40.     switch(dir)
  41.     {
  42.         case 0:
  43.             tanks[num].y -= speed;
  44.             break;
  45.         case 1:
  46.             tanks[num].x += speed;
  47.             tanks[num].y -= speed;
  48.             break;
  49.         case 2:
  50.             tanks[num].x += speed;
  51.             break;
  52.         case 3:
  53.             tanks[num].x += speed;
  54.             tanks[num].y += speed;
  55.             break;
  56.         case 4:
  57.             tanks[num].y += speed;
  58.             break;
  59.         case 5:
  60.             tanks[num].x -= speed;
  61.             tanks[num].y += speed;
  62.             break;
  63.         case 6:
  64.             tanks[num].x -= speed;
  65.             break;
  66.         case 7:
  67.             tanks[num].x -= speed;
  68.             tanks[num].y -= speed;
  69.             break;
  70.     }
  71.  
  72.     //keep tank inside the screen
  73.     if (tanks[num].x > SCREEN_W-22)
  74.     {
  75.         tanks[num].x = SCREEN_W-22;
  76.         tanks[num].speed = 0;
  77.     }
  78.     if (tanks[num].x < 22)
  79.     {
  80.         tanks[num].x = 22;
  81.         tanks[num].speed = 0;
  82.     }
  83.     if (tanks[num].y > SCREEN_H-22)
  84.     {
  85.         tanks[num].y = SCREEN_H-22;
  86.         tanks[num].speed = 0;
  87.     }
  88.     if (tanks[num].y < 22)
  89.     {
  90.         tanks[num].y = 22;
  91.         tanks[num].speed = 0;
  92.     }
  93. }
  94.  
  95. /////////////////////////////////////////////////////////////////////
  96. // explode function
  97. // display an explosion image
  98. /////////////////////////////////////////////////////////////////////
  99. void explode(int num, int x, int y)
  100. {
  101.     int n;
  102.  
  103.     //load explode image
  104.     if (explode_bmp == NULL)
  105.     {
  106.         explode_bmp = load_bitmap("explode.bmp", NULL);
  107.     }
  108.     
  109.     //draw the explosion bitmap several times
  110.     for (n = 0; n < 5; n++)
  111.     {
  112.         rotate_sprite(screen, explode_bmp, 
  113.             x + rand()%10 - 20, y + rand()%10 - 20, 
  114.             itofix(rand()%255));
  115.  
  116.         rest(30);
  117.     }
  118.  
  119.     //clear the explosion
  120.     circlefill(screen, x, y, 50, BLACK);
  121.    
  122. }
  123.  
  124. /////////////////////////////////////////////////////////////////////
  125. // updatebullet function
  126. // update the position of a bullet
  127. /////////////////////////////////////////////////////////////////////
  128. void updatebullet(int num)
  129. {
  130.     int x = bullets[num].x;
  131.     int y = bullets[num].y;
  132.     int tx, ty;
  133.  
  134.     //is the bullet active?
  135.     if (!bullets[num].alive) return;
  136.     
  137.     //erase bullet
  138.     rectfill(screen, x, y, x+10, y+10, BLACK);        
  139.  
  140.     //move bullet
  141.     bullets[num].x += bullets[num].xspd;
  142.     bullets[num].y += bullets[num].yspd;
  143.     x = bullets[num].x;
  144.     y = bullets[num].y;
  145.  
  146.     //stay within the screen
  147.     if (x < 6 || x > SCREEN_W-6 || y < 20 || y > SCREEN_H-6)
  148.     {
  149.         bullets[num].alive = 0;
  150.         return;
  151.     }
  152.  
  153.     //look for a direct hit using basic collision
  154.     //tank is either 0 or 1, so negative num = other tank
  155.     tx = tanks[!num].x;
  156.     ty = tanks[!num].y;
  157.     if (x > tx-16 && x < tx+16 && y > ty-16 && y < ty+16)
  158.     {
  159.         //kill the bullet
  160.         bullets[num].alive = 0;
  161.             
  162.         //blow up the tank
  163.         explode(num, x, y);
  164.         score(num);
  165.     }
  166.     else
  167.     //if no hit then draw the bullet
  168.     {
  169.         //draw bullet sprite
  170.         draw_sprite(screen, bullet_bmp, x, y);
  171.  
  172.         //update the bullet positions (for debugging)
  173.         textprintf_ex(screen, font, SCREEN_W/2-50, 1, TAN, 0,
  174.             "B1 %-3dx%-3d  B2 %-3dx%-3d", 
  175.             bullets[0].x, bullets[0].y, 
  176.             bullets[1].x, bullets[1].y);
  177.     }
  178. }
  179.  
  180.  
  181. /////////////////////////////////////////////////////////////////////
  182. // fireweapon function
  183. // set bullet direction and speed and activate it
  184. /////////////////////////////////////////////////////////////////////
  185. void fireweapon(int num)
  186. {
  187.     int x = tanks[num].x;
  188.     int y = tanks[num].y;
  189.  
  190.     //load bullet image if necessary
  191.     if (bullet_bmp == NULL)
  192.     {
  193.         bullet_bmp = load_bitmap("bullet.bmp", NULL);
  194.     }
  195.  
  196.     //ready to fire again?
  197.     if (!bullets[num].alive)
  198.     {
  199.         bullets[num].alive = 1;
  200.  
  201.         //fire bullet in direction tank is facing
  202.         switch (tanks[num].dir)
  203.         {
  204.             //north
  205.             case 0:
  206.                 bullets[num].x = x-2;
  207.                 bullets[num].y = y-22;
  208.                 bullets[num].xspd = 0;
  209.                 bullets[num].yspd = -BULLETSPEED;
  210.                 break;
  211.             //NE
  212.             case 1:
  213.                 bullets[num].x = x+18;
  214.                 bullets[num].y = y-18;
  215.                 bullets[num].xspd = BULLETSPEED;
  216.                 bullets[num].yspd = -BULLETSPEED;         
  217.                 break;  
  218.             //east
  219.             case 2:
  220.                 bullets[num].x = x+22;
  221.                 bullets[num].y = y-2;
  222.                 bullets[num].xspd = BULLETSPEED;
  223.                 bullets[num].yspd = 0;
  224.                 break;
  225.             //SE
  226.             case 3:
  227.                 bullets[num].x = x+18;
  228.                 bullets[num].y = y+18;
  229.                 bullets[num].xspd = BULLETSPEED;
  230.                 bullets[num].yspd = BULLETSPEED;
  231.                 break;
  232.             //south
  233.             case 4:
  234.                 bullets[num].x = x-2;
  235.                 bullets[num].y = y+22;
  236.                 bullets[num].xspd = 0;
  237.                 bullets[num].yspd = BULLETSPEED;
  238.                 break;
  239.             //SW
  240.             case 5:
  241.                 bullets[num].x = x-18;
  242.                 bullets[num].y = y+18;
  243.                 bullets[num].xspd = -BULLETSPEED;
  244.                 bullets[num].yspd = BULLETSPEED;
  245.                 break;
  246.             //west
  247.             case 6:
  248.                 bullets[num].x = x-22;
  249.                 bullets[num].y = y-2;
  250.                 bullets[num].xspd = -BULLETSPEED;
  251.                 bullets[num].yspd = 0;
  252.                 break;
  253.             //NW
  254.             case 7:
  255.                 bullets[num].x = x-18;
  256.                 bullets[num].y = y-18;
  257.                 bullets[num].xspd = -BULLETSPEED;
  258.                 bullets[num].yspd = -BULLETSPEED;
  259.                 break;
  260.         }
  261.     }
  262. }
  263.  
  264. /////////////////////////////////////////////////////////////////////
  265. // forward function
  266. // increase the tank's speed
  267. /////////////////////////////////////////////////////////////////////
  268. void forward(int num)
  269. {
  270.     tanks[num].speed++;
  271.     if (tanks[num].speed > MAXSPEED)
  272.         tanks[num].speed = MAXSPEED;
  273. }
  274.  
  275. /////////////////////////////////////////////////////////////////////
  276. // backward function
  277. // decrease the tank's speed
  278. /////////////////////////////////////////////////////////////////////
  279. void backward(int num)
  280. {
  281.     tanks[num].speed--;
  282.     if (tanks[num].speed < -MAXSPEED)
  283.         tanks[num].speed = -MAXSPEED;
  284. }
  285.  
  286. /////////////////////////////////////////////////////////////////////
  287. // turnleft function
  288. // rotate the tank counter-clockwise
  289. /////////////////////////////////////////////////////////////////////
  290. void turnleft(int num)
  291. {
  292.     tanks[num].dir--;
  293.     if (tanks[num].dir < 0)
  294.         tanks[num].dir = 7;
  295. }
  296.  
  297. /////////////////////////////////////////////////////////////////////
  298. // turnright function
  299. // rotate the tank clockwise
  300. /////////////////////////////////////////////////////////////////////
  301. void turnright(int num)
  302. {
  303.     tanks[num].dir++;
  304.     if (tanks[num].dir > 7)
  305.         tanks[num].dir = 0;
  306. }
  307.  
  308. /////////////////////////////////////////////////////////////////////
  309. // getinput function
  310. // check for player input keys (2 player support)
  311. /////////////////////////////////////////////////////////////////////
  312. void getinput()
  313. {
  314.     //hit ESC to quit
  315.     if (key[KEY_ESC])   gameover = 1;
  316.     
  317.     //WASD - SPACE keys control tank 1
  318.     if (key[KEY_W])     forward(0);
  319.     if (key[KEY_D])     turnright(0);
  320.     if (key[KEY_A])     turnleft(0);
  321.     if (key[KEY_S])     backward(0);
  322.     if (key[KEY_SPACE]) fireweapon(0);
  323.             
  324.     //arrow - ENTER keys control tank 2
  325.     if (key[KEY_UP])    forward(1);
  326.     if (key[KEY_RIGHT]) turnright(1);
  327.     if (key[KEY_DOWN])  backward(1);
  328.     if (key[KEY_LEFT])  turnleft(1);
  329.     if (key[KEY_ENTER]) fireweapon(1);
  330.  
  331.     //short delay after keypress        
  332.     rest(20);
  333. }
  334.  
  335. /////////////////////////////////////////////////////////////////////
  336. // score function
  337. // add a point to a player's score
  338. /////////////////////////////////////////////////////////////////////
  339. void score(int player)
  340. {
  341.     //update score
  342.     int points = ++tanks[player].score;
  343.  
  344.     //display score
  345.     textprintf_ex(screen, font, SCREEN_W-70*(player+1), 1, 0,
  346.         BURST, "P%d: %d", player+1, points);
  347. }
  348.  
  349. /////////////////////////////////////////////////////////////////////
  350. // setuptanks function
  351. // load tank bitmaps and position the tank
  352. /////////////////////////////////////////////////////////////////////
  353. void setuptanks()
  354. {
  355.     int n;
  356.     
  357.     //configure player 1's tank
  358.     tanks[0].x = 30;
  359.     tanks[0].y = 40;
  360.     tanks[0].speed = 0;
  361.     tanks[0].score = 0;
  362.     tanks[0].dir = 3;
  363.  
  364.     //load first tank bitmap
  365.     tank_bmp[0][0] = load_bitmap("tank1.bmp", NULL);
  366.     
  367.     //rotate image to generate all 8 directions
  368.     for (n=1; n<8; n++)
  369.     {
  370.         tank_bmp[0][n] = create_bitmap(32, 32);
  371.         clear_bitmap(tank_bmp[0][n]);
  372.         rotate_sprite(tank_bmp[0][n], tank_bmp[0][0], 
  373.             0, 0, itofix(n*32));
  374.     }
  375.  
  376.     //configure player 2's tank
  377.     tanks[1].x = SCREEN_W-30;
  378.     tanks[1].y = SCREEN_H-30;
  379.     tanks[1].speed = 0;
  380.     tanks[1].score = 0;
  381.     tanks[1].dir = 7;
  382.     
  383.     //load second tank bitmap
  384.     tank_bmp[1][0] = load_bitmap("tank2.bmp", NULL);    
  385.     
  386.     //rotate image to generate all 8 directions
  387.     for (n=1; n<8; n++)
  388.     {
  389.         tank_bmp[1][n] = create_bitmap(32, 32);
  390.         clear_bitmap(tank_bmp[1][n]);
  391.         rotate_sprite(tank_bmp[1][n], tank_bmp[1][0], 
  392.             0, 0, itofix(n*32));
  393.     }
  394. }
  395.  
  396.  
  397. /////////////////////////////////////////////////////////////////////
  398. // setupscreen function
  399. // set up the graphics mode and draw the game screen
  400. /////////////////////////////////////////////////////////////////////
  401. void setupscreen()
  402. {
  403.     int ret;
  404.  
  405.     //set video mode    
  406.     set_color_depth(32);
  407.     ret = set_gfx_mode(MODE, WIDTH, HEIGHT, 0, 0);
  408.     if (ret != 0) {
  409.         allegro_message(allegro_error);
  410.         return;
  411.     }
  412.  
  413.     //print title
  414.     textprintf_ex(screen, font, 1, 1, BURST, 0,
  415.         "Tank War - %dx%d", SCREEN_W, SCREEN_H);
  416.  
  417.     //draw screen border        
  418.     rect(screen, 0, 12, SCREEN_W-1, SCREEN_H-1, TAN);
  419.     rect(screen, 1, 13, SCREEN_W-2, SCREEN_H-2, TAN);
  420.    
  421. }
  422.  
  423. /////////////////////////////////////////////////////////////////////
  424. // main function
  425. // start point of the program
  426. /////////////////////////////////////////////////////////////////////
  427. int main(void)
  428. {
  429.     //initialize the game
  430.     allegro_init(); 
  431.     install_keyboard(); 
  432.     install_timer();
  433.     srand(time(NULL));
  434.     setupscreen();
  435.     setuptanks();
  436.  
  437.     //game loop
  438.     while(!gameover)
  439.     {
  440.         textprintf_ex(screen, font, 0, SCREEN_H-10, WHITE, 0,
  441.             "DIRS %d , %d", tanks[0].dir, tanks[1].dir);
  442.         //erase the tanks
  443.         erasetank(0);
  444.         erasetank(1);
  445.         
  446.         //move the tanks
  447.         movetank(0);
  448.         movetank(1);
  449.  
  450.         //draw the tanks
  451.         drawtank(0);
  452.         drawtank(1);
  453.  
  454.         //update the bullets
  455.         updatebullet(0);
  456.         updatebullet(1);
  457.         
  458.         //check for keypresses
  459.         if (keypressed())
  460.             getinput();
  461.  
  462.         //slow the game down
  463.         rest(10);
  464.     }
  465.  
  466.     //end program
  467.     allegro_exit();
  468.     return 0;
  469. }
  470. END_OF_MAIN()
  471.