added some more color functions for BD engine
authorHolger Schemel <info@artsoft.org>
Mon, 8 Apr 2024 23:46:32 +0000 (01:46 +0200)
committerHolger Schemel <info@artsoft.org>
Mon, 8 Apr 2024 23:46:32 +0000 (01:46 +0200)
src/game_bd/bd_cave.c
src/game_bd/bd_cave.h
src/game_bd/bd_colors.c
src/game_bd/bd_colors.h

index 88fa93299f57d61f39ce44e38802ab87f576978c..8add2cca7b29af9250b0ad604ed635915d5f3b6b 100644 (file)
@@ -777,6 +777,19 @@ void gd_cave_c64_random_set_seed(GdCave *cave, int seed1, int seed2)
   gd_c64_random_set_seed(&cave->c64_rand, seed1, seed2);
 }
 
+/*
+  select random colors for a given cave.
+  this function will select colors so that they should look somewhat nice; for example
+  brick walls won't be the darkest color, for example.
+*/
+static inline void swap(int *i1, int *i2)
+{
+  int t = *i1;
+
+  *i1 = *i2;
+  *i2 = t;
+}
+
 void gd_cave_set_random_c64_colors(GdCave *cave)
 {
   const int bright_colors[] = { 1, 3, 7 };
@@ -809,6 +822,151 @@ void gd_cave_set_random_c64_colors(GdCave *cave)
   cave->color5 = cave->color1;
 }
 
