added support for native sounds of Boulder Dash game engine
authorHolger Schemel <info@artsoft.org>
Sun, 11 Feb 2024 00:30:11 +0000 (01:30 +0100)
committerHolger Schemel <info@artsoft.org>
Sun, 18 Feb 2024 14:57:41 +0000 (15:57 +0100)
src/conf_snd.c
src/game.c
src/game_bd/import_bd.h

index 64fda4965c41e54c258ad994dfd84181ae33f489..0edf618145cc87b3b0ea0fc1e961a2572c2c1028 100644 (file)
@@ -284,16 +284,42 @@ struct ConfigInfo sound_config[] =
   { "[mm_steel_lock].exploding",       "whoosh.wav"                    },
   { "[mm_wooden_lock].exploding",      "whoosh.wav"                    },
 
-  // sounds not associated to game elements (used for menu screens etc.)
+
+  // ==========================================================================
+  // sound definitions not associated with game elements (menu screens etc.)
+  // ==========================================================================
+
   // keyword to stop parser: "NO_MORE_ELEMENT_SOUNDS" <-- do not change!
 
+  // sounds for Boulder Dash style elements and actions
+  { "bd_diamond.impact.RANDOM_1",      UNDEFINED_FILENAME              },
+  { "bd_diamond.impact.RANDOM_2",      UNDEFINED_FILENAME              },
+  { "bd_diamond.impact.RANDOM_3",      UNDEFINED_FILENAME              },
+  { "bd_diamond.impact.RANDOM_4",      UNDEFINED_FILENAME              },
+  { "bd_diamond.impact.RANDOM_5",      UNDEFINED_FILENAME              },
+  { "bd_diamond.impact.RANDOM_6",      UNDEFINED_FILENAME              },
+  { "bd_diamond.impact.RANDOM_7",      UNDEFINED_FILENAME              },
+  { "bd_diamond.impact.RANDOM_8",      UNDEFINED_FILENAME              },
+
   // sounds for other game actions
   { "game.starting",                   UNDEFINED_FILENAME              },
   { "game.leveltime_charging",         "fuel.wav"                      },
   { "game.health_charging",            "warnton.wav"                   },
   { "game.running_out_of_time",                "gong.wav"                      },
+  { "game.running_out_of_time_10",     UNDEFINED_FILENAME              },
+  { "game.running_out_of_time_9",      UNDEFINED_FILENAME              },
+  { "game.running_out_of_time_8",      UNDEFINED_FILENAME              },
+  { "game.running_out_of_time_7",      UNDEFINED_FILENAME              },
+  { "game.running_out_of_time_6",      UNDEFINED_FILENAME              },
+  { "game.running_out_of_time_5",      UNDEFINED_FILENAME              },
+  { "game.running_out_of_time_4",      UNDEFINED_FILENAME              },
+  { "game.running_out_of_time_3",      UNDEFINED_FILENAME              },
+  { "game.running_out_of_time_2",      UNDEFINED_FILENAME              },
+  { "game.running_out_of_time_1",      UNDEFINED_FILENAME              },
+  { "game.running_out_of_time_0",      UNDEFINED_FILENAME              },
   { "game.leveltime_bonus",            "sirr.wav"                      },
   { "game.health_bonus",               "sirr.wav"                      },
+  { "game.timeout",                    UNDEFINED_FILENAME              },
   { "game.losing",                     UNDEFINED_FILENAME              },
   { "game.winning",                    UNDEFINED_FILENAME              },
   { "game.sokoban_solving",            "buing.wav"                     },
index e6e78cbf92b0c713ed52641422fb08e6c7c1254d..0dc8e067ad913ae0110ae5782fdcfeef8fcac2a3 100644 (file)
@@ -15287,15 +15287,15 @@ void InitPlayLevelSound(void)
   loop_sound_volume = checked_calloc(num_sounds * sizeof(int));
 }
 
