home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 November / CHIP_2011_11.iso / Programy / Inne / Gry / Atomic_Tanks / Atomic-Tanks-5.1.exe / src / gameloop.cpp < prev    next >
C/C++ Source or Header  |  2011-06-04  |  19KB  |  591 lines

  1. #include <stdio.h>
  2. #include "main.h"
  3. #include "team.h"
  4. #include "files.h"
  5. #include "satellite.h"
  6. #include "update.h"
  7. #include "network.h"
  8. #include "land.h"
  9.  
  10. #include "floattext.h"
  11. #include "explosion.h"
  12. #include "beam.h"
  13. #include "missile.h"
  14. #include "decor.h"
  15. #include "teleport.h"
  16. #include "sky.h"
  17.  
  18. #include "gameloop.h"
  19.  
  20. #ifdef NEW_GAMELOOP
  21.  
  22. int game (GLOBALDATA *global, ENVIRONMENT *env)
  23. {
  24.     int humanPlayers = 0;
  25.     int skippingComputerPlay = FALSE;
  26.     int team_won = NO_WIN;
  27.     int my_class;
  28.     int screen_update = TRUE;
  29.     int text_bounce = 0, text_delta = 1;
  30.     VIRTUAL_OBJECT *my_object;
  31.     TANK *my_tank, *a_tank;
  32.     MISSILE *missile;
  33.     TELEPORT *teleport;
  34.     DECOR *decor;
  35.     BEAM *beam;
  36.     EXPLOSION *explosion;
  37.     FLOATTEXT *floattext;
  38.     SATELLITE *satellite = NULL;
  39.     int count;
  40.     int winner = -1, done = FALSE;
  41.     int stuff_happening = FALSE;
  42.     int AI_clock;
  43.     int fire = FALSE;
  44.     int roundEndCount = 0;
  45.     int game_speed = (int) global->frames_per_second * GAME_SPEED / 60;
  46.     int explosion_in_progress = FALSE;
  47.     
  48.     // adjust for Windows
  49.     #ifdef WIN32
  50.     game_speed /= 1000;
  51.     #endif
  52.  
  53.     global->computerPlayersOnly = FALSE;
  54.     // clear surface
  55.     for (count = 0; count < global->screenWidth; count++)
  56.        env->done[count] = 0;
  57.  
  58.     env->newRound();
  59.     env->Set_Wall_Colour();
  60.     global->bIsBoxed = env->Get_Boxed_Mode(global);
  61.     global->dMaxVelocity = global->Calc_Max_Velocity();
  62.    
  63.     for (count = 0; count <global->numPlayers; count++)
  64.         global->players[count]->newRound();
  65.  
  66.     // clear floating text
  67.     for (count = 0; count < MAX_OBJECTS; count++)
  68.     {
  69.          if (env->objects[count] && (env->objects[count]->isSubClass(FLOATTEXT_CLASS)))
  70.         ((FLOATTEXT *)env->objects[count])->newRound();
  71.     }
  72.  
  73.     // everyone gets to buy stuff
  74.     buystuff(global, env);
  75.     set_level_settings(global, env);
  76.  
  77.     for (count = 0; count < global->numPlayers; count++)
  78.     {
  79.         global->players[count]->exitShop();
  80.         if ( (global->players[count]->type == HUMAN_PLAYER) ||
  81.              (global->players[count]->type == NETWORK_CLIENT) )
  82.            humanPlayers++;
  83.         if (global->players[count]->tank)
  84.         {
  85.               // global->players[count]->tank->newRound();
  86.               global->players[count]->tank->flashdamage = 0;
  87.               global->players[count]->tank->boost_up_shield();
  88.          }
  89.         
  90.     }
  91.  
  92.     // set_level_settings(global, env);
  93.     env->stage = STAGE_AIM;
  94.     fi = global->updateMenu = TRUE;
  95.     global->window.x = 0;
  96.     global->window.y = 0;
  97.     global->window.w = global->screenWidth - 1;
  98.     global->window.h = global->screenHeight - 1;
  99.  
  100.     // set wind
  101.     if ( (int) env->windstrength != 0)
  102.        env->wind = (float) (rand() % (int)env->windstrength) - (env->windstrength / 2);
  103.     else
  104.        env->wind = 0;
  105.     env->lastwind = env->wind;
  106.  
  107.     // create satellite
  108.     if (env->satellite)
  109.         satellite = new SATELLITE(global, env);
  110.     if (satellite)
  111.        satellite->Init();
  112.  
  113.     // get some mood music
  114.     global->background_music = global->Load_Background_Music();
  115.     if (global->background_music)
  116.        play_sample( (SAMPLE *) global->background_music, 255, 128, 1000, TRUE);
  117.  
  118.     my_tank = env->order[0];
  119.     // init stuff complete. Get down to playing
  120.     while ( (! done) && (global->command != GLOBAL_COMMAND_QUIT) )
  121.     {
  122.         // see how long we have been skipping
  123.         if (skippingComputerPlay)
  124.         {
  125.             // advance clock
  126.             if (global->Check_Time_Changed() )
  127.                 AI_clock++;
  128.             if ( (AI_clock > MAX_AI_TIME) && (winner == -1) )
  129.             {
  130.                 // in over-time, kill all tanks
  131.                 count = 0;
  132.                 while (count < global->numPlayers)
  133.                 {
  134.                     if ( (global->players[count]) &&
  135.                          (global->players[count]->tank) )
  136.                        global->players[count]->tank->l = 0;
  137.                     count++;
  138.                 }
  139.             }
  140.         }
  141.  
  142.  
  143.         global->currTank = my_tank;
  144.         // move through all objects, updating them
  145.         explosion_in_progress = FALSE;
  146.         count = 0;
  147.         while (count < MAX_OBJECTS)
  148.         {
  149.             my_object = env->objects[count];
  150.             if (my_object)
  151.             {
  152.             my_class = my_object->getClass();
  153.             if (my_class == DECOR_CLASS)
  154.             {
  155.               decor = (DECOR *) my_object;
  156.               decor->applyPhysics ();
  157.               if (decor->destroy)
  158.                 {
  159.                   decor->requireUpdate ();
  160.                   decor->update ();
  161.                   delete decor;
  162.                 }
  163.             }
  164.             else if (my_class == EXPLOSION_CLASS)
  165.             {
  166.               explosion = (EXPLOSION *) my_object;
  167.               if (explosion->bIsWeaponExplosion)
  168.                  stuff_happening = TRUE;
  169.               explosion->explode ();
  170.               explosion_in_progress = TRUE;
  171.               explosion->applyPhysics ();
  172.               if (explosion->destroy)
  173.                 {
  174.                   explosion->requireUpdate ();
  175.                   explosion->update ();
  176.                   delete explosion;
  177.                 }
  178.             }
  179.  
  180.             else if (my_class == TELEPORT_CLASS)
  181.             {
  182.               teleport = (TELEPORT *) my_object;
  183.               stuff_happening = TRUE;
  184.               teleport->applyPhysics ();
  185.               if (teleport->destroy)
  186.                 {
  187.                   teleport->requireUpdate ();
  188.                   teleport->update ();
  189.                   delete teleport;
  190.                 }
  191.             }
  192.             else if (my_class == MISSILE_CLASS)
  193.             {
  194.               TANK *shooting_tank = NULL;
  195.               BEAM *defense_beam = NULL;
  196.               int angle_to_fire;
  197.  
  198.               missile = (MISSILE *) my_object;
  199.               stuff_happening = TRUE;
  200.               env->am++;
  201.               missile->hitSomething = 0;
  202.               missile->applyPhysics ();
  203.               missile->triggerTest ();
  204.               shooting_tank = missile->Check_SDI(global);
  205.               if (shooting_tank)
  206.               {
  207.                   // (shooting_tank->x < missile->x) ? angle_to_fire = 135 : angle_to_fire = 225;
  208.                   angle_to_fire = atan2(labs(shooting_tank->y - 10 - missile->y), (missile->x - shooting_tank->x)) * 180 / 3.14159265 + 90;
  209.                   defense_beam = new BEAM(global, env, shooting_tank->x, shooting_tank->y - 10, angle_to_fire, SML_LAZER);
  210.                   missile->trigger();
  211.               }
  212.               if (missile->destroy)
  213.               {
  214.                   missile->requireUpdate ();
  215.                   missile->update ();
  216.                   delete missile;
  217.               }
  218.             }
  219.             else if (my_class == BEAM_CLASS)
  220.             {
  221.               beam = (BEAM *) my_object;
  222.               // As bots should not target while a laser is shot:
  223.               stuff_happening = TRUE;
  224.               beam->applyPhysics ();
  225.               if (beam->destroy)
  226.                 {
  227.                   beam->requireUpdate ();
  228.                   beam->update ();
  229.                   delete beam;
  230.                 }
  231.             }
  232.             else if (my_class == FLOATTEXT_CLASS)
  233.             {
  234.               floattext = (FLOATTEXT *) my_object;
  235.               floattext->applyPhysics ();
  236.               if (floattext->destroy)
  237.                 {
  238.                   floattext->requireUpdate();
  239.                   floattext->update();
  240.                   delete floattext;
  241.                   env->make_fullUpdate(); // ...kill remaining texts!
  242.                 }
  243.             }
  244.             }        // end of if we have an object
  245.  
  246.             count++;
  247.         }       // end of updating envirnoment objects
  248.  
  249.     if (satellite)
  250.        satellite->Move();
  251.  
  252.     // move land
  253.     slideLand(global, env);
  254.  
  255.     // seems like a good place to update tanks
  256.     for (count = 0; count < global->numPlayers; count++)
  257.     {
  258.         a_tank = global->players[count]->tank;
  259.         if (a_tank)
  260.         {
  261.            // see if we are doing a volly
  262.            if (a_tank->fire_another_shot)
  263.            {
  264.               if (! (a_tank->fire_another_shot % VOLLY_DELAY) )
  265.                  a_tank->activateCurrentSelection();
  266.               a_tank->fire_another_shot--;
  267.            }
  268.  
  269.            if (a_tank->flashdamage)
  270.            {
  271.               if (a_tank->flashdamage > 25 || a_tank->l < 1)
  272.               {
  273.                  a_tank->damage = 0;
  274.                  a_tank->flashdamage = 0;
  275.                  a_tank->requireUpdate();
  276.               }
  277.            }
  278.  
  279.            // update position
  280.            a_tank->pen = 0;
  281.            a_tank->applyPhysics(global);
  282.  
  283.            if ( (a_tank->l <= 0) && (! explosion_in_progress) )    // dead tank
  284.            {
  285.                a_tank->explode();
  286.                a_tank->Give_Credit(global);
  287.                if (a_tank->destroy)
  288.                {
  289.                    if ( (a_tank->player) && 
  290.                         ( (a_tank->player->type == HUMAN_PLAYER) ||
  291.                           (a_tank->player->type == NETWORK_CLIENT) ) )
  292.                    {
  293.                        humanPlayers--;
  294.                        if ( (! humanPlayers) && (global->skipComputerPlay) )
  295.                            skippingComputerPlay = TRUE;
  296.                    }
  297.  
  298.                    a_tank->Destroy();
  299.                    if (my_tank == a_tank)
  300.                      my_tank = NULL;
  301.                    delete a_tank;
  302.                    a_tank = NULL;
  303.                }
  304.            }
  305.           
  306.            // if the tank is still alive, adjust its chess-style clock
  307.            if ( (global->max_fire_time > 0.0) &&
  308.                 (a_tank == my_tank) &&
  309.                 (a_tank) && (a_tank->player->type == HUMAN_PLAYER) &&
  310.                 (! env->stage) )
  311.            {
  312.                if (global->Check_Time_Changed() )
  313.                {
  314.                     int ran_out_of_time;
  315.                     ran_out_of_time = a_tank->player->Reduce_Time_Clock();
  316.                     if (ran_out_of_time)
  317.                     {
  318.                         a_tank->player->skip_me = true;
  319.                         a_tank = NULL;
  320.                         fire = FALSE;
  321.                         my_tank = env->Get_Next_Tank(&fire);
  322.                     }
  323.                     global->updateMenu = TRUE;
  324.                }
  325.            }
  326.                 
  327.         }
  328.     }
  329.     
  330.     #ifdef NETWORK
  331.     // check for input from network
  332.     for (count = 0; count < global->numPlayers; count++)
  333.     {
  334.          if (global->players[count]->type == NETWORK_CLIENT)
  335.          {
  336.              global->players[count]->Get_Network_Command();
  337.              global->players[count]->Execute_Network_Command(FALSE);
  338.          }
  339.     }   
  340.     #endif
  341.  
  342.     // drop some naturals
  343.     if (! stuff_happening)
  344.     {
  345.         env->stage = STAGE_AIM;
  346.         doNaturals(global, env);
  347.         if (satellite)
  348.             satellite->Shoot();
  349.     }
  350.  
  351.     // draw top bar
  352.     if (global->updateMenu)
  353.     {
  354.          set_clip_rect(env->db, 0, 0, global->screenWidth - 1,
  355.                        MENUHEIGHT - 1);
  356.          drawTopBar(global, env, env->db);
  357.          global->updateMenu = FALSE;
  358.     }
  359.  
  360.  
  361.         set_clip_rect (env->db, 0, MENUHEIGHT, 
  362.                        (global->screenWidth-1), (global->screenHeight-1));
  363.         if (screen_update)
  364.         {
  365.           blit (env->sky, env->db, global->window.x, global->window.y - MENUHEIGHT, global->window.x, global->window.y, (global->window.w - global->window.x) + 1, (global->window.h - global->window.y) + 1);
  366.           masked_blit (env->terrain, env->db, global->window.x, global->window.y, global->window.x, global->window.y, (global->window.w - global->window.x) + 1, (global->window.h - global->window.y) + 2);
  367.           // drawTopBar(global, env, env->db);
  368.           int iLeft = 0;
  369.           int iRight = global->screenWidth - 1;
  370.           int iTop = MENUHEIGHT;
  371.           int iBottom = global->screenHeight - 1;
  372.           set_clip_rect (env->db, 0, 0, iRight, iBottom);
  373.           vline(env->db, iLeft, iTop, iBottom, env->wallColour);    // Left edge
  374.           vline(env->db, iLeft + 1, iTop, iBottom, env->wallColour);    // Left edge
  375.           vline(env->db, iRight, iTop, iBottom, env->wallColour);   // right edge
  376.           vline(env->db, iRight - 1, iTop, iBottom, env->wallColour);   // right edge
  377.           hline(env->db, iLeft, iBottom, iRight, env->wallColour);// bottom edge
  378.           if (global->bIsBoxed)
  379.               hline(env->db, iLeft, iTop, iRight, env->wallColour);// top edge
  380.  
  381.           env->make_update(0, 0, global->screenWidth, global->screenHeight);
  382.         }
  383.         else
  384.         {
  385.           env->replaceCanvas ();
  386.           screen_update = TRUE;
  387.         }
  388.         for (count = 0; count < global->numPlayers; count++)
  389.         {
  390.            if ( (global->players[count]) && (global->players[count]->tank) )
  391.            {
  392.               global->players[count]->tank->framelyAccounting();
  393.               if ( my_tank == global->players[count]->tank )
  394.               {
  395.                  text_bounce += text_delta;
  396.                  global->players[count]->tank->draw(env->db, text_bounce / 4);
  397.                  if ( (text_bounce > MAX_TEXT_BOUNCE) ||
  398.                       (text_bounce < 1) )
  399.                     text_delta = -text_delta;
  400.               }
  401.                  
  402.               else
  403.                  global->players[count]->tank->draw(env->db, 0);
  404.               global->players[count]->tank->update();
  405.            }
  406.         }
  407.  
  408.  
  409.     // draw all this cool stuff
  410.     count = 0;
  411.     while (count < MAX_OBJECTS)
  412.     {
  413.        my_object = env->objects[count];
  414.        if (my_object)
  415.        {
  416.          my_class = my_object->getClass();
  417.          if (my_class == MISSILE_CLASS)
  418.          {
  419.            missile = (MISSILE *) my_object;
  420.            missile->draw (env->db);
  421.            missile->update ();
  422.          }
  423.         else if (my_class == BEAM_CLASS)
  424.         {
  425.           beam = (BEAM *) my_object;
  426.           beam->draw (env->db);
  427.           beam->update ();
  428.         }
  429.         else if (my_class == EXPLOSION_CLASS)
  430.         {
  431.           explosion = (EXPLOSION *) my_object;
  432.           explosion->draw (env->db);
  433.           explosion->update ();
  434.         }
  435.         else if (my_class == TELEPORT_CLASS)
  436.         {
  437.            teleport = (TELEPORT *) my_object;
  438.            if (teleport->object)
  439.              teleport->draw (env->db);
  440.            teleport->update ();
  441.         }
  442.         else if (my_class == DECOR_CLASS)
  443.          {
  444.            decor = (DECOR *) my_object;
  445.            decor->draw (env->db);
  446.            decor->update ();
  447.          }
  448.          else if (my_class == FLOATTEXT_CLASS)
  449.          {
  450.            floattext = (FLOATTEXT *) my_object;
  451.            floattext->draw (env->db);
  452.            floattext->requireUpdate ();
  453.            floattext->update ();
  454.          }
  455.         }        // end of if we have an object
  456.         count++;
  457.     }       // end of while drawing objects
  458.     if (satellite)
  459.        satellite->Draw(env->db);
  460.     env->do_updates();
  461.  
  462.      // it is possible our tank is dead, make sure we have one
  463.      if (! my_tank)
  464.      {
  465.         my_tank = env->Get_Next_Tank(&fire);
  466.         fire = FALSE;
  467.      }
  468.  
  469.      // get user input
  470.      if ( (my_tank) && (env->stage < STAGE_ENDGAME) )
  471.      {
  472.         PLAYER *my_player;
  473.         int control_result;
  474.  
  475.         global->updateMenu = FALSE;
  476.         my_player = my_tank->player;
  477.         // my_tank->reactivate_shield();
  478.         control_result = my_player->controlTank();
  479.         if (control_result == CONTROL_QUIT)
  480.            done = TRUE;
  481.         else if (control_result == CONTROL_FIRE)
  482.         {
  483.            my_tank = env->Get_Next_Tank(&fire);
  484.            if (global->turntype != TURN_SIMUL)
  485.               fire = TRUE;
  486.         }
  487.         else if ( (control_result == CONTROL_SKIP) && (! humanPlayers) )
  488.             skippingComputerPlay = TRUE;
  489.  
  490.         // if ( (fire) && (env->stage == STAGE_AIM) )
  491.         if (fire)
  492.         {
  493.            env->stage = STAGE_FIRE;
  494.            if (my_tank)
  495.                 my_tank->reactivate_shield();
  496.            doLaunch(global, env);
  497.            fire = FALSE;
  498.            // screen_update = TRUE;
  499.         }
  500.         // else
  501.            // screen_update = FALSE;
  502.  
  503.         screen_update = FALSE;
  504.         if (control_result)
  505.            global->updateMenu = TRUE;
  506.      }     // end of controling my tank
  507.  
  508.      if ( (! skippingComputerPlay) && (env->stage != STAGE_ENDGAME) )
  509.      {
  510.          #ifdef LINUX
  511.          usleep(game_speed);
  512.          #endif
  513.          #ifdef MACOSX
  514.          usleep(game_speed);
  515.          #endif
  516.          #ifdef WIN32
  517.          Sleep(game_speed);
  518.          #endif
  519.      }
  520.          stuff_happening = FALSE;
  521.          // check for winner
  522.          if (env->stage < STAGE_ENDGAME)
  523.          {
  524.             team_won = Team_Won(global);
  525.             if (team_won == NO_WIN)
  526.                winner = global->Check_For_Winner();
  527.  
  528.             if ( (winner >= 0) || (winner == -2) || (team_won != NO_WIN) )
  529.                env->stage = STAGE_ENDGAME;
  530.          }
  531.  
  532.          if (env->stage == STAGE_ENDGAME)
  533.          {
  534.              roundEndCount++;
  535.              if (roundEndCount >= WAIT_AT_END_OF_ROUND)
  536.                 done = TRUE;
  537.              screen_update = FALSE;
  538.          }
  539.          if (global->close_button_pressed)
  540.              done = TRUE;
  541.     }    // end of game loop
  542.  
  543.     // credit winners
  544.     if (team_won != NO_WIN)
  545.        winner = team_won;
  546.     global->Credit_Winners(winner);
  547.  
  548.     // display winning results
  549.     while ( keypressed() )
  550.          readkey();     // clear the buffer
  551.  
  552.     // check to see if we have a winner or we just bailed out early
  553.     if ( (winner != -1) && (! global->demo_mode) && 
  554.          (! global->close_button_pressed) )
  555.     {
  556.           showRoundEndScoresAt(global, env, env->db, global->screenWidth / 2,
  557.                                global->screenHeight / 2, winner);
  558.           env->do_updates();
  559.  
  560.           while ( (! keypressed() ) && (! global->demo_mode) )
  561.               LINUX_SLEEP;
  562.           readkey();
  563.     }
  564.     // else
  565.     // {
  566.         global->window.x = global->window.y = 0;
  567.         global->window.w = global->screenWidth - 1;
  568.         global->window.h = global->screenHeight - 1;
  569.         set_clip_rect(env->db, 0, 0, global->window.w, global->window.h);
  570.     // }
  571.  
  572.     // clean up
  573.     if (satellite)
  574.        delete satellite;
  575.  
  576.     // remove existing tanks etc
  577.     for (count = 0; count < global->numPlayers; count++)
  578.     {
  579.        if (global->players[count]->tank)
  580.        {
  581.           global->players[count]->Reclaim_Shield();
  582.           delete global->players[count]->tank;
  583.        }
  584.     }
  585.  
  586.     return done;
  587. }
  588.  
  589. #endif
  590.  
  591.