scroll_y = game.forced_scroll_y;
// !!! FIX THIS (START) !!!
- if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+ if (level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ {
+ InitGameEngine_BD();
+ }
+ else if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
{
InitGameEngine_EM();
}
}
// if not counting score after game, immediately update game panel values
- if (level_editor_test_game || !setup.count_score_after_game)
+ if (level_editor_test_game || !setup.count_score_after_game ||
+ level.game_engine_type == GAME_ENGINE_TYPE_BD)
{
time = time_final;
score = score_final;
static void PlayTimeoutSound(int seconds_left)
{
+ // will be played directly by BD engine (for classic bonus time sounds)
+ if (level.game_engine_type == GAME_ENGINE_TYPE_BD && checkBonusTime_BD())
+ return;
+
// try to use individual "running out of time" sound for each second left
int sound = SND_GAME_RUNNING_OUT_OF_TIME_0 - seconds_left;
static void CheckLevelTime(void)
{
+ int frames_per_second = FRAMES_PER_SECOND;
int i;
- if (TimeFrames >= FRAMES_PER_SECOND)
+ if (level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ {
+ // level time may be running slower in native BD engine
+ frames_per_second = getFramesPerSecond_BD();
+
+ // if native engine time changed, force main engine time change
+ if (getTimeLeft_BD() < TimeLeft)
+ TimeFrames = frames_per_second;
+
+ // if last second running, wait for native engine time to exactly reach zero
+ if (getTimeLeft_BD() == 1 && TimeLeft == 1)
+ TimeFrames = frames_per_second - 1;
+ }
+
+ if (TimeFrames >= frames_per_second)
{
TimeFrames = 0;
if (!TimeLeft && game.time_limit)
{
- if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+ if (level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ {
+ if (game_bd.game->cave->player_state == GD_PL_LIVING)
+ game_bd.game->cave->player_state = GD_PL_TIMEOUT;
+ }
+ else if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+ {
game_em.lev->killed_out_of_time = TRUE;
+ }
else
+ {
for (i = 0; i < MAX_PLAYERS; i++)
KillPlayer(&stored_player[i]);
+ }
}
}
else if (game.no_level_time_limit && !game.all_players_gone)
{
int i;
+ // handle game and tape time differently for native BD game engine
+
+ // tape time is running in native BD engine even if player is not hatched yet
+ if (!checkGameRunning())
+ return;
+
// advance frame counters (global frame counter and tape time frame counter)
FrameCounter++;
TapeTimeFrames++;
+ // level time is running in native BD engine after player is being hatched
+ if (!checkGamePlaying())
+ return;
+
// advance time frame counter (used to control available time to solve level)
TimeFrames++;
game.snapshot.last_action[i] = stored_player[i].effective_action;
}
- if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+ if (level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ {
+ GameActions_BD_Main();
+ }
+ else if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
{
GameActions_EM_Main();
}
GameActions_CheckSaveEngineSnapshot();
}
+void GameActions_BD_Main(void)
+{
+ byte effective_action[MAX_PLAYERS];
+ int i;
+
+ for (i = 0; i < MAX_PLAYERS; i++)
+ effective_action[i] = stored_player[i].effective_action;
+
+ GameActions_BD(effective_action);
+}
+
void GameActions_EM_Main(void)
{
byte effective_action[MAX_PLAYERS];
return TRUE;
}
+boolean checkGamePlaying(void)
+{
+ if (game_status != GAME_MODE_PLAYING)
+ return FALSE;
+
+ if (level.game_engine_type == GAME_ENGINE_TYPE_BD && !checkGamePlaying_BD())
+ return FALSE;
+
+ return TRUE;
+}
+
boolean checkGameSolved(void)
{
// set for all game engines if level was solved
void StartGameActions(boolean, boolean, int);
void GameActions(void);
+void GameActions_BD_Main(void);
void GameActions_EM_Main(void);
void GameActions_SP_Main(void);
void GameActions_MM_Main(void);
boolean CheckRestartGame(void);
boolean checkGameRunning(void);
+boolean checkGamePlaying(void);
boolean checkGameSolved(void);
boolean checkGameFailed(void);
boolean checkGameEnded(void);
int map_action_BD_to_RND(int);
boolean checkGameRunning_BD(void);
+boolean checkGamePlaying_BD(void);
+boolean checkBonusTime_BD(void);
+int getFramesPerSecond_BD(void);
+int getTimeLeft_BD(void);
void InitGfxBuffers_BD(void);
boolean LoadNativeLevel_BD(char *, int, boolean);
unsigned int InitEngineRandom_BD(int);
+void InitGameEngine_BD(void);
+void GameActions_BD(byte[MAX_PLAYERS]);
void CoverScreen_BD(void);
void BlitScreenToBitmap_BD(Bitmap *);
return (game_bd.game != NULL && game_bd.game->state_counter == GAME_INT_CAVE_RUNNING);
}
+boolean checkGamePlaying_BD(void)
+{
+ return (game_bd.game != NULL && game_bd.game->state_counter == GAME_INT_CAVE_RUNNING &&
+ game_bd.game->cave != NULL && game_bd.game->cave->hatched);
+}
+
+boolean checkBonusTime_BD(void)
+{
+ return (game_bd.game != NULL && game_bd.game->state_counter == GAME_INT_CHECK_BONUS_TIME);
+}
+
+int getFramesPerSecond_BD(void)
+{
+ if (game_bd.game != NULL && game_bd.game->cave != NULL && game_bd.game->cave->pal_timing)
+ return FRAMES_PER_SECOND_NTSC;
+
+ return FRAMES_PER_SECOND_PAL;
+}
+
+int getTimeLeft_BD(void)
+{
+ if (game_bd.game != NULL && game_bd.game->cave != NULL)
+ return gd_cave_time_show(game_bd.game->cave, game_bd.game->cave->time);
+
+ return 0;
+}
+
+static void UpdateGameDoorValues_BD(void)
+{
+ GdCave *cave = game_bd.game->cave;
+ int time_secs = gd_cave_time_show(cave, cave->time);
+ int gems_still_needed = MAX(0, (cave->diamonds_needed - cave->diamonds_collected));
+
+ game_bd.time_played = time_secs;
+ game_bd.gems_still_needed = gems_still_needed;
+ game_bd.score = game_bd.game->player_score;
+
+ if (game.LevelSolved)
+ {
+ // update time and score in panel while counting bonus time
+ game.LevelSolved_CountingTime = game_bd.time_played;
+ game.LevelSolved_CountingScore = game_bd.score;
+ }
+}
+
unsigned int InitEngineRandom_BD(int seed)
{
if (seed == NEW_RANDOMIZE)
return (unsigned int)seed;
}
+void InitGameEngine_BD(void)
+{
+ game_bd.level_solved = FALSE;
+ game_bd.game_over = FALSE;
+ game_bd.cover_screen = FALSE;
+
+ game_bd.time_played = 0;
+ game_bd.gems_still_needed = 0;
+ game_bd.score = 0;
+
+ gd_caveset_last_selected = native_bd_level.cave_nr;
+ gd_caveset_last_selected_level = native_bd_level.level_nr;
+
+ if (game_bd.game != NULL)
+ gd_game_free(game_bd.game);
+
+ game_bd.game = gd_game_new(native_bd_level.cave_nr, native_bd_level.level_nr);
+
+ // default: start with completely covered playfield
+ int next_state = GAME_INT_START_UNCOVER + 1;
+
+ // when skipping uncovering, start with uncovered playfield
+ if (setup.bd_skip_uncovering)
+ next_state = GAME_INT_LOAD_CAVE + 1;
+
+ // fast-forward game engine until cave loaded (covered or uncovered)
+ while (game_bd.game->state_counter < next_state)
+ play_game_func(game_bd.game, 0);
+
+ // when skipping uncovering, continue with uncovered playfield
+ if (setup.bd_skip_uncovering)
+ game_bd.game->state_counter = GAME_INT_UNCOVER_ALL + 1;
+
+ if (setup.bd_skip_uncovering)
+ gd_scroll(game_bd.game, TRUE, TRUE);
+
+ RedrawPlayfield_BD(TRUE);
+
+ UpdateGameDoorValues_BD();
+}
+
+void GameActions_BD(byte action[MAX_PLAYERS])
+{
+ GdCave *cave = game_bd.game->cave;
+ boolean player_found = FALSE;
+ int player_x = 0;
+ int player_y = 0;
+ int x, y;
+
+ if (cave->getp)
+ {
+ for (y = 0; y < cave->h && !player_found; y++)
+ {
+ for (x = 0; x < cave->w && !player_found; x++)
+ {
+ int element = *cave->getp(cave, x, y);
+
+ if (element == O_PLAYER ||
+ element == O_PLAYER_BOMB ||
+ element == O_PLAYER_STIRRING ||
+ element == O_PLAYER_PNEUMATIC_LEFT ||
+ element == O_PLAYER_PNEUMATIC_RIGHT)
+ {
+ player_x = x;
+ player_y = y;
+
+ player_found = TRUE;
+ }
+ }
+ }
+ }
+
+ UpdateEngineValues(get_scroll_x(),
+ get_scroll_y(),
+ player_x,
+ player_y);
+
+ if (setup.bd_skip_hatching && !game_bd.game->cave->hatched &&
+ game_bd.game->state_counter == GAME_INT_CAVE_RUNNING)
+ {
+ // fast-forward game engine until player hatched
+ while (!game_bd.game->cave->hatched)
+ {
+ play_game_func(game_bd.game, 0);
+
+ // also record or replay tape action during fast-forward
+ action = TapeCorrectAction_BD(action);
+ }
+ }
+
+ play_game_func(game_bd.game, action[0]);
+
+ RedrawPlayfield_BD(FALSE);
+
+ UpdateGameDoorValues_BD();
+}
+
// ============================================================================
// graphics functions
#define MAX_VSYNC_FRAME_DELAY 16 // maximum value for vsync to work
#define FRAMES_PER_SECOND (ONE_SECOND_DELAY / GAME_FRAME_DELAY)
#define FRAMES_PER_SECOND_SP 35
+#define FRAMES_PER_SECOND_PAL 50
+#define FRAMES_PER_SECOND_NTSC 60
// maximum playfield size supported by libgame functions
#define MAX_PLAYFIELD_WIDTH 128