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 / physobj.cpp < prev    next >
C/C++ Source or Header  |  2009-10-30  |  8KB  |  251 lines

  1. /*
  2.  * atanks - obliterate each other with oversize weapons
  3.  * Copyright (C) 2003  Thomas Hudson
  4.  *
  5.  * This program is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU General Public License
  7.  * as published by the Free Software Foundation; either version 2
  8.  * of the License, or (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  * */
  19.  
  20.  
  21. #include "physobj.h"
  22. #include "environment.h"
  23.  
  24.  
  25. void PHYSICAL_OBJECT::initialise ()
  26.     {
  27.       VIRTUAL_OBJECT::initialise ();
  28.       hitSomething = 0;
  29.     }
  30.  
  31.  
  32. void PHYSICAL_OBJECT::draw (BITMAP *dest)
  33.     {
  34.       VIRTUAL_OBJECT::draw (dest);
  35.     }
  36.  
  37.  
  38.  
  39. int  PHYSICAL_OBJECT::checkPixelsBetweenPrevAndNow ()
  40.     {
  41.       double startX = x - xv;
  42.       double startY = y - yv;
  43.  
  44.       if (checkPixelsBetweenTwoPoints (_global, _env, &startX, &startY, x, y))
  45.         {
  46.           x = startX;
  47.           y = startY;
  48.           return (1);
  49.         }
  50.  
  51.       return (0);
  52.     }
  53.  
  54.  
  55.  
  56. /** @brief applyPhysics
  57.   *
  58.   * Moves the object according to momentum and wind, boundec off of walls/ceiling/floor, and checks
  59.   * whether something is hit.
  60.   */
  61. int PHYSICAL_OBJECT::applyPhysics()
  62. {
  63.   // Normal physics
  64.  
  65.   double dPrevX = x;
  66.   double dPrevY = y;
  67.   if (((x + xv) <= 1) || ((x + xv) >= (_global->screenWidth - 1)))
  68.     {
  69.       if    (    (((x + xv) < 1) && checkPixelsBetweenTwoPoints (_global, _env, &dPrevX, &dPrevY, 1, y))
  70.            ||(    ((x + xv) > (_global->screenWidth - 2))
  71.                && checkPixelsBetweenTwoPoints (_global, _env, &dPrevX, &dPrevY, (_global->screenWidth - 2), y))    )
  72.         {
  73.           x = dPrevX;
  74.           y = dPrevY;
  75.           hitSomething = true;
  76.         }
  77.       else
  78.         {
  79.           //motion - wind affected
  80.           switch (_env->current_wallType)
  81.             {
  82.             case WALL_RUBBER:
  83.               xv = -xv;    //bounce on the border
  84.               break;
  85.             case WALL_SPRING:
  86.               xv = -xv * SPRING_CHANGE;
  87.               break;
  88.             case WALL_WRAP:
  89.               if (xv < 0)
  90.                 x = _global->screenWidth - 2; // -1 is the wall itself
  91.               else
  92.                 x = 1;
  93.               break;
  94.             case WALL_STEEL:
  95.               x += xv;
  96.               if (x < 1)
  97.                 x = 1;
  98.               if (x > (_global->screenWidth - 2))
  99.                 x = _global->screenWidth - 2;
  100.               xv = 0; // already applied!
  101.               hitSomething = 1; // blow up on steel
  102.               break;
  103.             }
  104.         }
  105.     }
  106.   if (!hitSomething)
  107.     xv += (double)(_env->wind - xv) / mass * drag * _env->viscosity;
  108.  
  109.   // hit floor or boxed top
  110.   if ((y + yv >= (_global->screenHeight - 1))
  111.       ||((y + yv <= MENUHEIGHT) && (_global->bIsBoxed)))
  112.     {
  113.       if    (    (    _global->bIsBoxed && ((y + yv) <= MENUHEIGHT)
  114.              && checkPixelsBetweenTwoPoints (_global, _env, &dPrevX, &dPrevY, x, MENUHEIGHT + 1))
  115.            ||(    ((y + yv) > (_global->screenHeight - 2))
  116.                && checkPixelsBetweenTwoPoints (_global, _env, &dPrevX, &dPrevY, x, (_global->screenHeight - 2)))    )
  117.         {
  118.           x = dPrevX;
  119.           y = dPrevY;
  120.           hitSomething = true;
  121.         }
  122.       else
  123.         {
  124.           switch (_env->current_wallType)
  125.             {
  126.             case WALL_RUBBER:
  127.               yv = -yv * 0.5;
  128.               xv *= 0.95;
  129.               break;
  130.             case WALL_SPRING:
  131.               yv = -yv * SPRING_CHANGE;
  132.               xv *= 1.05;
  133.               break;
  134.             default:
  135.               // steel or wrap floor (ceiling)
  136.               y += yv;
  137.               if (y >= (_global->screenHeight - 1))
  138.                 y = _global->screenHeight - 2; // -1 would be the floor itself!
  139.               else
  140.                 y = MENUHEIGHT + 1; // +1 or it would be the wall itself
  141.               yv = 0; // already applied!
  142.               hitSomething = 1;
  143.             }
  144.           if (fabs(xv) + fabs(yv) < 0.8)
  145.             hitSomething = 1;
  146.         }
  147.     }
  148.  
  149.   // velocity check:
  150.   /** the old calculation was wrong, but the new one, taking FPS into account, eventually works! **/
  151.   double dActVelocity = ABSDISTANCE((long double)xv, (long double)yv, 0, 0); // a┬▓+b┬▓=c┬▓ ... says Pythagoras :)
  152.   double dMaxVelocity = _global->dMaxVelocity * (1.20 + ((double)mass / ((double)MAX_POWER / 10.0)));
  153.   // apply mass, as more mass allows more max velocity:
  154.  
  155.   // The default means, that a small missile can be accelerated by 25% over MAX_POWER,
  156.   // while a large Napalm Bomb can go up to 220%.
  157.  
  158.   if (dActVelocity > dMaxVelocity)
  159.     {
  160. #ifdef DEBUG
  161.       cout << "** Missile too fast!" << endl;
  162.       cout << "mass: " << mass << " - Max Velocity: " << dMaxVelocity << " (FPS: " << _global->frames_per_second << ")" << endl;
  163.       cout << "xv: " << xv << " - yv: " << yv << " - Act Velocity: " << dActVelocity << endl;
  164. #endif // DEBUG
  165.       // apply *some* velocity, as the thing is killed on its way
  166.       y += yv / (1.0 + ((double)(rand() % 40) / 10.0)); // This produces somthing
  167.       x += xv / (1.0 + ((double)(rand() % 40) / 10.0)); // between 1.0 and 5.0
  168.       xv = 0.0;
  169.       yv = 0.0;
  170.       if (y <= MENUHEIGHT)
  171.         y = MENUHEIGHT + 1;
  172.       if (y > (_global->screenHeight - 2))
  173.         y = _global->screenHeight - 2;
  174.       if ((x < 1) && (_env->current_wallType != WALL_WRAP))
  175.         x = 1; // Wrapped Explosion takes care for explosions off the screen
  176.       if ((x > (_global->screenWidth - 2)) && (_env->current_wallType != WALL_WRAP))
  177.         x = _global->screenWidth - 2; // Wrapped Explosion takes care for explosions off the screen
  178.       hitSomething = 1;
  179.     }
  180.   if (!hitSomething)
  181.     {
  182.       x += xv;
  183.       y += yv;
  184.       yv += _env->gravity * (100.0 / _global->frames_per_second);
  185.       // Barrier test:
  186.       if ( (yv <= -1.0) && (y <= (_global->screenHeight * -25.0)))
  187.         yv *= -1.0;
  188.     }
  189.   else
  190.     {
  191.       // if something *is* hit, ensure that that damn thing is on screen! (only y matters here!)
  192.       if ((y < (MENUHEIGHT + 1)) && _global->bIsBoxed)    y = MENUHEIGHT + 1;
  193.       if ((y < MENUHEIGHT) && !_global->bIsBoxed)                y = MENUHEIGHT;
  194.     }
  195.   return (hitSomething);
  196. }
  197.  
  198. /* --- global method --- */
  199. int checkPixelsBetweenTwoPoints (GLOBALDATA *global, ENVIRONMENT *env, double *startX, double *startY, double endX, double endY)
  200. {
  201.   int landFound = 0;
  202.  
  203.   // only check if on screen
  204.   double xDist = endX - *startX;
  205.   double yDist = endY - *startY;
  206.   double length;
  207.   double xInc;
  208.   double yInc;
  209.  
  210.   if ((fabs(xDist) < 2) && (fabs(yDist) < 2))
  211.     {
  212.       if    (    (endX > 0)                                                     // 0 is the wall!
  213.            &&(endX < (global->screenWidth - 1))    // -1 is the wall!
  214.            &&(endY < (global->screenHeight - 1))    // -1 is the floor!
  215.            &&(endY > (MENUHEIGHT + 1))                        // or it would always fail for high shots!
  216.            &&(getpixel (env->terrain, (int)endX, (int)endY) != PINK)    )
  217.         return (1);
  218.       else
  219.         return (0);
  220.     }
  221.  
  222.   length = FABSDISTANCE(xDist, yDist, 0, 0);
  223.   yInc = yDist / length;
  224.   xInc = xDist / length;
  225.  
  226.   // sanity check
  227.   if (length > (global->screenWidth + global->screenHeight))
  228.     length = global->screenWidth + global->screenHeight;
  229.  
  230.   //check all pixels along line for land
  231.   for (int lengthPos = 0; lengthPos < length; lengthPos++)
  232.     {
  233.       //found land
  234.       if    (    (*startX > 0)                                                     // 0 is the wall!
  235.            &&(*startX < (global->screenWidth - 1))        // -1 is the wall!
  236.            &&(*startY < (global->screenHeight - 1))    // -1 is the floor!
  237.            &&(*startY > (MENUHEIGHT + 1))                        // or it would always fail for high shots!
  238.            &&(getpixel(env->terrain, (int)*startX, (int)*startY) != PINK)    )
  239.         {
  240.           // Leaves startX and Y at current point if within range!
  241.           landFound = 1;
  242.           break;
  243.         }
  244.       *startX += xInc;
  245.       *startY += yInc;
  246.     }
  247.  
  248.   return (landFound);
  249. }
  250.  
  251.