X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fanim.c;h=fa124cb6ab692e957125a060b0d8ffe0a013ef96;hp=2ef7872558b841ff080a4ee6902b6e2b13d54096;hb=8b3a64c55ed158de2659a0479a232ee4d335ce48;hpb=71c4b8d626b4a731a72840facb6bd548c7e33da9 diff --git a/src/anim.c b/src/anim.c index 2ef78725..fa124cb6 100644 --- a/src/anim.c +++ b/src/anim.c @@ -29,20 +29,25 @@ #define ANIM_CLASS_BIT_TITLE_INITIAL 0 #define ANIM_CLASS_BIT_TITLE 1 #define ANIM_CLASS_BIT_MAIN 2 -#define ANIM_CLASS_BIT_SUBMENU 3 -#define ANIM_CLASS_BIT_MENU 4 -#define ANIM_CLASS_BIT_TOONS 5 +#define ANIM_CLASS_BIT_SCORES 3 +#define ANIM_CLASS_BIT_SUBMENU 4 +#define ANIM_CLASS_BIT_MENU 5 +#define ANIM_CLASS_BIT_TOONS 6 -#define NUM_ANIM_CLASSES 6 +#define NUM_ANIM_CLASSES 7 #define ANIM_CLASS_NONE 0 #define ANIM_CLASS_TITLE_INITIAL (1 << ANIM_CLASS_BIT_TITLE_INITIAL) #define ANIM_CLASS_TITLE (1 << ANIM_CLASS_BIT_TITLE) #define ANIM_CLASS_MAIN (1 << ANIM_CLASS_BIT_MAIN) +#define ANIM_CLASS_SCORES (1 << ANIM_CLASS_BIT_SCORES) #define ANIM_CLASS_SUBMENU (1 << ANIM_CLASS_BIT_SUBMENU) #define ANIM_CLASS_MENU (1 << ANIM_CLASS_BIT_MENU) #define ANIM_CLASS_TOONS (1 << ANIM_CLASS_BIT_TOONS) +#define ANIM_CLASS_TOONS_SCORES (ANIM_CLASS_TOONS | \ + ANIM_CLASS_SCORES) + #define ANIM_CLASS_TOONS_MENU_MAIN (ANIM_CLASS_TOONS | \ ANIM_CLASS_MENU | \ ANIM_CLASS_MAIN) @@ -66,10 +71,15 @@ struct GlobalAnimPartControlInfo { + int old_nr; // position before mapping animation parts linearly + int old_anim_nr; // position before mapping animations linearly + int nr; int anim_nr; int mode_nr; + boolean is_base; // animation part is base/main/default animation part + int sound; int music; int graphic; @@ -114,11 +124,14 @@ struct GlobalAnimMainControlInfo struct GraphicInfo control_info; - int num_parts; + int num_parts; // number of animation parts, but without base part + int num_parts_all; // number of animation parts, including base part int part_counter; int active_part_nr; - boolean has_base; + boolean has_base; // animation has base/main/default animation part + + int last_x, last_y; int init_delay_counter; @@ -157,7 +170,8 @@ struct GameModeAnimClass { GAME_MODE_SETUP, ANIM_CLASS_TOONS_MENU_SUBMENU }, { GAME_MODE_PSEUDO_MAINONLY, ANIM_CLASS_TOONS_MENU_MAIN }, { GAME_MODE_PSEUDO_TYPENAME, ANIM_CLASS_TOONS_MENU_MAIN }, - { GAME_MODE_SCORES, ANIM_CLASS_TOONS }, + { GAME_MODE_PSEUDO_SCORESOLD, ANIM_CLASS_TOONS_SCORES }, + { GAME_MODE_PSEUDO_SCORESNEW, ANIM_CLASS_TOONS_SCORES }, { -1, -1 } }; @@ -171,6 +185,7 @@ struct AnimClassGameMode { ANIM_CLASS_BIT_TITLE_INITIAL, GAME_MODE_TITLE_INITIAL }, { ANIM_CLASS_BIT_TITLE, GAME_MODE_TITLE }, { ANIM_CLASS_BIT_MAIN, GAME_MODE_MAIN }, + { ANIM_CLASS_BIT_SCORES, GAME_MODE_SCORES }, { ANIM_CLASS_BIT_SUBMENU, GAME_MODE_PSEUDO_SUBMENU }, { ANIM_CLASS_BIT_MENU, GAME_MODE_PSEUDO_MENU }, { ANIM_CLASS_BIT_TOONS, GAME_MODE_PSEUDO_TOONS }, @@ -191,6 +206,7 @@ static unsigned int anim_sync_frame = 0; static int game_mode_anim_classes[NUM_GAME_MODES]; static int anim_class_game_modes[NUM_ANIM_CLASSES]; +static int anim_status_last_before_fading = GAME_MODE_DEFAULT; static int anim_status_last = GAME_MODE_DEFAULT; static int anim_classes_last = ANIM_CLASS_NONE; @@ -328,11 +344,15 @@ static void InitToonControls() anim->control_info = graphic_info[control]; anim->num_parts = 0; + anim->num_parts_all = 0; anim->part_counter = 0; anim->active_part_nr = 0; anim->has_base = FALSE; + anim->last_x = POS_OFFSCREEN; + anim->last_y = POS_OFFSCREEN; + anim->init_delay_counter = 0; anim->state = ANIM_STATE_INACTIVE; @@ -350,9 +370,13 @@ static void InitToonControls() part->nr = part_nr; part->anim_nr = anim_nr; part->mode_nr = mode_nr; + + part->is_base = FALSE; + part->sound = sound; part->music = music; part->graphic = graphic; + part->graphic_info = graphic_info[graphic]; part->control_info = graphic_info[control]; @@ -373,6 +397,8 @@ static void InitToonControls() part->last_anim_status = -1; anim->num_parts++; + anim->num_parts_all++; + part_nr++; } @@ -414,11 +440,15 @@ void InitGlobalAnimControls() anim->control_info = graphic_info[control]; anim->num_parts = 0; + anim->num_parts_all = 0; anim->part_counter = 0; anim->active_part_nr = 0; anim->has_base = FALSE; + anim->last_x = POS_OFFSCREEN; + anim->last_y = POS_OFFSCREEN; + anim->init_delay_counter = 0; anim->state = ANIM_STATE_INACTIVE; @@ -448,12 +478,17 @@ void InitGlobalAnimControls() m, a, p, mode_nr, anim_nr, part_nr, sound); #endif + part->old_nr = p; + part->old_anim_nr = a; + part->nr = part_nr; part->anim_nr = anim_nr; part->mode_nr = mode_nr; + part->sound = sound; part->music = music; part->graphic = graphic; + part->graphic_info = graphic_info[graphic]; part->control_info = graphic_info[control]; @@ -465,13 +500,19 @@ void InitGlobalAnimControls() part->state = ANIM_STATE_INACTIVE; part->last_anim_status = -1; + anim->num_parts_all++; + if (p < GLOBAL_ANIM_ID_PART_BASE) { + part->is_base = FALSE; + anim->num_parts++; part_nr++; } else { + part->is_base = TRUE; + anim->base = *part; anim->has_base = TRUE; } @@ -520,6 +561,7 @@ void InitGlobalAnimControls() anim_class_game_modes[anim_class_game_modes_list[i].class_bit] = anim_class_game_modes_list[i].game_mode; + anim_status_last_before_fading = GAME_MODE_LOADING; anim_status_last = GAME_MODE_LOADING; anim_classes_last = ANIM_CLASS_NONE; } @@ -558,15 +600,23 @@ void DrawGlobalAnimationsExt(int drawing_target, int drawing_stage) if (drawing_target == DRAW_TO_FADE_TARGET) after_fading = TRUE; + // special case: changing from/to this screen is done without fading + if (global.anim_status == GAME_MODE_PSEUDO_TYPENAME || + anim_status_last == GAME_MODE_PSEUDO_TYPENAME) + after_fading = TRUE; + // ---------- part 1 ------------------------------------------------------ // start or stop global animations by change of game mode // (special handling of animations for "current screen" and "all screens") - // stop animations for last screen - game_mode_anim_action[anim_status_last] = ANIM_STOP; + if (global.anim_status_next != anim_status_last_before_fading) + { + // stop animations for last screen before fading to new screen + game_mode_anim_action[anim_status_last] = ANIM_STOP; - // start animations for current screen - game_mode_anim_action[global.anim_status] = ANIM_START; + // start animations for current screen after fading to new screen + game_mode_anim_action[global.anim_status] = ANIM_START; + } // start animations for all screens after loading new artwork set if (anim_status_last == GAME_MODE_LOADING) @@ -595,7 +645,10 @@ void DrawGlobalAnimationsExt(int drawing_target, int drawing_stage) if (drawing_target == DRAW_TO_SCREEN) { if (after_fading) + { anim_classes_last = anim_classes_next; + anim_status_last_before_fading = global.anim_status; + } anim_status_last = global.anim_status; @@ -673,6 +726,10 @@ void DrawGlobalAnimationsExt(int drawing_target, int drawing_stage) int cut_y = 0; int sync_frame; int frame; + void (*blit_bitmap)(Bitmap *, Bitmap *, int, int, int, int, int, int) = + (g->draw_masked ? BlitBitmapMasked : BlitBitmap); + void (*blit_screen)(Bitmap *, int, int, int, int, int, int) = + (g->draw_masked ? BlitToScreenMasked : BlitToScreen); if (!(part->state & ANIM_STATE_RUNNING)) continue; @@ -716,11 +773,11 @@ void DrawGlobalAnimationsExt(int drawing_target, int drawing_stage) src_y += cut_y; if (drawing_target == DRAW_TO_SCREEN) - BlitToScreenMasked(src_bitmap, src_x, src_y, width, height, - dst_x, dst_y); + blit_screen(src_bitmap, src_x, src_y, width, height, + dst_x, dst_y); else - BlitBitmapMasked(src_bitmap, fade_bitmap, src_x, src_y, width, height, - dst_x, dst_y); + blit_bitmap(src_bitmap, fade_bitmap, src_x, src_y, width, height, + dst_x, dst_y); } } } @@ -897,12 +954,23 @@ static void StopGlobalAnimSoundAndMusic(struct GlobalAnimPartControlInfo *part) StopGlobalAnimMusic(part); } -static boolean isClickablePart(struct GlobalAnimPartControlInfo *part) +static boolean isClickablePart(struct GlobalAnimPartControlInfo *part, int mask) { struct GraphicInfo *c = &part->control_info; - - return (c->init_event & ANIM_EVENT_CLICK || - c->anim_event & ANIM_EVENT_CLICK); + int trigger_mask = ANIM_EVENT_ANIM_MASK | ANIM_EVENT_PART_MASK; + int mask_anim_only = mask & ANIM_EVENT_ANIM_MASK; + + if (mask & ANIM_EVENT_ANY) + return (c->init_event & ANIM_EVENT_ANY || + c->anim_event & ANIM_EVENT_ANY); + else if (mask & ANIM_EVENT_SELF) + return (c->init_event & ANIM_EVENT_SELF || + c->anim_event & ANIM_EVENT_SELF); + else + return ((c->init_event & trigger_mask) == mask || + (c->anim_event & trigger_mask) == mask || + (c->init_event & trigger_mask) == mask_anim_only || + (c->anim_event & trigger_mask) == mask_anim_only); } static boolean isClickedPart(struct GlobalAnimPartControlInfo *part, @@ -937,6 +1005,8 @@ static boolean isClickedPart(struct GlobalAnimPartControlInfo *part, int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state) { + struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[part->mode_nr]; + struct GlobalAnimMainControlInfo *anim = &ctrl->anim[part->anim_nr]; struct GraphicInfo *g = &part->graphic_info; struct GraphicInfo *c = &part->control_info; boolean viewport_changed = SetGlobalAnimPart_Viewport(part); @@ -1033,6 +1103,14 @@ int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state) if (c->y != ARG_UNDEFINED_VALUE) part->y = c->y; + if (c->position == POS_LAST && + anim->last_x > -g->width && anim->last_x < part->viewport_width && + anim->last_y > -g->height && anim->last_y < part->viewport_height) + { + part->x = anim->last_x; + part->y = anim->last_y; + } + if (c->step_xoffset != ARG_UNDEFINED_VALUE) part->step_xoffset = c->step_xoffset; if (c->step_yoffset != ARG_UNDEFINED_VALUE) @@ -1043,8 +1121,6 @@ int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state) PlayGlobalAnimSoundAndMusic(part); } - part->clickable = isClickablePart(part); - if (part->clicked && part->init_event_state != ANIM_EVENT_NONE) { @@ -1083,6 +1159,9 @@ int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state) if (part->init_event_state != ANIM_EVENT_NONE) return ANIM_STATE_WAITING; + // animation part is now running/visible and therefore clickable + part->clickable = TRUE; + // check if moving animation has left the visible screen area if ((part->x <= -g->width && part->step_xoffset <= 0) || (part->x >= part->viewport_width && part->step_xoffset >= 0) || @@ -1159,6 +1238,9 @@ int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state) part->x += part->step_xoffset; part->y += part->step_yoffset; + anim->last_x = part->x; + anim->last_y = part->y; + return ANIM_STATE_RUNNING; } @@ -1166,7 +1248,9 @@ void HandleGlobalAnim_Main(struct GlobalAnimMainControlInfo *anim, int action) { struct GlobalAnimPartControlInfo *part; struct GraphicInfo *c = &anim->control_info; + int num_parts = anim->num_parts + (anim->has_base ? 1 : 0); int state, active_part_nr; + int i; #if 0 printf("::: HandleGlobalAnim_Main: %d, %d => %d\n", @@ -1207,13 +1291,8 @@ void HandleGlobalAnim_Main(struct GlobalAnimMainControlInfo *anim, int action) case ANIM_STOP: anim->state = ANIM_STATE_INACTIVE; - { - int num_parts = anim->num_parts + (anim->has_base ? 1 : 0); - int i; - - for (i = 0; i < num_parts; i++) - StopGlobalAnimSoundAndMusic(&anim->part[i]); - } + for (i = 0; i < num_parts; i++) + StopGlobalAnimSoundAndMusic(&anim->part[i]); return; @@ -1223,9 +1302,6 @@ void HandleGlobalAnim_Main(struct GlobalAnimMainControlInfo *anim, int action) if (c->anim_mode & ANIM_ALL || anim->num_parts == 0) { - int num_parts = anim->num_parts + (anim->has_base ? 1 : 0); - int i; - #if 0 printf("::: HandleGlobalAnim_Main: %d, %d => %d\n", anim->mode_nr, anim->nr, num_parts); @@ -1366,12 +1442,12 @@ static void InitGlobalAnim_Clickable() struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr]; int anim_nr; - for (anim_nr = 0; anim_nr < NUM_GLOBAL_ANIMS_AND_TOONS; anim_nr++) + for (anim_nr = 0; anim_nr < ctrl->num_anims; anim_nr++) { struct GlobalAnimMainControlInfo *anim = &ctrl->anim[anim_nr]; int part_nr; - for (part_nr = 0; part_nr < NUM_GLOBAL_ANIM_PARTS_AND_TOONS; part_nr++) + for (part_nr = 0; part_nr < anim->num_parts_all; part_nr++) { struct GlobalAnimPartControlInfo *part = &anim->part[part_nr]; @@ -1383,32 +1459,98 @@ static void InitGlobalAnim_Clickable() static boolean InitGlobalAnim_Clicked(int mx, int my, boolean clicked) { + boolean anything_clicked = FALSE; boolean any_part_clicked = FALSE; int mode_nr; - for (mode_nr = 0; mode_nr < NUM_GAME_MODES; mode_nr++) + // check game modes in reverse draw order (to stop when clicked) + for (mode_nr = NUM_GAME_MODES - 1; mode_nr >= 0; mode_nr--) { struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr]; int anim_nr; - for (anim_nr = 0; anim_nr < NUM_GLOBAL_ANIMS_AND_TOONS; anim_nr++) + // check animations in reverse draw order (to stop when clicked) + for (anim_nr = ctrl->num_anims - 1; anim_nr >= 0; anim_nr--) { struct GlobalAnimMainControlInfo *anim = &ctrl->anim[anim_nr]; int part_nr; - for (part_nr = 0; part_nr < NUM_GLOBAL_ANIM_PARTS_AND_TOONS; part_nr++) + // check animation parts in reverse draw order (to stop when clicked) + for (part_nr = anim->num_parts_all - 1; part_nr >= 0; part_nr--) { struct GlobalAnimPartControlInfo *part = &anim->part[part_nr]; - part->clicked = FALSE; + if (!clicked) + { + part->clicked = FALSE; - if (part->clickable && isClickedPart(part, mx, my, clicked)) - any_part_clicked = part->clicked = TRUE; + continue; + } + + if (!part->clickable) + continue; + + // always handle "any" click events (clicking anywhere on screen) ... + if (isClickablePart(part, ANIM_EVENT_ANY)) + anything_clicked = part->clicked = TRUE; + + // ... but only handle the first (topmost) clickable animation + if (any_part_clicked) + continue; + + if (isClickedPart(part, mx, my, clicked)) + { +#if 0 + printf("::: %d.%d CLICKED\n", anim_nr, part_nr); +#endif + + any_part_clicked = TRUE; + + if (isClickablePart(part, ANIM_EVENT_SELF)) + anything_clicked = part->clicked = TRUE; + + // check if this click is defined to trigger other animations + int gic_anim_nr = part->old_anim_nr + 1; // X as in "anim_X" + int gic_part_nr = part->old_nr + 1; // Y as in "part_Y" + int mask = gic_anim_nr << ANIM_EVENT_ANIM_BIT; + + if (!part->is_base) + mask |= gic_part_nr << ANIM_EVENT_PART_BIT; + + int anim2_nr; + + for (anim2_nr = 0; anim2_nr < ctrl->num_anims; anim2_nr++) + { + struct GlobalAnimMainControlInfo *anim2 = &ctrl->anim[anim2_nr]; + int part2_nr; + + for (part2_nr = 0; part2_nr < anim2->num_parts_all; part2_nr++) + { + struct GlobalAnimPartControlInfo *part2 = &anim2->part[part2_nr]; + + if (isClickablePart(part2, mask)) + anything_clicked = part2->clicked = TRUE; + +#if 0 + struct GraphicInfo *c = &part2->control_info; + + printf("::: - %d.%d: 0x%08x, 0x%08x [0x%08x]", + anim2_nr, part2_nr, c->init_event, c->anim_event, mask); + + if (isClickablePart(part2, mask)) + printf(" <--- TRIGGERED BY %d.%d", + anim_nr, part_nr); + + printf("\n"); +#endif + } + } + } } } } - return any_part_clicked; + return anything_clicked; } static void ResetGlobalAnim_Clickable()