X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fgame.c;h=41add9e6745afd10fb6ad28fafe4e438d6aa7e9e;hp=1f0270d9051fbd850bbae2b27fd1deb94b8b82d8;hb=1afe0b4fb9e16c78f2bb810c1225098f5d77e2d3;hpb=cc1d6b89872ea3d6ae3e53023653ab86dd76c2ea diff --git a/src/game.c b/src/game.c index 1f0270d9..41add9e6 100644 --- a/src/game.c +++ b/src/game.c @@ -1949,7 +1949,7 @@ static void InitField(int x, int y, boolean init_game) CheckTriggeredElementChange(x, y, element, CE_CREATION_OF_X); } -static inline void InitField_WithBug1(int x, int y, boolean init_game) +inline static void InitField_WithBug1(int x, int y, boolean init_game) { InitField(x, y, init_game); @@ -1959,7 +1959,7 @@ static inline void InitField_WithBug1(int x, int y, boolean init_game) InitMovDir(x, y); } -static inline void InitField_WithBug2(int x, int y, boolean init_game) +inline static void InitField_WithBug2(int x, int y, boolean init_game) { int old_element = Feld[x][y]; @@ -3091,40 +3091,30 @@ void InitGame() int initial_move_dir = MV_DOWN; int i, j, x, y; - game_status = GAME_MODE_PLAYING; + // required here to update video display before fading (FIX THIS) + DrawMaskedBorder(REDRAW_DOOR_2); - StopAnimation(); + game_status = GAME_MODE_PLAYING; if (!game.restart_level) CloseDoor(DOOR_CLOSE_1); -#if 1 /* needed if different viewport properties defined for playing */ ChangeViewportPropertiesIfNeeded(); -#endif if (level_editor_test_game) FadeSkipNextFadeIn(); else FadeSetEnterScreen(); - if (CheckIfRedrawGlobalBorderIsNeeded()) + if (CheckIfGlobalBorderHasChanged()) fade_mask = REDRAW_ALL; -#if 0 - printf("::: %d\n", (fade_mask == REDRAW_ALL ? 1 : 0)); -#endif - FadeOut(fade_mask); -#if 0 - /* needed if different viewport properties defined for playing */ - ChangeViewportPropertiesIfNeeded(); -#endif + OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW); -#if 1 ClearField(); -#endif DrawCompleteVideoDisplay(); @@ -3938,6 +3928,8 @@ void InitGame() BlitScreenToBitmap(backbuffer); /* !!! FIX THIS (END) !!! */ + DrawMaskedBorder(fade_mask); + FadeIn(fade_mask); #if 1 @@ -3967,9 +3959,14 @@ void InitGame() { UnmapGameButtons(); UnmapTapeButtons(); + + FreeGameButtons(); + CreateGameButtons(); + game_gadget[SOUND_CTRL_ID_MUSIC]->checked = setup.sound_music; game_gadget[SOUND_CTRL_ID_LOOPS]->checked = setup.sound_loops; game_gadget[SOUND_CTRL_ID_SIMPLE]->checked = setup.sound_simple; + MapGameButtons(); MapTapeButtons(); @@ -4424,7 +4421,7 @@ void GameEnd() { game_status = GAME_MODE_MAIN; - DrawAndFadeInMainMenu(REDRAW_FIELD); + DrawMainMenu(); return; } @@ -4435,7 +4432,7 @@ void GameEnd() game_status = GAME_MODE_MAIN; - DrawAndFadeInMainMenu(REDRAW_FIELD); + DrawMainMenu(); return; } @@ -4454,9 +4451,6 @@ void GameEnd() { game_status = GAME_MODE_SCORES; - /* needed if different viewport properties defined for scores */ - ChangeViewportPropertiesIfNeeded(); - DrawHallOfFame(hi_pos); if (raise_level) @@ -4477,7 +4471,7 @@ void GameEnd() TapeErase(); } - DrawAndFadeInMainMenu(REDRAW_FIELD); + DrawMainMenu(); } } @@ -4902,7 +4896,11 @@ void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir, int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay); int wait_delay_value = (no_delay ? 0 : frame_delay_value); - if (quick_relocation) + 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) { @@ -4981,7 +4979,7 @@ void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir, } } - RedrawPlayfield(TRUE, 0,0,0,0); + RedrawPlayfield(); } else { @@ -5023,7 +5021,6 @@ void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir, offset_y - MIDPOSY); } - ScrollScreen(NULL, SCROLL_GO_ON); /* scroll last frame to full tile */ while (scroll_x != scroll_xx || scroll_y != scroll_yy) @@ -10255,9 +10252,50 @@ static void HandleElementChange(int x, int y, int page) { /* !!! not clear why graphic animation should be reset at all here !!! */ /* !!! UPDATE: but is needed for correct Snake Bite tail animation !!! */ + /* !!! SOLUTION: do not reset if graphics engine set to 4 or above !!! */ + + /* + GRAPHICAL BUG ADDRESSED BY CHECKING GRAPHICS ENGINE VERSION: + + When using an animation frame delay of 1 (this only happens with + "sp_zonk.moving.left/right" in the classic graphics), the default + (non-moving) animation shows wrong animation frames (while the + moving animation, like "sp_zonk.moving.left/right", is correct, + so this graphical bug never shows up with the classic graphics). + For an animation with 4 frames, this causes wrong frames 0,0,1,2 + 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, 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. + + As some animations may already be cleverly designed around this bug + (at least the "Snake Bite" snake tail animation does this), it cannot + simply be fixed here without breaking such existing animations. + Unfortunately, it cannot easily be detected if a graphics set was + designed "before" or "after" the bug was fixed. As a workaround, + a new graphics set option "game.graphics_engine_version" was added + to be able to specify the game's major release version for which the + graphics set was designed, which can then be used to decide if the + bugfix should be used (version 4 and above) or not (version 3 or + below, or if no version was specified at all, as with old sets). + + (The wrong/fixed animation frames can be tested with the test level set + "test_gfxframe" and level "000", which contains a specially prepared + custom element at level position (x/y) == (11/9) which uses the zonk + animation mentioned above. Using "game.graphics_engine_version: 4" + fixes the wrong animation frames, showing the correct frames 0,1,2,3. + This can also be seen from the debug output for this test element.) + */ + /* when a custom element is about to change (for example by change delay), do not reset graphic animation when the custom element is moving */ - if (!IS_MOVING(x, y)) + if (game.graphics_engine_version < 4 && + !IS_MOVING(x, y)) { ResetGfxAnimation(x, y); ResetRandomAnimationValue(x, y); @@ -10988,23 +11026,6 @@ void GameActions() byte tape_action[MAX_PLAYERS]; int i; - for (i = 0; i < MAX_PLAYERS; i++) - { - struct PlayerInfo *player = &stored_player[i]; - - // allow engine snapshot if movement attempt was stopped - if ((game.snapshot.last_action[i] & KEY_MOTION) != 0 && - (player->action & KEY_MOTION) == 0) - game.snapshot.changed_action = TRUE; - - // allow engine snapshot in case of snapping/dropping attempt - if ((game.snapshot.last_action[i] & KEY_BUTTON) == 0 && - (player->action & KEY_BUTTON) != 0) - game.snapshot.changed_action = TRUE; - - game.snapshot.last_action[i] = player->action; - } - /* detect endless loops, caused by custom element programming */ if (recursion_loop_detected && recursion_loop_depth == 0) { @@ -11211,6 +11232,21 @@ void GameActions() #endif #endif + for (i = 0; i < MAX_PLAYERS; i++) + { + // allow engine snapshot in case of changed movement attempt + if ((game.snapshot.last_action[i] & KEY_MOTION) != + (stored_player[i].effective_action & KEY_MOTION)) + game.snapshot.changed_action = TRUE; + + // allow engine snapshot in case of snapping/dropping attempt + if ((game.snapshot.last_action[i] & KEY_BUTTON) == 0 && + (stored_player[i].effective_action & KEY_BUTTON) != 0) + game.snapshot.changed_action = TRUE; + + game.snapshot.last_action[i] = stored_player[i].effective_action; + } + if (level.game_engine_type == GAME_ENGINE_TYPE_EM) { GameActions_EM_Main(); @@ -14489,13 +14525,13 @@ void RequestQuitGameExt(boolean skip_request, boolean quick_quit, char *message) game_status = GAME_MODE_MAIN; - DrawAndFadeInMainMenu(REDRAW_FIELD); + DrawMainMenu(); } else { game_status = GAME_MODE_MAIN; - DrawAndFadeInMainMenu(REDRAW_FIELD); + DrawMainMenu(); } } }