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 / land.cpp < prev    next >
C/C++ Source or Header  |  2009-09-20  |  6KB  |  205 lines

  1. #include "land.h"
  2. #include "files.h"
  3.  
  4. #ifdef THREADS
  5. #include <pthread.h>
  6. #endif
  7.  
  8. // Define how the land will look.
  9.  
  10. void generate_land (GLOBALDATA *global, ENVIRONMENT *env, BITMAP *land, int xoffset, int yoffset, int heightx)
  11. {
  12.   const int land_height = heightx * 5 / 6;
  13.   double        smoothness = 100;
  14.   int   octaves = 8;
  15.   double        lambda = 0.25;
  16.   double * depthStrip[2];
  17.  
  18.   depthStrip[0] = (double *)calloc(global->screenHeight, sizeof(double));
  19.   depthStrip[1] = (double *)calloc(global->screenHeight, sizeof(double));
  20.  
  21.   if (!depthStrip[0] || !depthStrip[1])
  22.     {
  23.       cerr << "ERROR: Unable to allocate " << (global->screenHeight * 2) << " bytes in generate_land() !!!" << endl;
  24.     }
  25.  
  26.   int landType = (env->landType == LANDTYPE_RANDOM)? (rand () % LANDTYPE_PLAIN) + 1 : (int)env->landType;
  27.  
  28.   switch (landType)
  29.     {
  30.     case LANDTYPE_MOUNTAINS:
  31.       smoothness = 200;
  32.       octaves = 8;
  33.       lambda = 0.65;
  34.       break;
  35.     case LANDTYPE_CANYONS:
  36.       smoothness = 50;
  37.       octaves = 8;
  38.       lambda = 0.25;
  39.       break;
  40.     case LANDTYPE_VALLEYS:
  41.       smoothness = 200;
  42.       octaves = 8;
  43.       lambda = 0.25;
  44.       break;
  45.     case LANDTYPE_HILLS:
  46.       smoothness = 600;
  47.       octaves = 6;
  48.       lambda = 0.40;
  49.       break;
  50.     case LANDTYPE_FOOTHILLS:
  51.       smoothness = 1200;
  52.       octaves = 3;
  53.       lambda = 0.25;
  54.       break;
  55.     case LANDTYPE_PLAIN:
  56.       smoothness = 4000;
  57.       octaves = 2;
  58.       lambda = 0.2;
  59.       break;
  60.     case LANDTYPE_NONE:
  61.       break;
  62.     default:
  63.       break;
  64.     }
  65.  
  66.   if (global->detailedLandscape)
  67.     memset (depthStrip[1], 0, global->screenHeight * sizeof (double));
  68.  
  69.  for (int x = 0; x < global->screenWidth; x++)
  70.     {
  71.       int depth = 0;
  72.       if (landType == LANDTYPE_NONE)
  73.         env->height[x] = 1;
  74.       else
  75.         env->height[x] = ((perlin2DPoint (1.0, smoothness, xoffset + x, yoffset, lambda, octaves) + 1) / 2);
  76.  
  77.       if (global->detailedLandscape)
  78.         {
  79.           memcpy (depthStrip[0], depthStrip[1], global->screenHeight * sizeof(double));
  80.           for (depth = 1; depth < global->screenHeight; depth++)
  81.             {
  82.               depthStrip[1][depth] = ((perlin2DPoint (1.0, smoothness, xoffset + x, yoffset + depth, lambda, octaves) + 1) / 2 * land_height - (global->screenHeight - depth));
  83.               if (depthStrip[1][depth] > env->height[x] * land_height)
  84.                 depthStrip[1][depth] = env->height[x] * land_height;
  85.             }
  86.           depthStrip[1][0] = 0;
  87.           depth = 1;
  88.         }
  89.  
  90.       if (landType == LANDTYPE_NONE)
  91.         env->height[x] = 1;
  92.       else
  93.         env->height[x] *= land_height;
  94.  
  95.      for (int y = 0; y <= env->height[x]; y++)
  96.         {
  97.           double offset = 0;
  98.           int color = 0;
  99.           double shade = 0;
  100.  
  101.           if (global->detailedLandscape)
  102.             {
  103.               double bot, top, minBot, maxTop, btdiff, i;
  104.               double a1, a2, angle;
  105.               while ((depthStrip[1][depth] <= y) && (depth < global->screenHeight))
  106.                 depth++;
  107.               bot = (depthStrip[0][depth - 1] + depthStrip[1][depth - 1]) / 2;
  108.               top = (depthStrip[0][depth] + depthStrip[1][depth]) / 2;
  109.               minBot = MIN (depthStrip[0][depth - 1], depthStrip[1][depth - 1]);
  110.               maxTop = MAX (depthStrip[0][depth], depthStrip[1][depth]);
  111.               btdiff = maxTop - minBot;
  112.               i = (y - bot) / btdiff;
  113.               a1 = atan2 (depthStrip[0][depth - 1] - depthStrip[1][depth - 1], 1.0) * 180 / PI + 180;
  114.               a2 = atan2 (depthStrip[0][depth] - depthStrip[1][depth], 1.0) * 180 / PI + 180;
  115.  
  116.               angle = interpolate (a1, a2, i);
  117.               shade = global->slope[(int)angle][0];
  118.             }
  119.  
  120.           if (global->ditherGradients)
  121.             offset += rand () % 10 - 5;
  122.  
  123.           if (global->detailedLandscape)
  124.             offset += (global->screenHeight - depth) * 0.5;
  125.  
  126.           while (y + offset < 0)
  127.             offset /= 2;
  128.           while (y + offset > global->screenHeight)
  129.             offset /= 2;
  130.  
  131.           color = gradientColorPoint (land_gradients[global->curland], env->height[x], y + offset);
  132.           if (global->detailedLandscape)
  133.             {
  134.               float h, s, v;
  135.               int r, g, b;
  136.  
  137.               r = getr (color);
  138.               g = getg (color);
  139.               b = getb (color);
  140.               rgb_to_hsv (r, g, b, &h, &s, &v);
  141.               shade += (double)(rand () % 1000 - 500) * (1.0/10000);
  142.               if (shade < 0)
  143.                 v += v * shade * 0.5;
  144.               else
  145.                 v += (1 - v) * shade * 0.5;
  146.               hsv_to_rgb (h, s, v, &r, &g, &b);
  147.               color = makecol (r, g, b);
  148.             }
  149.  
  150.           #ifdef THREADS
  151.           solid_mode();
  152.           #endif
  153.           putpixel (land, x, global->screenHeight - y, color);
  154.           #ifdef THREADS
  155.           drawing_mode(global->env->current_drawing_mode, NULL, 0, 0);
  156.           #endif
  157.         }
  158.     }
  159.  
  160.   free(depthStrip[0]);
  161.   free(depthStrip[1]);
  162.  
  163. }
  164.  
  165.  
  166.  
  167. #ifdef THREADS
  168. // This function should be called as a separate thread. Its sole purpose
  169. // is to generate terrain images in the background. Then pass them
  170. // to the main program.
  171. void *Generate_Land_In_Background(void *new_env)
  172. {
  173.     ENVIRONMENT *env = (ENVIRONMENT *) new_env;
  174.     GLOBALDATA *global = env->Get_Globaldata();
  175.     BITMAP *land = NULL;
  176.     int xoffset;
  177.  
  178.    while (global->command != GLOBAL_COMMAND_QUIT)
  179.    {
  180.       if (! env->waiting_terrain)
  181.       {
  182.           // The sky thread runs around the same time. We will wait a few seconds
  183.           LINUX_DREAMLAND;
  184.           land = create_bitmap(global->screenWidth, global->screenHeight);
  185.           if (! land)
  186.           {
  187.              printf("Memory error while creating land in background.\n");
  188.           }
  189.           else
  190.           {
  191.               clear_to_color(land, PINK);
  192.               xoffset = rand();
  193.               generate_land(global, env, land, xoffset, 0, global->screenHeight);
  194.           }
  195.           env->waiting_terrain = land;
  196.       }
  197.       LINUX_SLEEP;        // avoid taxing the CPU
  198.    }        // while still running program
  199.  
  200.    pthread_exit(NULL);
  201.    return NULL;         // keeps the compiler happy
  202. }
  203. #endif
  204.  
  205.