+static void cave_set_random_indexed_colors(GdCave *cave, GdColor (*color_indexer_func) (int, int))
+{
+  int hue = gd_random_int_range(0, 15);
+  int hue_spread = gd_random_int_range(1, 6);    // 1..5
+
+  // we only use 0..6, as saturation 15 is too bright (almost always white)
+  // also, saturation 0..1..2 is too dark. the color0=black is there for dark.
+  // so this is also 1..5. when hue spread is low, brightness spread is high
+  int bri_spread = 6 - hue_spread;
+  int bri1 = 8, bri2 = 8 - bri_spread, bri3 = 8 + bri_spread;
+
+  // there are 15 valid choices for hue, so we do a %15
+  int col1 = hue, col2 = (hue + hue_spread + 15) % 15, col3 = (hue - hue_spread + 15) % 15;
+
+  // this makes up a random color, and selects a color triad by hue+5 and hue+10.
+  // also creates a random saturation.
+  // color of brick is 8+sat, so it is always a bright color.
+  // another two are 8-sat and 8.
+  // order of colors is also changed randomly.
+  if (gd_random_boolean())    swap(&bri1, &bri2);
+
+  // we do not touch bri3 (8+sat), as it should be a bright color
+  if (gd_random_boolean())    swap(&col1, &col2);
+  if (gd_random_boolean())    swap(&col2, &col3);
+  if (gd_random_boolean())    swap(&col1, &col3);
+
+  cave->colorb = color_indexer_func(0, 0);
+  cave->color0 = color_indexer_func(0, 0);
+  cave->color1 = color_indexer_func(col1 + 1, bri1);
+  cave->color2 = color_indexer_func(col2 + 1, bri2);
+  cave->color3 = color_indexer_func(col3 + 1, bri3);
+  // amoeba and slime are different
+  // some green thing
+  cave->color4 = color_indexer_func(gd_random_int_range(11, 13), gd_random_int_range(6, 12));
+  // some blueish thing
+  cave->color5 = color_indexer_func(gd_random_int_range(7, 10),  gd_random_int_range(0, 6));
+}
+
+static void gd_cave_set_random_atari_colors(GdCave *cave)
+{
+  cave_set_random_indexed_colors(cave, gd_atari_color_huesat);
+}
+
+static void gd_cave_set_random_c64dtv_colors(GdCave *cave)
+{
+  cave_set_random_indexed_colors(cave, gd_c64dtv_color_huesat);
+}
+
+static inline void swapd(double *i1, double *i2)
+{
+  double t = *i1;
+
+  *i1 = *i2;
+  *i2 = t;
+}
+
+static void gd_cave_set_random_rgb_colors(GdCave *cave)
+{
+  const double hue_max = 10.0 / 30.0;
+  // any hue allowed
+  double hue = gd_random_double();
+  // hue 360 degress=1.  hue spread is min. 24 degrees, max 120 degrees (1/3)
+  double hue_spread = gd_random_double_range(2.0 / 30.0, hue_max);
+  double h1 = hue, h2 = hue + hue_spread, h3 = hue + 2 * hue_spread;
+  double v1, v2, v3;
+  double s1, s2, s3;
+
+  if (gd_random_boolean())
+  {
+    // when hue spread is low, brightness(saturation) spread is high
+    // this formula gives a number (x) between 0.1 and 0.4,
+    // which will be 0.5-x and 0.5+x, so the range is 0.1->0.9
+    double spread = 0.1 + 0.3 * (1 - hue_spread / hue_max);
+    v1 = 0.6;                // brightness variation, too
+    v2 = 0.7;
+    v3 = 0.8;
+    s1 = 0.5;                // saturation is different
+    s2 = 0.5 - spread;
+    s3 = 0.5 + spread;
+  }
+  else
+  {
+    // when hue spread is low, brightness(saturation) spread is high
+    // this formula gives a number (x) between 0.1 and 0.25,
+    // which will be 0.5+x and 0.5+2x, so the range is 0.5->0.9
+    double spread = 0.1 + 0.15 * (1 - hue_spread / hue_max);
+    v1 = 0.5;                // brightness is different
+    v2 = 0.5 + spread;
+    v3 = 0.5 + 2 * spread;
+    s1 = 0.7;                // saturation is same - a not fully saturated one
+    s2 = 0.8;
+    s3 = 0.9;
+  }
+
+  // randomly change values, but do not touch v3, as cave->color3 should be a bright color
+  if (gd_random_boolean())    swapd(&v1, &v2);
+
+  // randomly change hues and saturations
+  if (gd_random_boolean())    swapd(&h1, &h2);
+  if (gd_random_boolean())    swapd(&h2, &h3);
+  if (gd_random_boolean())    swapd(&h1, &h3);
+  if (gd_random_boolean())    swapd(&s1, &s2);
+  if (gd_random_boolean())    swapd(&s2, &s3);
+  if (gd_random_boolean())    swapd(&s1, &s3);
+
+  h1 = h1 * 360.0;
+  h2 = h2 * 360.0;
+  h3 = h3 * 360.0;
+
+  cave->colorb = gd_color_get_from_hsv(0, 0, 0);
+  cave->color0 = gd_color_get_from_hsv(0, 0, 0);       // black for background
+  cave->color1 = gd_color_get_from_hsv(h1, s1, v1);    // dirt
+  cave->color2 = gd_color_get_from_hsv(h2, s2, v2);    // steel
+  cave->color3 = gd_color_get_from_hsv(h3, s3, v3);    // brick
+  // green(120+-20) with the saturation and brightness of brick
+  cave->color4 = gd_color_get_from_hsv(gd_random_int_range(100, 140), s2, v2);
+  // blue(240+-20) with saturation and brightness of dirt
+  cave->color5 = gd_color_get_from_hsv(gd_random_int_range(220, 260), s1, v1);
+}
+
+void gd_cave_set_random_colors(GdCave *cave, GdColorType type)
+{
+  switch (type)
+  {
+    case GD_COLOR_TYPE_RGB:
+      gd_cave_set_random_rgb_colors(cave);
+      break;
+
+    case GD_COLOR_TYPE_C64:
+      gd_cave_set_random_c64_colors(cave);
+      break;
+
+    case GD_COLOR_TYPE_C64DTV:
+      gd_cave_set_random_c64dtv_colors(cave);
+      break;
+
+    case GD_COLOR_TYPE_ATARI:
+      gd_cave_set_random_atari_colors(cave);
+      break;
+
+    default:
+      break;
+  }
+}
+
 /*
   shrink cave
   if last line or last row is just steel wall (or (invisible) outbox).
index 483b54feafcaafdcf99d6ed4d72753ddc8b23585..c76923a9f75980681728083dc5c3f426b11ab095 100644 (file)
@@ -661,6 +661,7 @@ void gd_cave_free(GdCave *cave);
 void gd_cave_set_gdash_defaults(GdCave *cave);
 void gd_cave_set_defaults_from_array(GdCave* cave, GdPropertyDefault *defaults);
 void gd_cave_correct_visible_size(GdCave *cave);
+void gd_cave_set_random_colors(GdCave *cave, GdColorType type);
 void gd_cave_auto_shrink(GdCave *cave);
 
 void gd_cave_setup_for_game(GdCave *cave);
index 57f02ab0dd9294664bce0af4fab304f81d85e42f..9641fa07e6e28d65cc1f608fb337e90ca95ca416 100644 (file)
@@ -555,12 +555,22 @@ GdColor gd_atari_color(int index)
   return (GD_COLOR_TYPE_ATARI << 24) + index;
 }
 
+GdColor gd_atari_color_huesat(int hue, int sat)
+{
+  return gd_atari_color(16 * hue + sat);
+}
+
 // return c64dtv color with index.
 GdColor gd_c64dtv_color(int index)
 {
   return (GD_COLOR_TYPE_C64DTV << 24) + index;
 }
 
+GdColor gd_c64dtv_color_huesat(int hue, int sat)
+{
+  return gd_c64dtv_color(16 * hue + sat);
+}
+
 // return "unknown color"
 static GdColor unknown_color(void)
 {
@@ -632,6 +642,36 @@ GdColor gd_color_get_from_rgb(int r, int g, int b)
   return (GD_COLOR_TYPE_RGB << 24) + (r << 16) + (g << 8) + b;
 }
 
+// make up GdColor from h,s,v values.
+// h=0..360, s=0..1, v=0..1
+GdColor gd_color_get_from_hsv(double h, double s, double v)
+{
+  int hi = (int)(h / 60) % 6;
+  double f = h / 60 - (int)(h / 60);    // fractional part
+  double p = v * (1 - s);
+  double q = v * (1 - f * s);
+  double t = v * (1 - (1 - f) * s);
+
+  v *= 255;
+  p *= 255;
+  q *= 255;
+  t *= 255;
+
+  switch(hi)
+  {
+    case 0: return gd_color_get_from_rgb(v, t, p);
+    case 1: return gd_color_get_from_rgb(q, v, p);
+    case 2: return gd_color_get_from_rgb(p, v, t);
+    case 3: return gd_color_get_from_rgb(p, q, v);
+    case 4: return gd_color_get_from_rgb(t, p, v);
+    case 5: return gd_color_get_from_rgb(v, p, q);
+  }
+
+  // no way we reach this
+  return gd_color_get_from_rgb(0, 0, 0);
+}
+
+
 GdColor gd_color_get_from_string(const char *color)
 {
   int i, r, g, b;
index f3d09cae9bb4d57a064a5af48926faef091202e1..21cc82d7990301fe05a2f9c0cd81c7f5b254cf5b 100644 (file)
@@ -85,12 +85,16 @@ GdColor gd_c64_color(int index);
 GdColor gd_atari_color(int index);
 GdColor gd_c64dtv_color(int index);
 
+GdColor gd_atari_color_huesat(int hue, int sat);
+GdColor gd_c64dtv_color_huesat(int hue, int sat);
+
 unsigned int gd_color_get_r(GdColor color);
 unsigned int gd_color_get_g(GdColor color);
 unsigned int gd_color_get_b(GdColor color);
 
 GdColor gd_color_get_rgb(GdColor color);
 GdColor gd_color_get_from_rgb(int r, int g, int b);
+GdColor gd_color_get_from_hsv(double h, double s, double v);
 GdColor gd_color_get_from_string(const char *color);
 const char *gd_color_get_string(GdColor color);