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 / beam.cpp < prev    next >
C/C++ Source or Header  |  2009-10-30  |  8KB  |  287 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. #include "environment.h"
  21. #include "globaldata.h"
  22. #include "physobj.h"
  23. #include "player.h"
  24. #include "decor.h"
  25. #include "tank.h"
  26. #include "beam.h"
  27.  
  28.  
  29. BEAM::~BEAM ()
  30. {
  31.   requireUpdate();
  32.   update();
  33.   _env->make_bgupdate (_current.x, _current.y, _current.w, _current.h);
  34.   _env->make_bgupdate (_old.x, _old.y, _old.w, _old.h);
  35.   _env->removeObject (this);
  36.   weap    = NULL;
  37.   _global = NULL;
  38.   _env    = NULL;
  39.    delete(points);
  40. }
  41.  
  42. void tracePath (int *targetX, int *targetY, GLOBALDATA *global, ENVIRONMENT *env, int minRange, double xpos, double ypos, int angle)
  43. {
  44.   double dx = global->slope[angle][0];
  45.   double dy = global->slope[angle][1];
  46.   double tx = xpos, ty = ypos;
  47.   int hitSomething = 0;
  48.   int range = 0;
  49.  
  50.   while ((!hitSomething) && tx > -10 &&
  51.          tx < global->screenWidth + 10 && ty > -10 &&
  52.          ty < global->screenHeight &&
  53.          (getpixel (env->terrain, (int)tx, (int)ty) == PINK))
  54.     {
  55.       TANK *ltank;
  56.       for (int objCount = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; objCount++)
  57.         {
  58.           if (range > minRange && tx > ltank->x - TANKWIDTH && tx < ltank->x + TANKWIDTH && ty > ltank->y && ty < ltank->y + TANKHEIGHT && ltank->l > 0)
  59.             {
  60.               hitSomething = 1;
  61.               ltank->requireUpdate ();
  62.             }
  63.         }
  64.       tx += dx;
  65.       ty += dy;
  66.       range++;
  67.     }
  68.   *targetX = (int)tx;
  69.   *targetY = (int)ty;
  70. }
  71.  
  72. BEAM::BEAM (GLOBALDATA *global, ENVIRONMENT *env, double xpos, double ypos, int fireAngle,
  73.             int weaponType):PHYSICAL_OBJECT(),weap(NULL),points(NULL)
  74. {
  75.   player = NULL;
  76.   drag = 0.00;
  77.   mass = 0;
  78.   clock = 500;
  79.   age = 0;
  80.   setEnvironment (env);
  81.   _align = LEFT;
  82.   _global = global;
  83.   #ifdef NETWORK
  84.   char buffer[256];
  85.   sprintf(buffer, "BEAM %d %d %d %d", (int) xpos, (int) ypos, fireAngle, weaponType);
  86.   global->Send_To_Clients(buffer);
  87.   #endif
  88.   x = xpos;
  89.   y = ypos;
  90.   angle = fireAngle % 360;
  91.   type = weaponType;
  92.   if (type < WEAPONS)
  93.     weap = &(weapon[type]);
  94.   else
  95.     weap = &(naturals[type - WEAPONS]);
  96.   radius = weap->radius;
  97.  
  98.  
  99.   if (type >= SML_LIGHTNING && type <= LRG_LIGHTNING)
  100.     {
  101.       damage = (double)weap->damage / (10 * (type - SML_LIGHTNING + 1));
  102.       maxAge = 10 * (type - SML_LIGHTNING + 1);
  103.       numPoints = 4 + rand () % 10;
  104.       color = WHITE;
  105.       play_sample ((SAMPLE *) _global->sounds[LIGHTNING_SOUND], 128 + (radius * 10), 128, 500 + (radius * 50), 0);
  106.     }
  107.   else
  108.     {
  109.       numPoints = 2;
  110.       if (type >= SML_LAZER && type <= LRG_LAZER)
  111.         damage = (double)weap->damage / (10 * (type - SML_LAZER + 1));
  112.       maxAge = 10 * (type - SML_LAZER + 1);
  113.       color = makecol (255 - (type - SML_LAZER) * 64, 128, 64 + (type - SML_LAZER) * 64);
  114.     }
  115.   tracePath (&targetX, &targetY, global, env, radius + 2, x, y, angle);
  116.   xv = targetX - x;
  117.   yv = targetY - y;
  118.   points = new int[numPoints * 2];
  119.   if (!points)
  120.     {
  121.       perror ( "beam.cc: Failed allocating memory for points in BEAM::BEAM");
  122.       // exit (1);
  123.     }
  124.   setLightningPath ();
  125. }
  126.  
  127. void BEAM::setLightningPath ()
  128. {
  129.   int point = 0;
  130.   double x1 = x, y1 = y;
  131.  
  132.   do
  133.     {
  134.       double offX, offY;
  135.       if (point > 0 && point < numPoints - 1)
  136.         {
  137.           offX = (perlin2DPoint (1.0, 20, 12746 + x1, y1, 0.3, 6) + 1) * (radius * 10);
  138.           offY = (perlin2DPoint (1.0, 20, x1, 1273 + y1, 0.3, 6) + 1) * (radius * 10);
  139.         }
  140.       else
  141.         {
  142.           offX = 0;
  143.           offY = 0;
  144.         }
  145.       points[point * 2] = (int)(x1 + offX);
  146.       points[point * 2 + 1] = (int)(y1 + offY);
  147.  
  148.       x1 += xv / (numPoints - 1);
  149.       y1 += yv / (numPoints - 1);
  150.       point++;
  151.     }
  152.   while (point < numPoints);
  153. }
  154.  
  155. void BEAM::initialise ()
  156. {
  157.   PHYSICAL_OBJECT::initialise ();
  158.   drag = 0.00;
  159.   mass = 0;
  160.   clock = 500;
  161.   age = 0;
  162. }
  163.  
  164. int BEAM::applyPhysics ()
  165. {
  166.   TANK *ltank;
  167.   DECOR *decor;
  168.  
  169.   age++;
  170.   circlefill (_env->terrain, targetX, targetY, radius, PINK);
  171.   for (int col = targetX - radius - 1; col < targetX + radius + 1; col++)
  172.     setSlideColumnDimensions (_global, _env, col, true);
  173.  
  174.   if (age > maxAge)
  175.     destroy = TRUE;
  176.  
  177.   for (int objCount = 0; (ltank = (TANK*)_env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; objCount++)
  178.     {
  179.       if (targetX > ltank->x - TANKWIDTH - radius && targetX < ltank->x + TANKWIDTH + radius && targetY > ltank->y - radius && targetY < ltank->y + TANKHEIGHT + radius && ltank->l > 0)
  180.         {
  181.           // hitSomething = 1;
  182.           ltank->requireUpdate ();
  183.  
  184.           // make sure a player is involved
  185.           if (player)
  186.             ltank->damage += damage * player->damageMultiplier;
  187.           else
  188.             ltank->damage += damage;
  189.  
  190.           ltank->creditTo = player;
  191.           if (destroy)
  192.             ltank->applyDamage ();
  193.         }
  194.     }
  195.   decor = new DECOR (_global, _env, targetX, targetY, rand () % 6 - 3, rand () % 6 - 3, radius, DECOR_SMOKE);
  196.   if (!decor)
  197.     {
  198.       perror ( "beam.cc: Failed allocating memory for decor in applyPhysics");
  199.       // exit (1);
  200.     }
  201.   tracePath (&targetX, &targetY, _global, _env, radius + 2, x, y, angle);
  202.   setLightningPath ();
  203.  
  204.   return (hitSomething);
  205. }
  206.  
  207. int beamRadius;
  208. void lazerPoint (BITMAP *dest, int x1, int y1, int color)
  209. {
  210.   circlefill (dest, x1, y1, beamRadius, color);
  211. }
  212.  
  213. void lightningPoint (BITMAP *dest, int x1, int y1, int age)
  214. {
  215.   double pointRad = (perlin2DPoint (1.0, 2, x1 + age, y1, 0.3, 6) + 1) / 2 * beamRadius + 1;
  216.   double offX = (perlin2DPoint (1.0, 20, 127846 + x1, y1 + age, 0.3, 6) + 1) * beamRadius;
  217.   double offY = (perlin2DPoint (1.0, 20, x1 + age, 12973 + y1, 0.3, 6) + 1) * beamRadius;
  218.  
  219.   circlefill (dest, x1 + (int)offX, y1 + (int)offY, (int)pointRad, WHITE);
  220. }
  221.  
  222. void BEAM::draw (BITMAP *dest)
  223. {
  224.   int x1, y1, x2, y2;
  225.   setUpdateArea ((int)x - radius, (int)y - radius, (int)x + radius * 2, (int)y + radius * 2);
  226.  
  227.   drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
  228.   _env->current_drawing_mode = DRAW_MODE_TRANS;
  229.   set_trans_blender (0, 0, 0, (int)50);
  230.   if (type >= SML_LIGHTNING && type <= LRG_LIGHTNING)
  231.     {
  232.       beamRadius = radius;
  233.       for (int point = 1; point < numPoints; point++)
  234.         {
  235.  
  236.           x1 = points[(point - 1) * 2];
  237.           y1 = points[(point - 1) * 2 + 1];
  238.           x2 = points[point * 2];
  239.           y2 = points[point * 2 + 1];
  240.  
  241.           do_line (dest, x1, y1, x2, y2, age, lightningPoint);
  242.           addUpdateArea (MIN(x1,x2) - radius * 6,
  243.                          MIN(y1,y2) - radius * 6,
  244.                          MAX(x1,x2) + radius * 2 * 6,
  245.                          MAX(y1,y2) + radius * 2 * 6);
  246.         }
  247.     }
  248.   else if (type >= SML_LAZER && type <= LRG_LAZER)
  249.     {
  250.       beamRadius = radius;
  251.       for (int point = 1; point < numPoints; point++)
  252.         {
  253.  
  254.           x1 = points[(point - 1) * 2];
  255.           y1 = points[(point - 1) * 2 + 1];
  256.           x2 = points[point * 2];
  257.           y2 = points[point * 2 + 1];
  258.  
  259.           do_line (dest, x1, y1, x2, y2, color, lazerPoint);
  260.           //do_line (dest, x1, y1, x2, y2, color, lightningPoint);
  261.           addUpdateArea (MIN(x1,x2) - radius * 2,
  262.                          MIN(y1,y2) - radius * 2,
  263.                          MAX(x1,x2) + radius * 2 * 2,
  264.                          MAX(y1,y2) + radius * 2 * 2);
  265.         }
  266.     }
  267.   drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
  268.   _env->current_drawing_mode = DRAW_MODE_SOLID;
  269.   requireUpdate ();
  270. }
  271.  
  272. /*void BEAM::update ()
  273. {
  274.     _env->combineUpdates = FALSE;
  275.     VIRTUAL_OBJECT::update ();
  276.     _env->combineUpdates = TRUE;
  277. }*/
  278.  
  279. int BEAM::isSubClass (int classNum)
  280. {
  281.   if (classNum == BEAM_CLASS)
  282.     return (TRUE);
  283.   else
  284.     return (FALSE);
  285.   //return (PHYSICAL_OBJECT::isSubClass (classNum));
  286. }
  287.