X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fgame.c;h=29303a7e2f75eb069f2d18bb80d21beae9f9b3a3;hp=f17eb32359f76fccb2c1e25371125322ae9d1b26;hb=4239ba2adc93afb81230b1a4ea42e7eaf68452c6;hpb=e20eec573781b34a21a17f87f03abb43f3814715 diff --git a/src/game.c b/src/game.c index f17eb323..29303a7e 100644 --- a/src/game.c +++ b/src/game.c @@ -25,10 +25,6 @@ #define DEBUG_INIT_PLAYER 1 #define DEBUG_PLAYER_ACTIONS 0 -// test element position in level set "test_gfxframe" / level "000" -#define DEBUG_GFXFRAME_X 11 -#define DEBUG_GFXFRAME_Y 9 - /* EXPERIMENTAL STUFF */ #define USE_NEW_AMOEBA_CODE FALSE @@ -2450,7 +2446,7 @@ void DisplayGameControlValues() /* redraw game control buttons */ RedrawGameButtons(); - game_status = GAME_MODE_PSEUDO_PANEL; + SetGameStatus(GAME_MODE_PSEUDO_PANEL); for (i = 0; i < NUM_GAME_PANEL_CONTROLS; i++) { @@ -2578,7 +2574,7 @@ void DisplayGameControlValues() redraw_mask |= REDRAW_DOOR_1; } - game_status = GAME_MODE_PLAYING; + SetGameStatus(GAME_MODE_PLAYING); } void UpdateAndDisplayGameControlValues() @@ -3044,11 +3040,14 @@ static void InitGameEngine() for (i = 0; i < MAX_PLAYERS; i++) game.snapshot.last_action[i] = 0; game.snapshot.changed_action = FALSE; + game.snapshot.collected_item = FALSE; game.snapshot.mode = (strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_STEP) ? SNAPSHOT_MODE_EVERY_STEP : strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_MOVE) ? - SNAPSHOT_MODE_EVERY_MOVE : SNAPSHOT_MODE_OFF); + SNAPSHOT_MODE_EVERY_MOVE : + strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_COLLECT) ? + SNAPSHOT_MODE_EVERY_COLLECT : SNAPSHOT_MODE_OFF); } int get_num_special_action(int element, int action_first, int action_last) @@ -3095,19 +3094,14 @@ void InitGame() int initial_move_dir = MV_DOWN; int i, j, x, y; -#if 1 - printf("::: game.graphics_engine_version == %d\n", - game.graphics_engine_version); -#endif - // required here to update video display before fading (FIX THIS) DrawMaskedBorder(REDRAW_DOOR_2); - game_status = GAME_MODE_PLAYING; - if (!game.restart_level) CloseDoor(DOOR_CLOSE_1); + SetGameStatus(GAME_MODE_PLAYING); + /* needed if different viewport properties defined for playing */ ChangeViewportPropertiesIfNeeded(); @@ -3119,12 +3113,14 @@ void InitGame() if (CheckIfGlobalBorderHasChanged()) fade_mask = REDRAW_ALL; - FadeOut(fade_mask); + ExpireSoundLoops(TRUE); - OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW); + FadeOut(fade_mask); ClearField(); + OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW); + DrawCompleteVideoDisplay(); InitGameEngine(); @@ -3395,10 +3391,6 @@ void InitGame() GfxRedraw[x][y] = GFX_REDRAW_NONE; } -#if 1 - printf("::: INIT GAME"); -#endif - SCAN_PLAYFIELD(x, y) { if (emulate_bd && !IS_BD_ELEMENT(Feld[x][y])) @@ -3413,10 +3405,6 @@ void InitGame() ResetGfxAnimation(x, y); } -#if 1 - printf(" -> %d\n", GfxFrame[DEBUG_GFXFRAME_X][DEBUG_GFXFRAME_Y]); -#endif - InitBeltMovement(); for (i = 0; i < MAX_PLAYERS; i++) @@ -4436,7 +4424,7 @@ void GameEnd() if (level_editor_test_game) { - game_status = GAME_MODE_MAIN; + SetGameStatus(GAME_MODE_MAIN); DrawMainMenu(); @@ -4445,9 +4433,7 @@ void GameEnd() if (!local_player->LevelSolved_SaveScore) { - FadeOut(REDRAW_FIELD); - - game_status = GAME_MODE_MAIN; + SetGameStatus(GAME_MODE_MAIN); DrawMainMenu(); @@ -4466,7 +4452,7 @@ void GameEnd() if ((hi_pos = NewHiScore()) >= 0) { - game_status = GAME_MODE_SCORES; + SetGameStatus(GAME_MODE_SCORES); DrawHallOfFame(hi_pos); @@ -4478,9 +4464,7 @@ void GameEnd() } else { - FadeOut(REDRAW_FIELD); - - game_status = GAME_MODE_MAIN; + SetGameStatus(GAME_MODE_MAIN); if (raise_level) { @@ -4616,11 +4600,6 @@ static void ResetGfxAnimation(int x, int y) GfxFrame[x][y] = 0; ResetGfxFrame(x, y, FALSE); - -#if 1 - if (x == DEBUG_GFXFRAME_X && y == DEBUG_GFXFRAME_Y) - printf(" (RESET_GFX_ANIM)"); -#endif } static void ResetRandomAnimationValue(int x, int y) @@ -4917,167 +4896,101 @@ void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir, boolean no_delay = (tape.warp_forward); int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay); int wait_delay_value = (no_delay ? 0 : frame_delay_value); + int new_scroll_x, new_scroll_y; if (level.lazy_relocation && IN_VIS_FIELD(SCREENX(x), SCREENY(y))) { - RedrawPlayfield(); - } - else if (quick_relocation) - { - if (!IN_VIS_FIELD(SCREENX(x), SCREENY(y)) || center_screen) - { - if (!level.shifted_relocation || center_screen) - { - /* quick relocation (without scrolling), with centering of screen */ - - scroll_x = (x < SBX_Left + MIDPOSX ? SBX_Left : - x > SBX_Right + MIDPOSX ? SBX_Right : - x - MIDPOSX); + /* case 1: quick relocation inside visible screen (without scrolling) */ - scroll_y = (y < SBY_Upper + MIDPOSY ? SBY_Upper : - y > SBY_Lower + MIDPOSY ? SBY_Lower : - y - MIDPOSY); - } - else - { - /* quick relocation (without scrolling), but do not center screen */ - - int center_scroll_x = (old_x < SBX_Left + MIDPOSX ? SBX_Left : - old_x > SBX_Right + MIDPOSX ? SBX_Right : - old_x - MIDPOSX); - - int center_scroll_y = (old_y < SBY_Upper + MIDPOSY ? SBY_Upper : - old_y > SBY_Lower + MIDPOSY ? SBY_Lower : - old_y - MIDPOSY); - - int offset_x = x + (scroll_x - center_scroll_x); - int offset_y = y + (scroll_y - center_scroll_y); + RedrawPlayfield(); - scroll_x = (offset_x < SBX_Left + MIDPOSX ? SBX_Left : - offset_x > SBX_Right + MIDPOSX ? SBX_Right : - offset_x - MIDPOSX); + return; + } - scroll_y = (offset_y < SBY_Upper + MIDPOSY ? SBY_Upper : - offset_y > SBY_Lower + MIDPOSY ? SBY_Lower : - offset_y - MIDPOSY); - } - } - else - { - if (!level.shifted_relocation || center_screen) - { - /* quick relocation (without scrolling), with centering of screen */ + if (!level.shifted_relocation || center_screen) + { + /* relocation _with_ centering of screen */ - scroll_x = (x < SBX_Left + MIDPOSX ? SBX_Left : + new_scroll_x = (x < SBX_Left + MIDPOSX ? SBX_Left : x > SBX_Right + MIDPOSX ? SBX_Right : x - MIDPOSX); - scroll_y = (y < SBY_Upper + MIDPOSY ? SBY_Upper : + new_scroll_y = (y < SBY_Upper + MIDPOSY ? SBY_Upper : y > SBY_Lower + MIDPOSY ? SBY_Lower : y - MIDPOSY); - } - else - { - /* quick relocation (without scrolling), but do not center screen */ + } + else + { + /* relocation _without_ centering of screen */ - int center_scroll_x = (old_x < SBX_Left + MIDPOSX ? SBX_Left : - old_x > SBX_Right + MIDPOSX ? SBX_Right : - old_x - MIDPOSX); + int center_scroll_x = (old_x < SBX_Left + MIDPOSX ? SBX_Left : + old_x > SBX_Right + MIDPOSX ? SBX_Right : + old_x - MIDPOSX); - int center_scroll_y = (old_y < SBY_Upper + MIDPOSY ? SBY_Upper : - old_y > SBY_Lower + MIDPOSY ? SBY_Lower : - old_y - MIDPOSY); + int center_scroll_y = (old_y < SBY_Upper + MIDPOSY ? SBY_Upper : + old_y > SBY_Lower + MIDPOSY ? SBY_Lower : + old_y - MIDPOSY); - int offset_x = x + (scroll_x - center_scroll_x); - int offset_y = y + (scroll_y - center_scroll_y); + int offset_x = x + (scroll_x - center_scroll_x); + int offset_y = y + (scroll_y - center_scroll_y); - scroll_x = (offset_x < SBX_Left + MIDPOSX ? SBX_Left : + new_scroll_x = (offset_x < SBX_Left + MIDPOSX ? SBX_Left : offset_x > SBX_Right + MIDPOSX ? SBX_Right : offset_x - MIDPOSX); - scroll_y = (offset_y < SBY_Upper + MIDPOSY ? SBY_Upper : + new_scroll_y = (offset_y < SBY_Upper + MIDPOSY ? SBY_Upper : offset_y > SBY_Lower + MIDPOSY ? SBY_Lower : offset_y - MIDPOSY); - } - } - - RedrawPlayfield(); } - else - { - int scroll_xx, scroll_yy; - - if (!level.shifted_relocation || center_screen) - { - /* visible relocation (with scrolling), with centering of screen */ - scroll_xx = (x < SBX_Left + MIDPOSX ? SBX_Left : - x > SBX_Right + MIDPOSX ? SBX_Right : - x - MIDPOSX); - - scroll_yy = (y < SBY_Upper + MIDPOSY ? SBY_Upper : - y > SBY_Lower + MIDPOSY ? SBY_Lower : - y - MIDPOSY); - } - else - { - /* visible relocation (with scrolling), but do not center screen */ - - int center_scroll_x = (old_x < SBX_Left + MIDPOSX ? SBX_Left : - old_x > SBX_Right + MIDPOSX ? SBX_Right : - old_x - MIDPOSX); - - int center_scroll_y = (old_y < SBY_Upper + MIDPOSY ? SBY_Upper : - old_y > SBY_Lower + MIDPOSY ? SBY_Lower : - old_y - MIDPOSY); + if (quick_relocation) + { + /* case 2: quick relocation (redraw without visible scrolling) */ - int offset_x = x + (scroll_x - center_scroll_x); - int offset_y = y + (scroll_y - center_scroll_y); + scroll_x = new_scroll_x; + scroll_y = new_scroll_y; - scroll_xx = (offset_x < SBX_Left + MIDPOSX ? SBX_Left : - offset_x > SBX_Right + MIDPOSX ? SBX_Right : - offset_x - MIDPOSX); + RedrawPlayfield(); - scroll_yy = (offset_y < SBY_Upper + MIDPOSY ? SBY_Upper : - offset_y > SBY_Lower + MIDPOSY ? SBY_Lower : - offset_y - MIDPOSY); - } + return; + } - ScrollScreen(NULL, SCROLL_GO_ON); /* scroll last frame to full tile */ + /* case 3: visible relocation (with scrolling to new position) */ - while (scroll_x != scroll_xx || scroll_y != scroll_yy) - { - int dx = 0, dy = 0; - int fx = FX, fy = FY; + ScrollScreen(NULL, SCROLL_GO_ON); /* scroll last frame to full tile */ - dx = (scroll_xx < scroll_x ? +1 : scroll_xx > scroll_x ? -1 : 0); - dy = (scroll_yy < scroll_y ? +1 : scroll_yy > scroll_y ? -1 : 0); + while (scroll_x != new_scroll_x || scroll_y != new_scroll_y) + { + int dx = 0, dy = 0; + int fx = FX, fy = FY; - if (dx == 0 && dy == 0) /* no scrolling needed at all */ - break; + dx = (new_scroll_x < scroll_x ? +1 : new_scroll_x > scroll_x ? -1 : 0); + dy = (new_scroll_y < scroll_y ? +1 : new_scroll_y > scroll_y ? -1 : 0); - scroll_x -= dx; - scroll_y -= dy; + if (dx == 0 && dy == 0) /* no scrolling needed at all */ + break; - fx += dx * TILEX / 2; - fy += dy * TILEY / 2; + scroll_x -= dx; + scroll_y -= dy; - ScrollLevel(dx, dy); - DrawAllPlayers(); + fx += dx * TILEX / 2; + fy += dy * TILEY / 2; - /* scroll in two steps of half tile size to make things smoother */ - BlitBitmap(drawto_field, window, fx, fy, SXSIZE, SYSIZE, SX, SY); - Delay(wait_delay_value); + ScrollLevel(dx, dy); + DrawAllPlayers(); - /* scroll second step to align at full tile size */ - BackToFront(); - Delay(wait_delay_value); - } + /* scroll in two steps of half tile size to make things smoother */ + BlitBitmap(drawto_field, window, fx, fy, SXSIZE, SYSIZE, SX, SY); + Delay(wait_delay_value); - DrawAllPlayers(); + /* scroll second step to align at full tile size */ BackToFront(); Delay(wait_delay_value); } + + DrawAllPlayers(); + BackToFront(); + Delay(wait_delay_value); } void RelocatePlayer(int jx, int jy, int el_player_raw) @@ -9586,6 +9499,8 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) { local_player->gems_still_needed = action_arg_number_new; + game.snapshot.collected_item = TRUE; + game_panel_controls[GAME_PANEL_GEMS].value = local_player->gems_still_needed; @@ -10018,11 +9933,6 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change) ResetGfxAnimation(x, y); ResetRandomAnimationValue(x, y); -#if 0 - if (x == DEBUG_GFXFRAME_X && y == DEBUG_GFXFRAME_Y) - printf(" (RESET X)"); -#endif - TEST_DrawLevelField(x, y); if (GFX_CRUMBLED(new_element)) @@ -10293,10 +10203,9 @@ static void HandleElementChange(int x, int y, int page) be drawn instead of the correct frames 0,1,2,3. This is caused by "GfxFrame[][]" being reset *twice* (in two successive frames) after an element change: First when the change delay ("ChangeDelay[][]") - counter has reached zero after decrementing (see "RESET 1" below), - then a second time in the next frame (after "GfxFrame[][]" was - already incremented) when "ChangeDelay[][]" is reset to the initial - delay value again (see "RESET 2" below). + counter has reached zero after decrementing, then a second time in + the next frame (after "GfxFrame[][]" was already incremented) when + "ChangeDelay[][]" is reset to the initial delay value again. This causes frame 0 to be drawn twice, while the last frame won't be drawn anymore, resulting in the wrong frame sequence 0,0,1,2. @@ -10327,12 +10236,6 @@ static void HandleElementChange(int x, int y, int page) { ResetGfxAnimation(x, y); ResetRandomAnimationValue(x, y); - -#if 1 - if (x == DEBUG_GFXFRAME_X && y == DEBUG_GFXFRAME_Y) - printf(" (RESET 2)"); -#endif - } if (change->pre_change_function) @@ -10387,12 +10290,6 @@ static void HandleElementChange(int x, int y, int page) if (change->post_change_function) change->post_change_function(x, y); } - -#if 1 - if (x == DEBUG_GFXFRAME_X && y == DEBUG_GFXFRAME_Y) - printf(" (RESET 1)"); -#endif - } if (change->has_action && !handle_action_before_change) @@ -11202,8 +11099,11 @@ void GameActions() SendToServer_MovePlayer(summarized_player_action); #endif + // summarize all actions at local players mapped input device position + // (this allows using different input devices in single player mode) if (!options.network && !game.team_mode) - local_player->effective_action = summarized_player_action; + stored_player[map_player_action[local_player->index_nr]].effective_action = + summarized_player_action; if (tape.recording && setup.team_mode && @@ -11239,6 +11139,7 @@ void GameActions() #if USE_NEW_PLAYER_ASSIGNMENTS // !!! also map player actions in single player mode !!! // if (game.team_mode) + if (1) { byte mapped_action[MAX_PLAYERS]; @@ -11469,10 +11370,6 @@ void GameActions_RND() } } -#if 1 - printf("::: %d", GfxFrame[DEBUG_GFXFRAME_X][DEBUG_GFXFRAME_Y]); -#endif - SCAN_PLAYFIELD(x, y) { ChangeCount[x][y] = 0; @@ -11545,10 +11442,6 @@ void GameActions_RND() #endif } -#if 1 - printf(" -> %d", GfxFrame[DEBUG_GFXFRAME_X][DEBUG_GFXFRAME_Y]); -#endif - SCAN_PLAYFIELD(x, y) { element = Feld[x][y]; @@ -11691,10 +11584,6 @@ void GameActions_RND() } } -#if 1 - printf(" -> %d\n", GfxFrame[DEBUG_GFXFRAME_X][DEBUG_GFXFRAME_Y]); -#endif - #if USE_NEW_AMOEBA_CODE /* new experimental amoeba growth stuff */ if (!(FrameCounter % 8)) @@ -13580,6 +13469,8 @@ static int DigField(struct PlayerInfo *player, if (local_player->gems_still_needed < 0) local_player->gems_still_needed = 0; + game.snapshot.collected_item = TRUE; + game_panel_controls[GAME_PANEL_GEMS].value = local_player->gems_still_needed; DisplayGameControlValues(); @@ -13778,9 +13669,16 @@ static int DigField(struct PlayerInfo *player, SCAN_PLAYFIELD(xx, yy) { if (Feld[xx][yy] == EL_SP_DISK_YELLOW) + { Bang(xx, yy); + } else if (Feld[xx][yy] == EL_SP_TERMINAL) + { Feld[xx][yy] = EL_SP_TERMINAL_ACTIVE; + + ResetGfxAnimation(xx, yy); + TEST_DrawLevelField(xx, yy); + } } } else if (IS_BELT_SWITCH(element)) @@ -14572,19 +14470,11 @@ void RequestQuitGameExt(boolean skip_request, boolean quick_quit, char *message) #endif { if (quick_quit) - { FadeSkipNextFadeIn(); - game_status = GAME_MODE_MAIN; - - DrawMainMenu(); - } - else - { - game_status = GAME_MODE_MAIN; + SetGameStatus(GAME_MODE_MAIN); - DrawMainMenu(); - } + DrawMainMenu(); } } else /* continue playing the game */ @@ -14875,9 +14765,12 @@ static boolean SaveEngineSnapshotToListExt(boolean initial_snapshot) (initial_snapshot || (game.snapshot.mode == SNAPSHOT_MODE_EVERY_STEP) || (game.snapshot.mode == SNAPSHOT_MODE_EVERY_MOVE && - game.snapshot.changed_action)); + game.snapshot.changed_action) || + (game.snapshot.mode == SNAPSHOT_MODE_EVERY_COLLECT && + game.snapshot.collected_item)); game.snapshot.changed_action = FALSE; + game.snapshot.collected_item = FALSE; if (game.snapshot.mode == SNAPSHOT_MODE_OFF || tape.quick_resume || @@ -15219,6 +15112,7 @@ void GameRedo(int steps) static void HandleGameButtonsExt(int id, int button) { + static boolean game_undo_executed = FALSE; int steps = BUTTON_STEPSIZE(button); boolean handle_game_buttons = (game_status == GAME_MODE_PLAYING || @@ -15253,6 +15147,9 @@ static void HandleGameButtonsExt(int id, int button) } else TapeTogglePause(TAPE_TOGGLE_MANUAL); + + game_undo_executed = FALSE; + break; case GAME_CTRL_ID_PLAY: @@ -15272,6 +15169,17 @@ static void HandleGameButtonsExt(int id, int button) break; case GAME_CTRL_ID_UNDO: + // Important: When using "save snapshot when collecting an item" mode, + // load last (current) snapshot for first "undo" after pressing "pause" + // (else the last-but-one snapshot would be loaded, because the snapshot + // pointer already points to the last snapshot when pressing "pause", + // which is fine for "every step/move" mode, but not for "every collect") + if (game.snapshot.mode == SNAPSHOT_MODE_EVERY_COLLECT && + !game_undo_executed) + steps--; + + game_undo_executed = TRUE; + GameUndo(steps); break;