X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame_bd%2Fbd_cave.c;h=d946bac4c203a3decaa24f2304211802e40a217c;hb=edaa850fd2d2cae7ec31961fae3d56487e710c71;hp=88fa93299f57d61f39ce44e38802ab87f576978c;hpb=ee1d57d74c4e4037fafb677953f8363489a263d0;p=rocksndiamonds.git diff --git a/src/game_bd/bd_cave.c b/src/game_bd/bd_cave.c index 88fa9329..d946bac4 100644 --- a/src/game_bd/bd_cave.c +++ b/src/game_bd/bd_cave.c @@ -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). @@ -1158,13 +1316,14 @@ void gd_cave_count_diamonds(GdCave *cave) if a cell is changed, it is flagged with GD_REDRAW; the flag can be cleared by the caller. */ -void gd_drawcave_game(const GdCave *cave, int **element_buffer, int **gfx_buffer, +void gd_drawcave_game(const GdCave *cave, + int **element_buffer, int **last_element_buffer, int **gfx_buffer, boolean bonus_life_flash, int animcycle, boolean hate_invisible_outbox) { static int player_blinking = 0; static int player_tapping = 0; - int elemmapping[O_MAX]; - int elemdrawing[O_MAX]; + int elemmapping[O_MAX_ALL]; + int elemdrawing[O_MAX_ALL]; int x, y, map, draw; if (cave->last_direction) @@ -1188,7 +1347,7 @@ void gd_drawcave_game(const GdCave *cave, int **element_buffer, int **gfx_buffer } } - for (x = 0; x < O_MAX; x++) + for (x = 0; x < O_MAX_ALL; x++) { elemmapping[x] = x; elemdrawing[x] = gd_elements[x].image_game; @@ -1296,6 +1455,16 @@ void gd_drawcave_game(const GdCave *cave, int **element_buffer, int **gfx_buffer draw = gd_elements[O_PLAYER].image_game; } } + else if (cave->last_direction == GD_MV_UP && use_bd_up_down_graphics()) + { + map = O_PLAYER_UP; + draw = gd_elements[O_PLAYER_UP].image_game; + } + else if (cave->last_direction == GD_MV_DOWN && use_bd_up_down_graphics()) + { + map = O_PLAYER_DOWN; + draw = gd_elements[O_PLAYER_DOWN].image_game; + } else if (cave->last_horizontal_direction == GD_MV_LEFT) { map = O_PLAYER_LEFT; @@ -1353,8 +1522,8 @@ void gd_drawcave_game(const GdCave *cave, int **element_buffer, int **gfx_buffer // change only graphically if (hate_invisible_outbox) { - elemmapping[O_PRE_INVIS_OUTBOX] = O_PRE_OUTBOX; - elemmapping[O_INVIS_OUTBOX] = O_OUTBOX; + elemmapping[O_PRE_INVIS_OUTBOX] = elemmapping[O_PRE_OUTBOX]; + elemmapping[O_INVIS_OUTBOX] = elemmapping[O_OUTBOX]; } if (hate_invisible_outbox) @@ -1381,6 +1550,28 @@ void gd_drawcave_game(const GdCave *cave, int **element_buffer, int **gfx_buffer else draw = elemdrawing[actual]; + // draw special graphics if player is pushing something + if (use_bd_pushing_graphics() && + (cave->last_direction == GD_MV_LEFT || cave->last_direction == GD_MV_RIGHT) && + is_player(cave, x, y) && can_be_pushed_dir(cave, x, y, cave->last_direction)) + { + // special check needed when smooth game element movements selected in setup menu: + // last element must either be player (before pushing) or pushable element (while pushing) + // (extra check needed to prevent pushing animation when moving towards pushable element) + if (!use_bd_smooth_movements() || last_element_buffer[y][x] != O_SPACE) + { + if (cave->last_direction == GD_MV_LEFT) + map = O_PLAYER_PUSH_LEFT; + else + map = O_PLAYER_PUSH_RIGHT; + + if (cave->last_direction == GD_MV_LEFT) + draw = elemdrawing[O_PLAYER_PUSH_LEFT]; + else + draw = elemdrawing[O_PLAYER_PUSH_RIGHT]; + } + } + // if negative, animated. if (draw < 0) draw = -draw + animcycle;