X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fanim.c;h=060bb60e8f9e7995644742030e8a410cdd5d7205;hb=fd4817380a5fba31a5745366b2f223f98ac4c169;hp=219c79fd4c97b88ff074a77db45fee1052a25672;hpb=dbba72fb511aee11057e6db5d0e9a4d53c9a0ddc;p=rocksndiamonds.git diff --git a/src/anim.c b/src/anim.c index 219c79fd..060bb60e 100644 --- a/src/anim.c +++ b/src/anim.c @@ -17,6 +17,7 @@ #include "files.h" #include "events.h" #include "screens.h" +#include "tape.h" #define DEBUG_ANIM_DELAY 0 @@ -114,6 +115,8 @@ struct GlobalAnimPartControlInfo struct GraphicInfo graphic_info; struct GraphicInfo control_info; + boolean class_playfield; + int viewport_x; int viewport_y; int viewport_width; @@ -122,6 +125,9 @@ struct GlobalAnimPartControlInfo int x, y; int step_xoffset, step_yoffset; + int tile_x, tile_y; + int tile_xoffset, tile_yoffset; + unsigned int initial_anim_sync_frame; unsigned int anim_random_frame; @@ -369,6 +375,27 @@ static int compareGlobalAnimMainControlInfo(const void *obj1, const void *obj2) return compare_result; } +static boolean isPausedOnPlayfield(struct GlobalAnimPartControlInfo *part) +{ + // only pause playfield animations when playing + if (game_status != GAME_MODE_PLAYING) + return FALSE; + + // do not pause animations when game ended (and engine is running) + if (checkGameEnded()) + return FALSE; + + // only pause animations on playfield + if (!part->class_playfield) + return FALSE; + + // only pause animations when engine is paused or request dialog is open(ing) + if (!tape.pausing && !game.request_active_or_moving) + return FALSE; + + return TRUE; +} + static void InitToonControls(void) { int mode_nr_toons = GAME_MODE_PSEUDO_TOONS; @@ -854,6 +881,10 @@ static void DrawGlobalAnimationsExt(int drawing_target, int drawing_stage) } } + // when restarting global animations, do not redraw them, but stop here + if (drawing_stage == DRAW_GLOBAL_ANIM_STAGE_RESTART) + return; + if (global.anim_status == GAME_MODE_LOADING) return; @@ -914,6 +945,10 @@ static void DrawGlobalAnimationsExt(int drawing_target, int drawing_stage) if (part->drawing_stage != drawing_stage) continue; + // if game is paused, also pause playfield animations + if (isPausedOnPlayfield(part)) + part->initial_anim_sync_frame++; + sync_frame = anim_sync_frame - part->initial_anim_sync_frame; // re-initialize random animation frame after animation delay @@ -967,8 +1002,6 @@ void DrawGlobalAnimations(int drawing_target, int drawing_stage) ResetGlobalAnim_Clicked(); } - DrawEnvelopeRequestToScreen(drawing_target, drawing_stage); - if (gfx.cursor_mode_override != last_cursor_mode_override) SetMouseCursor(gfx.cursor_mode); } @@ -989,6 +1022,8 @@ static boolean SetGlobalAnimPart_Viewport(struct GlobalAnimPartControlInfo *part part->drawing_stage = DRAW_GLOBAL_ANIM_STAGE_1; + part->class_playfield = FALSE; + if (part->control_info.class == get_hash_from_key("window") || part->control_info.class == get_hash_from_key("border")) { @@ -1050,6 +1085,8 @@ static boolean SetGlobalAnimPart_Viewport(struct GlobalAnimPartControlInfo *part viewport_y = REAL_SY; viewport_width = FULL_SXSIZE; viewport_height = FULL_SYSIZE; + + part->class_playfield = TRUE; } if (viewport_x != part->viewport_x || @@ -1210,24 +1247,32 @@ static boolean checkGlobalAnimEvent(int anim_event, int mask) static boolean isClickablePart(struct GlobalAnimPartControlInfo *part, int mask) { struct GraphicInfo *c = &part->control_info; - int num_init_events = GetGlobalAnimEventValueCount(c->init_event); - int num_anim_events = GetGlobalAnimEventValueCount(c->anim_event); int i; - for (i = 0; i < num_init_events; i++) + if (part->init_event_state) { - int init_event = GetGlobalAnimEventValue(c->init_event, i); + int num_init_events = GetGlobalAnimEventValueCount(c->init_event); + + for (i = 0; i < num_init_events; i++) + { + int init_event = GetGlobalAnimEventValue(c->init_event, i); - if (checkGlobalAnimEvent(init_event, mask)) - return TRUE; + if (checkGlobalAnimEvent(init_event, mask)) + return TRUE; + } } - for (i = 0; i < num_anim_events; i++) + if (part->anim_event_state) { - int anim_event = GetGlobalAnimEventValue(c->anim_event, i); + int num_anim_events = GetGlobalAnimEventValueCount(c->anim_event); - if (checkGlobalAnimEvent(anim_event, mask)) - return TRUE; + for (i = 0; i < num_anim_events; i++) + { + int anim_event = GetGlobalAnimEventValue(c->anim_event, i); + + if (checkGlobalAnimEvent(anim_event, mask)) + return TRUE; + } } return FALSE; @@ -1382,18 +1427,28 @@ static void InitGlobalAnim_Triggered_ByCustomElement(int nr, int page, if (!(part2->state & ANIM_STATE_RUNNING)) continue; - if (isClickablePart(part2, mask)) + if (isClickablePart(part2, mask) && !part2->triggered) { struct GraphicInfo *c = &part2->control_info; if (c->position == POS_CE) { - part2->x = c->x + x; - part2->y = c->y + y; + // store CE tile and offset position to handle scrolling + part2->tile_x = x; + part2->tile_y = y; + part2->tile_xoffset = c->x; + part2->tile_yoffset = c->y; + + // restart animation (by using current sync frame) + part2->initial_anim_sync_frame = anim_sync_frame; } part2->triggered = TRUE; + // do not trigger any other animation if CE change event was consumed + if (c->style == STYLE_CONSUME_CE_EVENT) + return; + #if 0 Debug("anim:InitGlobalAnim_Triggered_ByCustomElement", "%d.%d TRIGGERED BY CE %d", anim2_nr, part2_nr, nr + 1); @@ -1442,6 +1497,10 @@ static int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, struct GraphicInfo *c = &part->control_info; boolean viewport_changed = SetGlobalAnimPart_Viewport(part); + // if game is paused, also pause playfield animations + if (isPausedOnPlayfield(part)) + return state; + if (viewport_changed) state |= ANIM_STATE_RESTART; @@ -1575,12 +1634,7 @@ static int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, part->init_event_state) { if (part->initial_anim_sync_frame > 0) - { - if (part->init_delay_counter > 0) - part->initial_anim_sync_frame -= part->init_delay_counter - 1; - else - part->initial_anim_sync_frame = anim_sync_frame; - } + part->initial_anim_sync_frame = anim_sync_frame; part->init_delay_counter = 1; part->init_event_state = FALSE; @@ -1609,9 +1663,13 @@ static int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, HandleGlobalAnimDelay(part, ANIM_DELAY_INIT, "START [INIT_DELAY]"); HandleGlobalAnimEvent(part, ANIM_EVENT_START, "START [ANIM]"); - } - return ANIM_STATE_WAITING; + // continue with state ANIM_STATE_RUNNING (set below) + } + else + { + return ANIM_STATE_WAITING; + } } if (part->init_event_state) @@ -1705,8 +1763,32 @@ static int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, } #endif - part->x += part->step_xoffset; - part->y += part->step_yoffset; + if (c->position == POS_CE) + { + // calculate playfield position (with scrolling) for related CE tile + // (do not use FX/FY, which are incorrect during envelope requests) + int FX0 = 2 * TILEX_VAR; // same as FX during DRAW_TO_FIELDBUFFER + int FY0 = 2 * TILEY_VAR; // same as FY during DRAW_TO_FIELDBUFFER + int fx = getFieldbufferOffsetX_RND(ScreenMovDir, ScreenGfxPos); + int fy = getFieldbufferOffsetY_RND(ScreenMovDir, ScreenGfxPos); + int sx = FX0 + SCREENX(part->tile_x) * TILEX_VAR; + int sy = FY0 + SCREENY(part->tile_y) * TILEY_VAR; + int cx = SX - REAL_SX; + int cy = SY - REAL_SY; + int x = sx - fx + cx; + int y = sy - fy + cy; + + part->tile_xoffset += part->step_xoffset; + part->tile_yoffset += part->step_yoffset; + + part->x = x + part->tile_xoffset; + part->y = y + part->tile_yoffset; + } + else + { + part->x += part->step_xoffset; + part->y += part->step_yoffset; + } anim->last_x = part->x; anim->last_y = part->y; @@ -2116,11 +2198,16 @@ void RestartGlobalAnimsByStatus(int status) global.anim_status = status; // force restarting global animations by changed global animation status - SDLRedrawWindow(); + DrawGlobalAnimationsExt(DRAW_TO_SCREEN, DRAW_GLOBAL_ANIM_STAGE_RESTART); global.anim_status = anim_status_last; } +void SetAnimStatusBeforeFading(int status) +{ + anim_status_last_before_fading = status; +} + boolean HandleGlobalAnimClicks(int mx, int my, int button, boolean force_click) { static boolean click_consumed = FALSE;