1 // ============================================================================
2 // Rocks'n'Diamonds - McDuffin Strikes Back!
3 // ----------------------------------------------------------------------------
4 // (c) 1995-2014 by Artsoft Entertainment
7 // http://www.artsoft.org/
8 // ----------------------------------------------------------------------------
10 // ============================================================================
17 /* values for global toon animation definition */
18 #define NUM_GLOBAL_TOON_ANIMS 1
19 #define NUM_GLOBAL_TOON_PARTS MAX_NUM_TOONS
21 /* values for global animation definition (including toons) */
22 #define NUM_GLOBAL_ANIMS_AND_TOONS (NUM_GLOBAL_ANIMS + \
23 NUM_GLOBAL_TOON_ANIMS)
24 #define NUM_GLOBAL_ANIM_PARTS_AND_TOONS MAX(NUM_GLOBAL_ANIM_PARTS_ALL, \
25 NUM_GLOBAL_TOON_PARTS)
27 #define ANIM_CLASS_BIT_TITLE_INITIAL 0
28 #define ANIM_CLASS_BIT_TITLE 1
29 #define ANIM_CLASS_BIT_MAIN 2
30 #define ANIM_CLASS_BIT_SUBMENU 3
31 #define ANIM_CLASS_BIT_MENU 4
32 #define ANIM_CLASS_BIT_TOONS 5
34 #define NUM_ANIM_CLASSES 6
36 #define ANIM_CLASS_NONE 0
37 #define ANIM_CLASS_TITLE_INITIAL (1 << ANIM_CLASS_BIT_TITLE_INITIAL)
38 #define ANIM_CLASS_TITLE (1 << ANIM_CLASS_BIT_TITLE)
39 #define ANIM_CLASS_MAIN (1 << ANIM_CLASS_BIT_MAIN)
40 #define ANIM_CLASS_SUBMENU (1 << ANIM_CLASS_BIT_SUBMENU)
41 #define ANIM_CLASS_MENU (1 << ANIM_CLASS_BIT_MENU)
42 #define ANIM_CLASS_TOONS (1 << ANIM_CLASS_BIT_TOONS)
44 #define ANIM_CLASS_TOONS_MENU_MAIN (ANIM_CLASS_TOONS | \
48 #define ANIM_CLASS_TOONS_MENU_SUBMENU (ANIM_CLASS_TOONS | \
52 struct GlobalAnimPartControlInfo
61 struct GraphicInfo graphic_info;
62 struct GraphicInfo control_info;
70 int step_xoffset, step_yoffset;
72 unsigned int initial_anim_sync_frame;
73 unsigned int step_delay, step_delay_value;
75 int init_delay_counter;
76 int anim_delay_counter;
77 int post_delay_counter;
85 struct GlobalAnimMainControlInfo
87 struct GlobalAnimPartControlInfo base;
88 struct GlobalAnimPartControlInfo part[NUM_GLOBAL_ANIM_PARTS_AND_TOONS];
93 struct GraphicInfo control_info;
101 int init_delay_counter;
105 int last_state, last_active_part_nr;
108 struct GlobalAnimControlInfo
110 struct GlobalAnimMainControlInfo anim[NUM_GLOBAL_ANIMS_AND_TOONS];
116 struct GameModeAnimClass
120 } game_mode_anim_classes_list[] =
122 { GAME_MODE_TITLE_INITIAL_1, ANIM_CLASS_TITLE_INITIAL },
123 { GAME_MODE_TITLE_INITIAL_2, ANIM_CLASS_TITLE_INITIAL },
124 { GAME_MODE_TITLE_INITIAL_3, ANIM_CLASS_TITLE_INITIAL },
125 { GAME_MODE_TITLE_INITIAL_4, ANIM_CLASS_TITLE_INITIAL },
126 { GAME_MODE_TITLE_INITIAL_5, ANIM_CLASS_TITLE_INITIAL },
127 { GAME_MODE_TITLE_1, ANIM_CLASS_TITLE },
128 { GAME_MODE_TITLE_2, ANIM_CLASS_TITLE },
129 { GAME_MODE_TITLE_3, ANIM_CLASS_TITLE },
130 { GAME_MODE_TITLE_4, ANIM_CLASS_TITLE },
131 { GAME_MODE_TITLE_5, ANIM_CLASS_TITLE },
132 { GAME_MODE_LEVELS, ANIM_CLASS_TOONS_MENU_SUBMENU },
133 { GAME_MODE_LEVELNR, ANIM_CLASS_TOONS_MENU_SUBMENU },
134 { GAME_MODE_INFO, ANIM_CLASS_TOONS_MENU_SUBMENU },
135 { GAME_MODE_SETUP, ANIM_CLASS_TOONS_MENU_SUBMENU },
136 { GAME_MODE_PSEUDO_MAINONLY, ANIM_CLASS_TOONS_MENU_MAIN },
137 { GAME_MODE_PSEUDO_TYPENAME, ANIM_CLASS_TOONS_MENU_MAIN },
138 { GAME_MODE_SCORES, ANIM_CLASS_TOONS },
143 struct AnimClassGameMode
147 } anim_class_game_modes_list[] =
149 { ANIM_CLASS_BIT_TITLE_INITIAL, GAME_MODE_TITLE_INITIAL },
150 { ANIM_CLASS_BIT_TITLE, GAME_MODE_TITLE },
151 { ANIM_CLASS_BIT_MAIN, GAME_MODE_MAIN },
152 { ANIM_CLASS_BIT_SUBMENU, GAME_MODE_PSEUDO_SUBMENU },
153 { ANIM_CLASS_BIT_MENU, GAME_MODE_PSEUDO_MENU },
154 { ANIM_CLASS_BIT_TOONS, GAME_MODE_PSEUDO_TOONS },
159 /* forward declaration for internal use */
160 static void HandleGlobalAnim(int, int);
161 static void DoAnimationExt(void);
163 static struct GlobalAnimControlInfo global_anim_ctrl[NUM_GAME_MODES];
164 static struct ToonInfo toons[MAX_NUM_TOONS];
166 static unsigned int anim_sync_frame = 0;
167 static unsigned int anim_sync_frame_delay = 0;
168 static unsigned int anim_sync_frame_delay_value = GAME_FRAME_DELAY;
170 static int game_mode_anim_classes[NUM_GAME_MODES];
171 static int anim_class_game_modes[NUM_ANIM_CLASSES];
173 static int anim_status_last = GAME_MODE_DEFAULT;
174 static int anim_classes_last = ANIM_CLASS_NONE;
177 static int getGlobalAnimationPart(struct GlobalAnimMainControlInfo *anim)
179 struct GraphicInfo *c = &anim->control_info;
180 int last_anim_random_frame = gfx.anim_random_frame;
183 gfx.anim_random_frame = -1; // (use simple, ad-hoc random numbers)
185 part_nr = getAnimationFrame(anim->num_parts, 1,
186 c->anim_mode, c->anim_start_frame,
189 gfx.anim_random_frame = last_anim_random_frame;
194 static int compareGlobalAnimPartControlInfo(const void *obj1, const void *obj2)
196 const struct GlobalAnimPartControlInfo *o1 =
197 (struct GlobalAnimPartControlInfo *)obj1;
198 const struct GlobalAnimPartControlInfo *o2 =
199 (struct GlobalAnimPartControlInfo *)obj2;
202 if (o1->control_info.draw_order != o2->control_info.draw_order)
203 compare_result = o1->control_info.draw_order - o2->control_info.draw_order;
205 compare_result = o1->nr - o2->nr;
207 return compare_result;
210 static int compareGlobalAnimMainControlInfo(const void *obj1, const void *obj2)
212 const struct GlobalAnimMainControlInfo *o1 =
213 (struct GlobalAnimMainControlInfo *)obj1;
214 const struct GlobalAnimMainControlInfo *o2 =
215 (struct GlobalAnimMainControlInfo *)obj2;
218 if (o1->control_info.draw_order != o2->control_info.draw_order)
219 compare_result = o1->control_info.draw_order - o2->control_info.draw_order;
221 compare_result = o1->nr - o2->nr;
223 return compare_result;
226 static void PrepareBackbuffer()
228 if (game_status != GAME_MODE_PLAYING)
231 BlitScreenToBitmap(backbuffer);
234 boolean ToonNeedsRedraw()
241 int num_toons = MAX_NUM_TOONS;
244 if (global.num_toons >= 0 && global.num_toons < MAX_NUM_TOONS)
245 num_toons = global.num_toons;
247 for (i = 0; i < num_toons; i++)
249 int graphic = IMG_TOON_1 + i;
250 struct FileInfo *image = getImageListEntryFromImageID(graphic);
252 toons[i].bitmap = graphic_info[graphic].bitmap;
254 toons[i].src_x = graphic_info[graphic].src_x;
255 toons[i].src_y = graphic_info[graphic].src_y;
257 toons[i].width = graphic_info[graphic].width;
258 toons[i].height = graphic_info[graphic].height;
260 toons[i].anim_frames = graphic_info[graphic].anim_frames;
261 toons[i].anim_delay = graphic_info[graphic].anim_delay;
262 toons[i].anim_mode = graphic_info[graphic].anim_mode;
263 toons[i].anim_start_frame = graphic_info[graphic].anim_start_frame;
265 toons[i].step_offset = graphic_info[graphic].step_offset;
266 toons[i].step_delay = graphic_info[graphic].step_delay;
268 toons[i].direction = image->parameter[GFX_ARG_DIRECTION];
269 toons[i].position = image->parameter[GFX_ARG_POSITION];
272 InitToonScreen(bitmap_db_toons,
273 BackToFront, PrepareBackbuffer, ToonNeedsRedraw,
275 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
279 static void InitToonControls()
281 int mode_nr_toons = GAME_MODE_PSEUDO_TOONS;
282 struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr_toons];
283 struct GlobalAnimMainControlInfo *anim = &ctrl->anim[ctrl->num_anims];
284 int mode_nr, anim_nr, part_nr;
285 int control = IMG_INTERNAL_GLOBAL_TOON_DEFAULT;
286 int num_toons = MAX_NUM_TOONS;
289 if (global.num_toons >= 0 && global.num_toons < MAX_NUM_TOONS)
290 num_toons = global.num_toons;
292 mode_nr = mode_nr_toons;
293 anim_nr = ctrl->num_anims;
296 anim->mode_nr = mode_nr;
297 anim->control_info = graphic_info[control];
300 anim->part_counter = 0;
301 anim->active_part_nr = 0;
303 anim->has_base = FALSE;
305 anim->init_delay_counter = 0;
307 anim->state = ANIM_STATE_INACTIVE;
311 for (i = 0; i < num_toons; i++)
313 struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
314 int sound = SND_UNDEFINED;
315 int graphic = IMG_TOON_1 + i;
316 int control = graphic;
319 part->anim_nr = anim_nr;
320 part->mode_nr = mode_nr;
322 part->graphic = graphic;
323 part->graphic_info = graphic_info[graphic];
324 part->control_info = graphic_info[control];
326 part->graphic_info.anim_delay *= part->graphic_info.step_delay;
328 part->control_info.init_delay_fixed = 0;
329 part->control_info.init_delay_random = 150;
331 part->control_info.x = ARG_UNDEFINED_VALUE;
332 part->control_info.y = ARG_UNDEFINED_VALUE;
334 part->initial_anim_sync_frame = 0;
336 part->step_delay = 0;
337 part->step_delay_value = graphic_info[control].step_delay;
339 part->state = ANIM_STATE_INACTIVE;
340 part->last_anim_status = -1;
349 void InitGlobalAnimControls()
352 int mode_nr, anim_nr, part_nr;
353 int sound, graphic, control;
357 ResetDelayCounter(&anim_sync_frame_delay);
359 for (m = 0; m < NUM_GAME_MODES; m++)
363 struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr];
370 for (a = 0; a < NUM_GLOBAL_ANIMS; a++)
372 struct GlobalAnimMainControlInfo *anim = &ctrl->anim[anim_nr];
373 int ctrl_id = GLOBAL_ANIM_ID_CONTROL_FIRST + a;
375 control = global_anim_info[ctrl_id].graphic[GLOBAL_ANIM_ID_PART_BASE][m];
377 // if no base animation parameters defined, use default values
378 if (control == IMG_UNDEFINED)
379 control = IMG_INTERNAL_GLOBAL_ANIM_DEFAULT;
382 anim->mode_nr = mode_nr;
383 anim->control_info = graphic_info[control];
386 anim->part_counter = 0;
387 anim->active_part_nr = 0;
389 anim->has_base = FALSE;
391 anim->init_delay_counter = 0;
393 anim->state = ANIM_STATE_INACTIVE;
397 for (p = 0; p < NUM_GLOBAL_ANIM_PARTS_ALL; p++)
399 struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
401 sound = global_anim_info[a].sound[p][m];
402 graphic = global_anim_info[a].graphic[p][m];
403 control = global_anim_info[ctrl_id].graphic[p][m];
405 if (graphic == IMG_UNDEFINED || graphic_info[graphic].bitmap == NULL ||
406 control == IMG_UNDEFINED)
410 printf("::: mode == %d, anim = %d, part = %d [%d, %d, %d] [%d]\n",
411 m, a, p, mode_nr, anim_nr, part_nr, control);
415 printf("::: mode == %d, anim = %d, part = %d [%d, %d, %d] [%d]\n",
416 m, a, p, mode_nr, anim_nr, part_nr, sound);
420 part->anim_nr = anim_nr;
421 part->mode_nr = mode_nr;
423 part->graphic = graphic;
424 part->graphic_info = graphic_info[graphic];
425 part->control_info = graphic_info[control];
427 part->initial_anim_sync_frame = 0;
429 part->step_delay = 0;
430 part->step_delay_value = graphic_info[control].step_delay;
432 part->state = ANIM_STATE_INACTIVE;
433 part->last_anim_status = -1;
435 if (p < GLOBAL_ANIM_ID_PART_BASE)
443 anim->has_base = TRUE;
447 if (anim->num_parts > 0 || anim->has_base)
457 /* sort all animations according to draw_order and animation number */
458 for (m = 0; m < NUM_GAME_MODES; m++)
460 struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[m];
462 /* sort all main animations for this game mode */
463 qsort(ctrl->anim, ctrl->num_anims,
464 sizeof(struct GlobalAnimMainControlInfo),
465 compareGlobalAnimMainControlInfo);
467 for (a = 0; a < ctrl->num_anims; a++)
469 struct GlobalAnimMainControlInfo *anim = &ctrl->anim[a];
471 /* sort all animation parts for this main animation */
472 qsort(anim->part, anim->num_parts,
473 sizeof(struct GlobalAnimPartControlInfo),
474 compareGlobalAnimPartControlInfo);
478 for (i = 0; i < NUM_GAME_MODES; i++)
479 game_mode_anim_classes[i] = ANIM_CLASS_NONE;
480 for (i = 0; game_mode_anim_classes_list[i].game_mode != -1; i++)
481 game_mode_anim_classes[game_mode_anim_classes_list[i].game_mode] =
482 game_mode_anim_classes_list[i].class;
484 for (i = 0; i < NUM_ANIM_CLASSES; i++)
485 anim_class_game_modes[i] = GAME_MODE_DEFAULT;
486 for (i = 0; anim_class_game_modes_list[i].game_mode != -1; i++)
487 anim_class_game_modes[anim_class_game_modes_list[i].class_bit] =
488 anim_class_game_modes_list[i].game_mode;
490 anim_status_last = GAME_MODE_LOADING;
491 anim_classes_last = ANIM_CLASS_NONE;
494 void InitGlobalAnimations()
496 InitGlobalAnimControls();
499 void DrawGlobalAnimExt(int drawing_stage)
503 if (global.anim_status != anim_status_last)
505 boolean before_fading = (global.anim_status == GAME_MODE_PSEUDO_FADING);
506 boolean after_fading = (anim_status_last == GAME_MODE_PSEUDO_FADING);
507 int anim_classes_next = game_mode_anim_classes[global.anim_status_next];
510 // ---------- part 1 ------------------------------------------------------
511 // start or stop global animations by change of game mode
512 // (special handling of animations for "current screen" and "all screens")
514 // stop animations for last screen
515 HandleGlobalAnim(ANIM_STOP, anim_status_last);
517 // start animations for current screen
518 HandleGlobalAnim(ANIM_START, global.anim_status);
520 // start animations for all screens after loading new artwork set
521 if (anim_status_last == GAME_MODE_LOADING)
522 HandleGlobalAnim(ANIM_START, GAME_MODE_DEFAULT);
524 // ---------- part 2 ------------------------------------------------------
525 // start or stop global animations by change of animation class
526 // (generic handling of animations for "class of screens")
528 for (i = 0; i < NUM_ANIM_CLASSES; i++)
530 int anim_class_check = (1 << i);
531 int anim_class_game_mode = anim_class_game_modes[i];
532 int anim_class_last = anim_classes_last & anim_class_check;
533 int anim_class_next = anim_classes_next & anim_class_check;
535 // stop animations for changed screen class before fading to new screen
536 if (before_fading && anim_class_last && !anim_class_next)
537 HandleGlobalAnim(ANIM_STOP, anim_class_game_mode);
539 // start animations for changed screen class after fading to new screen
540 if (after_fading && !anim_class_last && anim_class_next)
541 HandleGlobalAnim(ANIM_START, anim_class_game_mode);
545 anim_classes_last = anim_classes_next;
547 anim_status_last = global.anim_status;
550 if (!setup.toons || global.anim_status == GAME_MODE_LOADING)
553 if (drawing_stage == DRAW_GLOBAL_ANIM_STAGE_1)
556 for (mode_nr = 0; mode_nr < NUM_GAME_MODES; mode_nr++)
558 struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr];
562 if (mode_nr != GFX_SPECIAL_ARG_DEFAULT &&
563 mode_nr != game_status)
567 for (anim_nr = 0; anim_nr < ctrl->num_anims; anim_nr++)
569 struct GlobalAnimMainControlInfo *anim = &ctrl->anim[anim_nr];
570 struct GraphicInfo *c = &anim->control_info;
571 int part_first, part_last;
574 if (!(anim->state & ANIM_STATE_RUNNING))
577 part_first = part_last = anim->active_part_nr;
579 if (c->anim_mode & ANIM_ALL || anim->num_parts == 0)
581 int num_parts = anim->num_parts + (anim->has_base ? 1 : 0);
584 part_last = num_parts - 1;
587 for (part_nr = part_first; part_nr <= part_last; part_nr++)
589 struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
590 struct GraphicInfo *g = &part->graphic_info;
593 int width = g->width;
594 int height = g->height;
602 if (!(part->state & ANIM_STATE_RUNNING))
605 if (part->drawing_stage != drawing_stage)
614 else if (part->x > part->viewport_width - g->width)
615 width -= (part->x - (part->viewport_width - g->width));
623 else if (part->y > part->viewport_height - g->height)
624 height -= (part->y - (part->viewport_height - g->height));
626 if (width <= 0 || height <= 0)
629 dst_x += part->viewport_x;
630 dst_y += part->viewport_y;
632 sync_frame = anim_sync_frame - part->initial_anim_sync_frame;
633 frame = getAnimationFrame(g->anim_frames, g->anim_delay,
634 g->anim_mode, g->anim_start_frame,
637 getFixedGraphicSource(part->graphic, frame, &src_bitmap,
643 BlitToScreenMasked(src_bitmap, src_x, src_y, width, height,
650 void DrawGlobalAnim(int drawing_stage)
652 DrawGlobalAnimExt(drawing_stage);
655 boolean SetGlobalAnimPart_Viewport(struct GlobalAnimPartControlInfo *part)
661 boolean changed = FALSE;
663 if (part->last_anim_status == global.anim_status)
666 part->last_anim_status = global.anim_status;
668 part->drawing_stage = DRAW_GLOBAL_ANIM_STAGE_1;
670 if (part->control_info.class == get_hash_from_key("window") ||
671 part->control_info.class == get_hash_from_key("border"))
675 viewport_width = WIN_XSIZE;
676 viewport_height = WIN_YSIZE;
678 part->drawing_stage = DRAW_GLOBAL_ANIM_STAGE_2;
680 else if (part->control_info.class == get_hash_from_key("door_1"))
684 viewport_width = DXSIZE;
685 viewport_height = DYSIZE;
687 else if (part->control_info.class == get_hash_from_key("door_2"))
691 viewport_width = VXSIZE;
692 viewport_height = VYSIZE;
694 else // default: "playfield"
696 viewport_x = REAL_SX;
697 viewport_y = REAL_SY;
698 viewport_width = FULL_SXSIZE;
699 viewport_height = FULL_SYSIZE;
702 if (viewport_x != part->viewport_x ||
703 viewport_y != part->viewport_y ||
704 viewport_width != part->viewport_width ||
705 viewport_height != part->viewport_height)
707 part->viewport_x = viewport_x;
708 part->viewport_y = viewport_y;
709 part->viewport_width = viewport_width;
710 part->viewport_height = viewport_height;
718 void PlayGlobalAnimSound(struct GlobalAnimPartControlInfo *part)
720 int sound = part->sound;
722 if (sound == SND_UNDEFINED)
725 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
726 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
729 // !!! TODO: ADD STEREO POSITION FOR MOVING ANIMATIONS !!!
730 if (IS_LOOP_SOUND(sound))
731 PlaySoundLoop(sound);
736 printf("::: PLAY %d.%d.%d: %d\n",
737 part->anim_nr, part->nr, part->mode_nr, sound);
741 void StopGlobalAnimSound(struct GlobalAnimPartControlInfo *part)
743 int sound = part->sound;
745 if (sound == SND_UNDEFINED)
751 printf("::: STOP %d.%d.%d: %d\n",
752 part->anim_nr, part->nr, part->mode_nr, sound);
756 int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state)
758 struct GraphicInfo *g = &part->graphic_info;
759 struct GraphicInfo *c = &part->control_info;
760 boolean viewport_changed = SetGlobalAnimPart_Viewport(part);
762 if (viewport_changed)
763 state |= ANIM_STATE_RESTART;
765 if (state & ANIM_STATE_RESTART)
767 ResetDelayCounterExt(&part->step_delay, anim_sync_frame);
769 part->init_delay_counter =
770 (c->init_delay_fixed + GetSimpleRandom(c->init_delay_random));
772 part->anim_delay_counter =
773 (c->anim_delay_fixed + GetSimpleRandom(c->anim_delay_random));
775 part->initial_anim_sync_frame =
776 (g->anim_global_sync ? 0 : anim_sync_frame + part->init_delay_counter);
778 if (c->direction & MV_HORIZONTAL)
780 int pos_bottom = part->viewport_height - g->height;
782 if (c->position == POS_TOP)
784 else if (c->position == POS_UPPER)
785 part->y = GetSimpleRandom(pos_bottom / 2);
786 else if (c->position == POS_MIDDLE)
787 part->y = pos_bottom / 2;
788 else if (c->position == POS_LOWER)
789 part->y = pos_bottom / 2 + GetSimpleRandom(pos_bottom / 2);
790 else if (c->position == POS_BOTTOM)
791 part->y = pos_bottom;
793 part->y = GetSimpleRandom(pos_bottom);
795 if (c->direction == MV_RIGHT)
797 part->step_xoffset = c->step_offset;
798 part->x = -g->width + part->step_xoffset;
802 part->step_xoffset = -c->step_offset;
803 part->x = part->viewport_width + part->step_xoffset;
806 part->step_yoffset = 0;
808 else if (c->direction & MV_VERTICAL)
810 int pos_right = part->viewport_width - g->width;
812 if (c->position == POS_LEFT)
814 else if (c->position == POS_RIGHT)
817 part->x = GetSimpleRandom(pos_right);
819 if (c->direction == MV_DOWN)
821 part->step_yoffset = c->step_offset;
822 part->y = -g->height + part->step_yoffset;
826 part->step_yoffset = -c->step_offset;
827 part->y = part->viewport_height + part->step_yoffset;
830 part->step_xoffset = 0;
837 part->step_xoffset = 0;
838 part->step_yoffset = 0;
841 if (c->x != ARG_UNDEFINED_VALUE)
843 if (c->y != ARG_UNDEFINED_VALUE)
846 if (c->step_xoffset != ARG_UNDEFINED_VALUE)
847 part->step_xoffset = c->step_xoffset;
848 if (c->step_yoffset != ARG_UNDEFINED_VALUE)
849 part->step_yoffset = c->step_yoffset;
851 if (part->init_delay_counter == 0)
852 PlayGlobalAnimSound(part);
855 if (part->init_delay_counter > 0)
857 part->init_delay_counter--;
859 if (part->init_delay_counter == 0)
860 PlayGlobalAnimSound(part);
862 return ANIM_STATE_WAITING;
865 // check if moving animation has left the visible screen area
866 if ((part->x <= -g->width && part->step_xoffset <= 0) ||
867 (part->x >= part->viewport_width && part->step_xoffset >= 0) ||
868 (part->y <= -g->height && part->step_yoffset <= 0) ||
869 (part->y >= part->viewport_height && part->step_yoffset >= 0))
871 // do not stop animation before "anim" or "post" counter are finished
872 if (part->anim_delay_counter == 0 &&
873 part->post_delay_counter == 0)
875 StopGlobalAnimSound(part);
877 part->post_delay_counter =
878 (c->post_delay_fixed + GetSimpleRandom(c->post_delay_random));
880 if (part->post_delay_counter > 0)
881 return ANIM_STATE_RUNNING;
883 // drawing last frame not needed here -- animation not visible anymore
884 return ANIM_STATE_RESTART;
888 if (part->anim_delay_counter > 0)
890 part->anim_delay_counter--;
892 if (part->anim_delay_counter == 0)
894 StopGlobalAnimSound(part);
896 part->post_delay_counter =
897 (c->post_delay_fixed + GetSimpleRandom(c->post_delay_random));
899 if (part->post_delay_counter > 0)
900 return ANIM_STATE_RUNNING;
902 // additional state "RUNNING" required to not skip drawing last frame
903 return ANIM_STATE_RESTART | ANIM_STATE_RUNNING;
907 if (part->post_delay_counter > 0)
909 part->post_delay_counter--;
911 if (part->post_delay_counter == 0)
912 return ANIM_STATE_RESTART;
914 return ANIM_STATE_WAITING;
917 if (!DelayReachedExt(&part->step_delay, part->step_delay_value,
919 return ANIM_STATE_RUNNING;
923 static unsigned int last_counter = -1;
924 unsigned int counter = Counter();
926 printf("::: NEXT ANIM PART [%d, %d]\n",
927 anim_sync_frame, counter - last_counter);
929 last_counter = counter;
933 part->x += part->step_xoffset;
934 part->y += part->step_yoffset;
936 return ANIM_STATE_RUNNING;
939 void HandleGlobalAnim_Main(struct GlobalAnimMainControlInfo *anim, int action)
941 struct GlobalAnimPartControlInfo *part;
942 struct GraphicInfo *c = &anim->control_info;
943 int state, active_part_nr;
946 printf("::: HandleGlobalAnim_Main: %d, %d => %d\n",
947 anim->mode_nr, anim->nr, anim->num_parts);
948 printf("::: %d, %d, %d\n", global.num_toons, setup.toons, num_toons);
952 printf("::: %s(%d): %d, %d, %d [%d]\n",
953 (action == ANIM_START ? "ANIM_START" :
954 action == ANIM_CONTINUE ? "ANIM_CONTINUE" :
955 action == ANIM_STOP ? "ANIM_STOP" : "(should not happen)"),
957 anim->state & ANIM_STATE_RESTART,
958 anim->state & ANIM_STATE_WAITING,
959 anim->state & ANIM_STATE_RUNNING,
966 anim->state = anim->last_state = ANIM_STATE_RESTART;
967 anim->active_part_nr = anim->last_active_part_nr = 0;
968 anim->part_counter = 0;
973 if (anim->state == ANIM_STATE_INACTIVE)
976 anim->state = anim->last_state;
977 anim->active_part_nr = anim->last_active_part_nr;
982 anim->state = ANIM_STATE_INACTIVE;
985 int num_parts = anim->num_parts + (anim->has_base ? 1 : 0);
988 for (i = 0; i < num_parts; i++)
989 StopGlobalAnimSound(&anim->part[i]);
998 if (c->anim_mode & ANIM_ALL || anim->num_parts == 0)
1000 int num_parts = anim->num_parts + (anim->has_base ? 1 : 0);
1004 printf("::: HandleGlobalAnim_Main: %d, %d => %d\n",
1005 anim->mode_nr, anim->nr, num_parts);
1008 for (i = 0; i < num_parts; i++)
1010 part = &anim->part[i];
1015 anim->state = ANIM_STATE_RUNNING;
1016 part->state = ANIM_STATE_RESTART;
1021 if (part->state == ANIM_STATE_INACTIVE)
1027 part->state = ANIM_STATE_INACTIVE;
1035 part->state = HandleGlobalAnim_Part(part, part->state);
1037 // when animation mode is "once", stop after animation was played once
1038 if (c->anim_mode & ANIM_ONCE &&
1039 part->state & ANIM_STATE_RESTART)
1040 part->state = ANIM_STATE_INACTIVE;
1043 anim->last_state = anim->state;
1044 anim->last_active_part_nr = anim->active_part_nr;
1049 if (anim->state & ANIM_STATE_RESTART) // directly after restart
1050 anim->active_part_nr = getGlobalAnimationPart(anim);
1052 part = &anim->part[anim->active_part_nr];
1054 part->state = ANIM_STATE_RUNNING;
1056 anim->state = HandleGlobalAnim_Part(part, anim->state);
1058 if (anim->state & ANIM_STATE_RESTART)
1059 anim->part_counter++;
1061 // when animation mode is "once", stop after all animations were played once
1062 if (c->anim_mode & ANIM_ONCE &&
1063 anim->part_counter == anim->num_parts)
1064 anim->state = ANIM_STATE_INACTIVE;
1066 state = anim->state;
1067 active_part_nr = anim->active_part_nr;
1069 // while the animation parts are pausing (waiting or inactive), play the base
1070 // (main) animation; this corresponds to the "boring player animation" logic
1071 // (!!! KLUDGE WARNING: I THINK THIS IS A MESS THAT SHOULD BE CLEANED UP !!!)
1074 if (anim->state == ANIM_STATE_WAITING ||
1075 anim->state == ANIM_STATE_INACTIVE)
1077 anim->active_part_nr = anim->num_parts; // part nr of base animation
1078 part = &anim->part[anim->active_part_nr];
1080 if (anim->state != anim->last_state)
1081 part->state = ANIM_STATE_RESTART;
1083 anim->state = ANIM_STATE_RUNNING;
1084 part->state = HandleGlobalAnim_Part(part, part->state);
1088 anim->last_state = state;
1089 anim->last_active_part_nr = active_part_nr;
1092 void HandleGlobalAnim_Mode(struct GlobalAnimControlInfo *ctrl, int action)
1097 printf("::: HandleGlobalAnim_Mode: %d => %d\n",
1098 ctrl->nr, ctrl->num_anims);
1101 for (i = 0; i < ctrl->num_anims; i++)
1102 HandleGlobalAnim_Main(&ctrl->anim[i], action);
1105 static void HandleGlobalAnim(int action, int game_mode)
1108 printf("::: HandleGlobalAnim [mode == %d]\n", game_status);
1111 HandleGlobalAnim_Mode(&global_anim_ctrl[game_mode], action);
1114 void InitAnimation()
1118 void StopAnimation()
1122 static void DoAnimationExt()
1127 printf("::: DoAnimation [%d, %d]\n", anim_sync_frame, Counter());
1131 WaitUntilDelayReached(&anim_sync_frame_delay, anim_sync_frame_delay_value);
1134 if (DelayReached(&anim_sync_frame_delay, anim_sync_frame_delay_value))
1138 for (i = 0; i < NUM_GAME_MODES; i++)
1139 HandleGlobalAnim(ANIM_CONTINUE, i);
1142 // force screen redraw in next frame to continue drawing global animations
1143 redraw_mask = REDRAW_ALL;
1149 // HandleAnimation(ANIM_CONTINUE);
1152 // force screen redraw in next frame to continue drawing global animations
1153 redraw_mask = REDRAW_ALL;