-static void PlayLevelSound(int x, int y, int nr)
+static void PlayLevelSoundExt(int x, int y, int nr, boolean is_loop_sound)
 {
   int sx = SCREENX(x), sy = SCREENY(y);
   int volume, stereo_position;
   int max_distance = 8;
-  int type = (IS_LOOP_SOUND(nr) ? SND_CTRL_PLAY_LOOP : SND_CTRL_PLAY_SOUND);
+  int type = (is_loop_sound ? SND_CTRL_PLAY_LOOP : SND_CTRL_PLAY_SOUND);
 
-  if ((!setup.sound_simple && !IS_LOOP_SOUND(nr)) ||
-      (!setup.sound_loops && IS_LOOP_SOUND(nr)))
+  if ((!setup.sound_simple && !is_loop_sound) ||
+      (!setup.sound_loops && is_loop_sound))
     return;
 
   if (!IN_LEV_FIELD(x, y) ||
@@ -15317,7 +15317,7 @@ static void PlayLevelSound(int x, int y, int nr)
                     (sx + max_distance) * SOUND_MAX_LEFT2RIGHT /
                     (SCR_FIELDX + 2 * max_distance));
 
-  if (IS_LOOP_SOUND(nr))
+  if (is_loop_sound)
   {
     /* This assures that quieter loop sounds do not overwrite louder ones,
        while restarting sound volume comparison with each new game frame. */
@@ -15332,6 +15332,11 @@ static void PlayLevelSound(int x, int y, int nr)
   PlaySoundExt(nr, volume, stereo_position, type);
 }
 
+static void PlayLevelSound(int x, int y, int nr)
+{
+  PlayLevelSoundExt(x, y, nr, IS_LOOP_SOUND(nr));
+}
+
 static void PlayLevelSoundNearest(int x, int y, int sound_action)
 {
   PlayLevelSound(x < LEVELX(BX1) ? LEVELX(BX1) :
@@ -15420,6 +15425,226 @@ static void PlayLevelMusic(void)
     PlayMusicLoop(music_nr);
 }
 
+static int getSoundAction_BD(int sample)
+{
+  switch (sample)
+  {
+    case GD_S_STONE:
+    case GD_S_NUT:
+    case GD_S_DIRT_BALL:
+    case GD_S_NITRO:
+    case GD_S_FALLING_WALL:
+      return ACTION_IMPACT;
+
+    case GD_S_NUT_CRACK:
+      return ACTION_BREAKING;
+
+    case GD_S_EXPANDING_WALL:
+    case GD_S_WALL_REAPPEAR:
+    case GD_S_SLIME:
+    case GD_S_LAVA:
+    case GD_S_ACID_SPREAD:
+      return ACTION_GROWING;
+
+    case GD_S_DIAMOND_COLLECT:
+    case GD_S_SKELETON_COLLECT:
+    case GD_S_PNEUMATIC_COLLECT:
+    case GD_S_BOMB_COLLECT:
+    case GD_S_CLOCK_COLLECT:
+    case GD_S_SWEET_COLLECT:
+    case GD_S_KEY_COLLECT:
+    case GD_S_DIAMOND_KEY_COLLECT:
+      return ACTION_COLLECTING;
+
+    case GD_S_BOMB_PLACE:
+    case GD_S_REPLICATOR:
+      return ACTION_DROPPING;
+
+    case GD_S_BLADDER_MOVE:
+      return ACTION_MOVING;
+
+    case GD_S_BLADDER_SPENDER:
+    case GD_S_BLADDER_CONVERT:
+    case GD_S_GRAVITY_CHANGE:
+      return ACTION_CHANGING;
+
+    case GD_S_BITER_EAT:
+      return ACTION_EATING;
+
+    case GD_S_DOOR_OPEN:
+    case GD_S_CRACK:
+      return ACTION_OPENING;
+
+    case GD_S_WALK_EARTH:
+      return ACTION_DIGGING;
+
+    case GD_S_WALK_EMPTY:
+      return ACTION_WALKING;
+
+    case GD_S_SWITCH_BITER:
+    case GD_S_SWITCH_CREATURES:
+    case GD_S_SWITCH_GRAVITY:
+    case GD_S_SWITCH_EXPANDING:
+    case GD_S_SWITCH_CONVEYOR:
+    case GD_S_SWITCH_REPLICATOR:
+    case GD_S_STIRRING:
+      return ACTION_ACTIVATING;
+
+    case GD_S_BOX_PUSH:
+      return ACTION_PUSHING;
+
+    case GD_S_TELEPORTER:
+      return ACTION_PASSING;
+
+    case GD_S_EXPLOSION:
+    case GD_S_BOMB_EXPLOSION:
+    case GD_S_GHOST_EXPLOSION:
+    case GD_S_VOODOO_EXPLOSION:
+    case GD_S_NITRO_EXPLOSION:
+      return ACTION_EXPLODING;
+
+    case GD_S_COVER:
+    case GD_S_AMOEBA:
+    case GD_S_AMOEBA_MAGIC:
+    case GD_S_MAGIC_WALL:
+    case GD_S_PNEUMATIC_HAMMER:
+    case GD_S_WATER:
+      return ACTION_ACTIVE;
+
+    case GD_S_DIAMOND_RANDOM:
+    case GD_S_DIAMOND_1:
+    case GD_S_DIAMOND_2:
+    case GD_S_DIAMOND_3:
+    case GD_S_DIAMOND_4:
+    case GD_S_DIAMOND_5:
+    case GD_S_DIAMOND_6:
+    case GD_S_DIAMOND_7:
+    case GD_S_DIAMOND_8:
+    case GD_S_TIMEOUT_0:
+    case GD_S_TIMEOUT_1:
+    case GD_S_TIMEOUT_2:
+    case GD_S_TIMEOUT_3:
+    case GD_S_TIMEOUT_4:
+    case GD_S_TIMEOUT_5:
+    case GD_S_TIMEOUT_6:
+    case GD_S_TIMEOUT_7:
+    case GD_S_TIMEOUT_8:
+    case GD_S_TIMEOUT_9:
+    case GD_S_TIMEOUT_10:
+    case GD_S_BONUS_LIFE:
+      // kludge to prevent playing as loop sound
+      return ACTION_OTHER;
+
+    case GD_S_FINISHED:
+      return ACTION_DEFAULT;
+
+    default:
+      return ACTION_DEFAULT;
+  }
+}
+
+static int getSoundEffect_BD(int element_bd, int sample)
+{
+  int sound_action = getSoundAction_BD(sample);
+  int sound_effect = element_info[SND_ELEMENT(element_bd)].sound[sound_action];
+  int nr;
+
+  // standard sounds
+  if (sound_action != ACTION_OTHER &&
+      sound_action != ACTION_DEFAULT)
+    return sound_effect;
+
+  // special sounds
+  switch (sample)
+  {
+    case GD_S_DIAMOND_RANDOM:
+      nr = GetSimpleRandom(8);
+      sound_effect = SND_BD_DIAMOND_IMPACT_RANDOM_1 + nr;
+      break;
+
+    case GD_S_DIAMOND_1:
+    case GD_S_DIAMOND_2:
+    case GD_S_DIAMOND_3:
+    case GD_S_DIAMOND_4:
+    case GD_S_DIAMOND_5:
+    case GD_S_DIAMOND_6:
+    case GD_S_DIAMOND_7:
+    case GD_S_DIAMOND_8:
+      nr = sample - GD_S_DIAMOND_1;
+      sound_effect = SND_BD_DIAMOND_IMPACT_RANDOM_1 + nr;
+      break;
+
+    case GD_S_TIMEOUT_0:
+    case GD_S_TIMEOUT_1:
+    case GD_S_TIMEOUT_2:
+    case GD_S_TIMEOUT_3:
+    case GD_S_TIMEOUT_4:
+    case GD_S_TIMEOUT_5:
+    case GD_S_TIMEOUT_6:
+    case GD_S_TIMEOUT_7:
+    case GD_S_TIMEOUT_8:
+    case GD_S_TIMEOUT_9:
+    case GD_S_TIMEOUT_10:
+      nr = sample - GD_S_TIMEOUT_0;
+      sound_effect = SND_GAME_RUNNING_OUT_OF_TIME_0 + nr;
+
+      if (getSoundInfoEntryFilename(sound_effect) == NULL && sample != GD_S_TIMEOUT_0)
+       sound_effect = SND_GAME_RUNNING_OUT_OF_TIME;
+      break;
+
+    case GD_S_FINISHED:
+      sound_effect = SND_GAME_LEVELTIME_BONUS;
+      break;
+
+    case GD_S_BONUS_LIFE:
+      sound_effect = SND_GAME_HEALTH_BONUS;
+      break;
+
+    default:
+      sound_effect = SND_UNDEFINED;
+      break;
+  }
+
+  return sound_effect;
+}
+
+void PlayLevelSound_BD(int xx, int yy, int element_bd, int sample)
+{
+  int element = (element_bd > -1 ? map_element_BD_to_RND(element_bd) : 0);
+  int sound_effect = getSoundEffect_BD(element, sample);
+  int sound_action = getSoundAction_BD(sample);
+  boolean is_loop_sound = IS_LOOP_SOUND(sound_effect);
+  int offset = 0;
+  int x = xx - offset;
+  int y = yy - offset;
+
+  if (sound_action == ACTION_OTHER)
+    is_loop_sound = FALSE;
+
+  if (sound_effect != SND_UNDEFINED)
+    PlayLevelSoundExt(x, y, sound_effect, is_loop_sound);
+}
+
+void StopSound_BD(int element_bd, int sample)
+{
+  int element = (element_bd > -1 ? map_element_BD_to_RND(element_bd) : 0);
+  int sound_effect = getSoundEffect_BD(element, sample);
+
+  if (sound_effect != SND_UNDEFINED)
+    StopSound(sound_effect);
+}
+
+boolean isSoundPlaying_BD(int element_bd, int sample)
+{
+  int element = (element_bd > -1 ? map_element_BD_to_RND(element_bd) : 0);
+  int sound_effect = getSoundEffect_BD(element, sample);
+
+  if (sound_effect != SND_UNDEFINED)
+    return isSoundPlaying(sound_effect);
+
+  return FALSE;
+}
+
 void PlayLevelSound_EM(int xx, int yy, int element_em, int sample)
 {
   int element = (element_em > -1 ? map_element_EM_to_RND_game(element_em) : 0);
index 64b256c0ddf5b234d808561c4b1685c4f8e908a8..cccee3a4ca1da720916fe669ecb009ca484e497f 100644 (file)
@@ -22,4 +22,8 @@
 // functions and definitions exported from main program to game_bd
 // ============================================================================
 
+void PlayLevelSound_BD(int, int, int, int);
+void StopSound_BD(int, int);
+boolean isSoundPlaying_BD(int, int);
+
 #endif // IMPORT_BD_H