X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=38650b36c8c52807fbbc582890a83f291877fd56;hb=86e110774e5210b326e6867b134bd638d93554d3;hp=d096ac20d4e1f6492ba149ab8345ca157947a4af;hpb=9a7426789c04bf396df78eb915522f9e57af985e;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index d096ac20..38650b36 100644 --- a/src/game.c +++ b/src/game.c @@ -76,29 +76,6 @@ #define DX_TIME (DX + XX_TIME) #define DY_TIME (DY + YY_TIME) -#define IS_LOOP_SOUND(s) ((s) == SND_BD_MAGIC_WALL_RUNNING || \ - (s) == SND_BD_BUTTERFLY_MOVING || \ - (s) == SND_BD_FIREFLY_MOVING || \ - (s) == SND_SP_SNIKSNAK_MOVING || \ - (s) == SND_SP_ELECTRON_MOVING || \ - (s) == SND_DYNAMITE_BURNING || \ - (s) == SND_BUG_MOVING || \ - (s) == SND_SPACESHIP_MOVING || \ - (s) == SND_YAMYAM_MOVING || \ - (s) == SND_YAMYAM_WAITING || \ - (s) == SND_ROBOT_WHEEL_RUNNING || \ - (s) == SND_MAGIC_WALL_RUNNING || \ - (s) == SND_BALLOON_MOVING || \ - (s) == SND_MOLE_MOVING || \ - (s) == SND_TIMEGATE_WHEEL_RUNNING || \ - (s) == SND_CONVEYOR_BELT_RUNNING || \ - (s) == SND_DYNABOMB_BURNING || \ - (s) == SND_PACMAN_MOVING || \ - (s) == SND_PENGUIN_MOVING || \ - (s) == SND_PIG_MOVING || \ - (s) == SND_DRAGON_MOVING || \ - (s) == SND_DRAGON_BREATHING_FIRE) - /* values for player movement speed (which is in fact a delay value) */ #define MOVE_DELAY_NORMAL_SPEED 8 #define MOVE_DELAY_HIGH_SPEED 4 @@ -123,11 +100,30 @@ static void CloseAllOpenTimegates(void); static void CheckGravityMovement(struct PlayerInfo *); static void KillHeroUnlessProtected(int, int); +void PlaySoundLevel(int, int, int); +void PlaySoundLevelAction(int, int, int); + static void MapGameButtons(); static void HandleGameButtons(struct GadgetInfo *); static struct GadgetInfo *game_gadget[NUM_GAME_BUTTONS]; +static char *loop_sound_actions[] = +{ + ".waiting", + ".moving", + ".running", + ".burning", + ".growing", + ".attacking" +}; +static boolean is_loop_sound[NUM_SOUND_EFFECTS]; +static boolean sound_info_initialized = FALSE; + +#define IS_LOOP_SOUND(x) (is_loop_sound[x]) + +#define SND_MOVING 1 +#define SND_WAITING 2 #ifdef DEBUG @@ -721,6 +717,37 @@ void InitGame() } } + /* initialize sound effect properties */ + if (!sound_info_initialized) + { + int i, j; + + for (i=0; i len_action_text && + strcmp(&sound_effects[i].text[len_effect_text - len_action_text], + loop_sound_actions[j]) == 0) + is_loop_sound[i] = TRUE; + } + } + + for (i=0; iLevelSolved = FALSE; - PlaySoundStereo(SND_GAME_WINNING, PSND_MAX_RIGHT); + PlaySoundStereo(SND_GAME_WINNING, SOUND_MAX_RIGHT); if (TimeLeft) { if (!tape.playing && setup.sound_loops) - PlaySoundExt(SND_GAME_LEVELTIME_BONUS, PSND_MAX_VOLUME, PSND_MAX_RIGHT, + PlaySoundExt(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_VOLUME, SOUND_MAX_RIGHT, SND_CTRL_PLAY_LOOP); while (TimeLeft > 0) { if (!tape.playing && !setup.sound_loops) - PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, PSND_MAX_RIGHT); + PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_RIGHT); if (TimeLeft > 0 && !(TimeLeft % 10)) RaiseScore(level.score[SC_ZEITBONUS]); if (TimeLeft > 100 && !(TimeLeft % 10)) @@ -1028,13 +1055,13 @@ void GameWon() else if (level.time == 0) /* level without time limit */ { if (!tape.playing && setup.sound_loops) - PlaySoundExt(SND_GAME_LEVELTIME_BONUS, PSND_MAX_VOLUME, PSND_MAX_RIGHT, + PlaySoundExt(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_VOLUME, SOUND_MAX_RIGHT, SND_CTRL_PLAY_LOOP); while (TimePlayed < 999) { if (!tape.playing && !setup.sound_loops) - PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, PSND_MAX_RIGHT); + PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_RIGHT); if (TimePlayed < 999 && !(TimePlayed % 10)) RaiseScore(level.score[SC_ZEITBONUS]); if (TimePlayed < 900 && !(TimePlayed % 10)) @@ -1328,7 +1355,11 @@ void CheckDynamite(int x, int y) MovDelay[x][y]--; if (MovDelay[x][y]) { +#if 0 if (!(MovDelay[x][y] % 12)) +#else + if (!(MovDelay[x][y] % 6)) +#endif { if (Feld[x][y] == EL_DYNAMITE_ACTIVE) PlaySoundLevel(x, y, SND_DYNAMITE_BURNING); @@ -2752,6 +2783,7 @@ void StartMoving(int x, int y) if (element!=EL_MAMPFER && element!=EL_MAMPFER2 && element!=EL_PACMAN) { TurnRound(x, y); + if (MovDelay[x][y] && (element == EL_KAEFER || element == EL_FLIEGER || element == EL_SP_SNIKSNAK || @@ -2829,43 +2861,14 @@ void StartMoving(int x, int y) } } - if (MovDelay[x][y]) + if (MovDelay[x][y]) /* element still has to wait some time */ + { + PlaySoundLevelAction(x, y, SND_WAITING); + return; + } } - if (element == EL_KAEFER) - PlaySoundLevel(x, y, SND_BUG_MOVING); - else if (element == EL_FLIEGER) - PlaySoundLevel(x, y, SND_SPACESHIP_MOVING); - else if (element == EL_BUTTERFLY) - PlaySoundLevel(x, y, SND_BD_BUTTERFLY_MOVING); - else if (element == EL_FIREFLY) - PlaySoundLevel(x, y, SND_BD_FIREFLY_MOVING); - else if (element == EL_SP_SNIKSNAK) - PlaySoundLevel(x, y, SND_SP_SNIKSNAK_MOVING); - else if (element == EL_SP_ELECTRON) - PlaySoundLevel(x, y, SND_SP_ELECTRON_MOVING); - else if (element == EL_MAMPFER) - PlaySoundLevel(x, y, SND_YAMYAM_MOVING); - else if (element == EL_MAMPFER2) - PlaySoundLevel(x, y, SND_DARK_YAMYAM_MOVING); - else if (element == EL_BALLOON) - PlaySoundLevel(x, y, SND_BALLOON_MOVING); - else if (element == EL_SPRING_MOVING) - PlaySoundLevel(x, y, SND_SPRING_MOVING); - else if (element == EL_MOLE) - PlaySoundLevel(x, y, SND_MOLE_MOVING); - else if (element == EL_SONDE) - PlaySoundLevel(x, y, SND_SATELLITE_MOVING); - else if (element == EL_PACMAN) - PlaySoundLevel(x, y, SND_PACMAN_MOVING); - else if (element == EL_PINGUIN) - PlaySoundLevel(x, y, SND_PENGUIN_MOVING); - else if (element == EL_SCHWEIN) - PlaySoundLevel(x, y, SND_PIG_MOVING); - else if (element == EL_DRACHE) - PlaySoundLevel(x, y, SND_DRAGON_MOVING); - /* now make next step */ Moving2Blocked(x, y, &newx, &newy); /* get next screen position */ @@ -2980,7 +2983,7 @@ void StartMoving(int x, int y) else DrawLevelField(x, y); - PlaySoundLevel(x, y, SND_DRAGON_BREATHING_FIRE); + PlaySoundLevel(x, y, SND_DRAGON_ATTACKING); MovDelay[x][y] = 50; Feld[newx][newy] = EL_BURNING; @@ -3077,13 +3080,14 @@ void StartMoving(int x, int y) if (DONT_TOUCH(element)) TestIfBadThingTouchesHero(x, y); + PlaySoundLevelAction(x, y, SND_WAITING); + return; } - if (element == EL_ROBOT && IN_SCR_FIELD(x, y)) - PlaySoundLevel(x, y, SND_ROBOT_MOVING); - InitMovingField(x, y, MovDir[x][y]); + + PlaySoundLevelAction(x, y, SND_MOVING); } if (MovDir[x][y]) @@ -3123,7 +3127,7 @@ void ContinueMoving(int x, int y) MovPos[x][y] += step; - if (ABS(MovPos[x][y])>=TILEX) /* object reached its destination */ + if (ABS(MovPos[x][y]) >= TILEX) /* object reached its destination */ { Feld[x][y] = EL_LEERRAUM; Feld[newx][newy] = element; @@ -4358,6 +4362,9 @@ static void DrawBeltAnimation(int x, int y, int element) int graphic = el2gfx(element) + (belt_dir == MV_LEFT ? 0 : 7); DrawGraphicAnimation(x, y, graphic, 8, delay, mode); + + if (!(FrameCounter % 2)) + PlaySoundLevel(x, y, SND_CONVEYOR_BELT_RUNNING); } } @@ -4708,11 +4715,7 @@ void GameActions() else if (element == EL_SP_TERMINAL_ACTIVE) DrawGraphicAnimation(x, y, GFX2_SP_TERMINAL_ACTIVE, 7, 4, ANIM_NORMAL); else if (IS_BELT(element)) - { DrawBeltAnimation(x, y, element); - if (!(FrameCounter % 2)) - PlaySoundLevel(x, y, SND_CONVEYOR_BELT_RUNNING); - } else if (element == EL_SWITCHGATE_OPENING) OpenSwitchgate(x, y); else if (element == EL_SWITCHGATE_CLOSING) @@ -4921,7 +4924,7 @@ void GameActions() TimeLeft--; if (TimeLeft <= 10 && setup.time_limit) - PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, PSND_MAX_RIGHT); + PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MAX_RIGHT); DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW); @@ -5044,7 +5047,9 @@ static void CheckGravityMovement(struct PlayerInfo *player) (Feld[new_jx][new_jy] == EL_SP_BASE || Feld[new_jx][new_jy] == EL_ERDREICH)); - if (field_under_player_is_free && !player_is_moving_to_valid_field) + if (field_under_player_is_free && + !player_is_moving_to_valid_field && + !IS_TUBE(Feld[jx][jy])) player->programmed_action = MV_DOWN; } } @@ -5666,7 +5671,7 @@ int DigField(struct PlayerInfo *player, dy == +1 ? MV_DOWN : MV_NO_MOVING); int element; - if (!player->MovPos) + if (player->MovPos == 0) player->Pushing = FALSE; if (mode == DF_NO_PUSH) @@ -5787,7 +5792,7 @@ int DigField(struct PlayerInfo *player, TimeLeft += 10; DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW); } - PlaySoundStereo(SND_EXTRA_TIME_COLLECTING, PSND_MAX_RIGHT); + PlaySoundStereo(SND_EXTRA_TIME_COLLECTING, SOUND_MAX_RIGHT); break; case EL_SHIELD_PASSIVE: @@ -5970,6 +5975,7 @@ int DigField(struct PlayerInfo *player, element == EL_BALLOON_SEND_UP ? MV_UP : element == EL_BALLOON_SEND_DOWN ? MV_DOWN : MV_NO_MOVING); + PlaySoundLevel(x, y, SND_BALLOON_SWITCH_ACTIVATING); return MF_ACTION; break; @@ -5979,11 +5985,11 @@ int DigField(struct PlayerInfo *player, return MF_NO_ACTION; player->LevelSolved = player->GameOver = TRUE; - PlaySoundStereo(SND_SP_EXIT_ENTERING, PSND_MAX_RIGHT); + PlaySoundStereo(SND_SP_EXIT_ENTERING, SOUND_MAX_RIGHT); break; + /* the following elements cannot be pushed by "snapping" */ case EL_FELSBROCKEN: - case EL_BD_ROCK: case EL_BOMBE: case EL_DX_SUPABOMB: case EL_KOKOSNUSS: @@ -5991,7 +5997,12 @@ int DigField(struct PlayerInfo *player, case EL_SP_ZONK: case EL_SP_DISK_ORANGE: case EL_SPRING: - if (dy || mode == DF_SNAP) + if (mode == DF_SNAP) + return MF_NO_ACTION; + /* no "break" -- fall through to next case */ + /* the following elements can be pushed by "snapping" */ + case EL_BD_ROCK: + if (dy) return MF_NO_ACTION; player->Pushing = TRUE; @@ -6018,8 +6029,16 @@ int DigField(struct PlayerInfo *player, return MF_NO_ACTION; #endif - RemoveField(x, y); - Feld[x+dx][y+dy] = element; + if (mode == DF_SNAP) + { + InitMovingField(x, y, move_direction); + ContinueMoving(x, y); + } + else + { + RemoveField(x, y); + Feld[x+dx][y+dy] = element; + } if (element == EL_SPRING) { @@ -6196,6 +6215,8 @@ int DigField(struct PlayerInfo *player, if (!(tube_enter_directions[i][1] & move_direction)) return MF_NO_ACTION; /* tube has no opening in this direction */ + + PlaySoundLevel(x, y, SND_TUBE_PASSING); } break; @@ -6226,7 +6247,7 @@ int DigField(struct PlayerInfo *player, TimeLeft += 10; DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW); DrawLevelField(x, y); - PlaySoundStereo(SND_TIME_ORB_FULL_COLLECTING, PSND_MAX_RIGHT); + PlaySoundStereo(SND_TIME_ORB_FULL_COLLECTING, SOUND_MAX_RIGHT); return MF_ACTION; break; @@ -6355,6 +6376,9 @@ boolean SnapField(struct PlayerInfo *player, int dx, int dy) if (!dx && !dy) { + if (player->MovPos == 0) + player->Pushing = FALSE; + player->snapped = FALSE; return FALSE; } @@ -6425,42 +6449,129 @@ boolean PlaceBomb(struct PlayerInfo *player) return TRUE; } -void PlaySoundLevel(int x, int y, int sound_nr) +void PlaySoundLevel(int x, int y, int nr) { + static int loop_sound_frame[NUM_SOUND_EFFECTS]; + static int loop_sound_volume[NUM_SOUND_EFFECTS]; int sx = SCREENX(x), sy = SCREENY(y); - int volume, stereo; - int silence_distance = 8; + int volume, stereo_position; + int max_distance = 8; + int type = (IS_LOOP_SOUND(nr) ? SND_CTRL_PLAY_LOOP : SND_CTRL_PLAY_SOUND); - if ((!setup.sound_simple && !IS_LOOP_SOUND(sound_nr)) || - (!setup.sound_loops && IS_LOOP_SOUND(sound_nr))) + if ((!setup.sound_simple && !IS_LOOP_SOUND(nr)) || + (!setup.sound_loops && IS_LOOP_SOUND(nr))) return; if (!IN_LEV_FIELD(x, y) || - sx < -silence_distance || sx >= SCR_FIELDX+silence_distance || - sy < -silence_distance || sy >= SCR_FIELDY+silence_distance) + sx < -max_distance || sx >= SCR_FIELDX + max_distance || + sy < -max_distance || sy >= SCR_FIELDY + max_distance) return; - volume = PSND_MAX_VOLUME; - -#if !defined(PLATFORM_MSDOS) - stereo = (sx - SCR_FIELDX/2) * 12; -#else - stereo = PSND_MIDDLE + (2 * sx - (SCR_FIELDX - 1)) * 5; - if (stereo > PSND_MAX_RIGHT) - stereo = PSND_MAX_RIGHT; - if (stereo < PSND_MAX_LEFT) - stereo = PSND_MAX_LEFT; -#endif + volume = SOUND_MAX_VOLUME; if (!IN_SCR_FIELD(sx, sy)) { - int dx = ABS(sx - SCR_FIELDX/2) - SCR_FIELDX/2; - int dy = ABS(sy - SCR_FIELDY/2) - SCR_FIELDY/2; + int dx = ABS(sx - SCR_FIELDX / 2) - SCR_FIELDX / 2; + int dy = ABS(sy - SCR_FIELDY / 2) - SCR_FIELDY / 2; + + volume -= volume * (dx > dy ? dx : dy) / max_distance; + } + + stereo_position = (SOUND_MAX_LEFT + + (sx + max_distance) * SOUND_MAX_LEFT2RIGHT / + (SCR_FIELDX + 2 * max_distance)); + + if (IS_LOOP_SOUND(nr)) + { + /* This assures that quieter loop sounds do not overwrite louder ones, + while restarting sound volume comparison with each new game frame. */ + + if (loop_sound_volume[nr] > volume && loop_sound_frame[nr] == FrameCounter) + return; - volume -= volume * (dx > dy ? dx : dy) / silence_distance; + loop_sound_volume[nr] = volume; + loop_sound_frame[nr] = FrameCounter; } - PlaySoundExt(sound_nr, volume, stereo, SND_CTRL_PLAY_SOUND); + PlaySoundExt(nr, volume, stereo_position, type); +} + +void PlaySoundLevelAction(int x, int y, int action) +{ + int element = Feld[x][y]; + + if (action == SND_MOVING) + { + if (element == EL_KAEFER) + PlaySoundLevel(x, y, SND_BUG_MOVING); + else if (element == EL_FLIEGER) + PlaySoundLevel(x, y, SND_SPACESHIP_MOVING); + else if (element == EL_BUTTERFLY) + PlaySoundLevel(x, y, SND_BD_BUTTERFLY_MOVING); + else if (element == EL_FIREFLY) + PlaySoundLevel(x, y, SND_BD_FIREFLY_MOVING); + else if (element == EL_SP_SNIKSNAK) + PlaySoundLevel(x, y, SND_SP_SNIKSNAK_MOVING); + else if (element == EL_SP_ELECTRON) + PlaySoundLevel(x, y, SND_SP_ELECTRON_MOVING); + else if (element == EL_MAMPFER) + PlaySoundLevel(x, y, SND_YAMYAM_MOVING); + else if (element == EL_MAMPFER2) + PlaySoundLevel(x, y, SND_DARK_YAMYAM_MOVING); + else if (element == EL_BALLOON) + PlaySoundLevel(x, y, SND_BALLOON_MOVING); + else if (element == EL_SPRING_MOVING) + PlaySoundLevel(x, y, SND_SPRING_MOVING); + else if (element == EL_MOLE) + PlaySoundLevel(x, y, SND_MOLE_MOVING); + else if (element == EL_SONDE) + PlaySoundLevel(x, y, SND_SATELLITE_MOVING); + else if (element == EL_PACMAN) + PlaySoundLevel(x, y, SND_PACMAN_MOVING); + else if (element == EL_PINGUIN) + PlaySoundLevel(x, y, SND_PENGUIN_MOVING); + else if (element == EL_SCHWEIN) + PlaySoundLevel(x, y, SND_PIG_MOVING); + else if (element == EL_DRACHE) + PlaySoundLevel(x, y, SND_DRAGON_MOVING); + else if (element == EL_ROBOT) + PlaySoundLevel(x, y, SND_ROBOT_STEPPING); + } + else if (action == SND_WAITING) + { + if (element == EL_KAEFER) + PlaySoundLevel(x, y, SND_BUG_WAITING); + else if (element == EL_FLIEGER) + PlaySoundLevel(x, y, SND_SPACESHIP_WAITING); + else if (element == EL_BUTTERFLY) + PlaySoundLevel(x, y, SND_BD_BUTTERFLY_WAITING); + else if (element == EL_FIREFLY) + PlaySoundLevel(x, y, SND_BD_FIREFLY_WAITING); + else if (element == EL_SP_SNIKSNAK) + PlaySoundLevel(x, y, SND_SP_SNIKSNAK_WAITING); + else if (element == EL_SP_ELECTRON) + PlaySoundLevel(x, y, SND_SP_ELECTRON_WAITING); + else if (element == EL_MAMPFER) + PlaySoundLevel(x, y, SND_YAMYAM_WAITING); + else if (element == EL_MAMPFER2) + PlaySoundLevel(x, y, SND_DARK_YAMYAM_WAITING); + else if (element == EL_BALLOON) + PlaySoundLevel(x, y, SND_BALLOON_WAITING); + else if (element == EL_MOLE) + PlaySoundLevel(x, y, SND_MOLE_WAITING); + else if (element == EL_SONDE) + PlaySoundLevel(x, y, SND_SATELLITE_WAITING); + else if (element == EL_PACMAN) + PlaySoundLevel(x, y, SND_PACMAN_WAITING); + else if (element == EL_PINGUIN) + PlaySoundLevel(x, y, SND_PENGUIN_WAITING); + else if (element == EL_SCHWEIN) + PlaySoundLevel(x, y, SND_PIG_WAITING); + else if (element == EL_DRACHE) + PlaySoundLevel(x, y, SND_DRAGON_WAITING); + else if (element == EL_ROBOT) + PlaySoundLevel(x, y, SND_ROBOT_WAITING); + } } void RaiseScore(int value)