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 struct GlobalAnimPartControlInfo
34 struct GraphicInfo graphic_info;
35 struct GraphicInfo control_info;
43 int step_xoffset, step_yoffset;
45 unsigned int initial_anim_sync_frame;
46 unsigned int step_delay, step_delay_value;
48 int init_delay_counter;
49 int anim_delay_counter;
50 int post_delay_counter;
58 struct GlobalAnimMainControlInfo
60 struct GlobalAnimPartControlInfo base;
61 struct GlobalAnimPartControlInfo part[NUM_GLOBAL_ANIM_PARTS_AND_TOONS];
66 struct GraphicInfo control_info;
74 int init_delay_counter;
79 struct GlobalAnimControlInfo
81 struct GlobalAnimMainControlInfo anim[NUM_GLOBAL_ANIMS_AND_TOONS];
88 /* forward declaration for internal use */
89 static void DoAnimationExt(void);
91 static struct GlobalAnimControlInfo global_anim_ctrl[NUM_SPECIAL_GFX_ARGS];
92 static struct ToonInfo toons[MAX_NUM_TOONS];
94 static unsigned int anim_sync_frame = 0;
95 static unsigned int anim_sync_frame_delay = 0;
96 static unsigned int anim_sync_frame_delay_value = GAME_FRAME_DELAY;
98 static boolean do_animations = FALSE;
101 static int getGlobalAnimationPart(struct GlobalAnimMainControlInfo *anim)
103 struct GraphicInfo *c = &anim->control_info;
104 int last_anim_random_frame = gfx.anim_random_frame;
107 gfx.anim_random_frame = -1; // (use simple, ad-hoc random numbers)
109 part_nr = getAnimationFrame(anim->num_parts, 1,
110 c->anim_mode, c->anim_start_frame,
113 gfx.anim_random_frame = last_anim_random_frame;
118 static void PrepareBackbuffer()
120 if (game_status != GAME_MODE_PLAYING)
123 BlitScreenToBitmap(backbuffer);
126 boolean ToonNeedsRedraw()
133 int num_toons = MAX_NUM_TOONS;
136 if (global.num_toons >= 0 && global.num_toons < MAX_NUM_TOONS)
137 num_toons = global.num_toons;
139 for (i = 0; i < num_toons; i++)
141 int graphic = IMG_TOON_1 + i;
142 struct FileInfo *image = getImageListEntryFromImageID(graphic);
144 toons[i].bitmap = graphic_info[graphic].bitmap;
146 toons[i].src_x = graphic_info[graphic].src_x;
147 toons[i].src_y = graphic_info[graphic].src_y;
149 toons[i].width = graphic_info[graphic].width;
150 toons[i].height = graphic_info[graphic].height;
152 toons[i].anim_frames = graphic_info[graphic].anim_frames;
153 toons[i].anim_delay = graphic_info[graphic].anim_delay;
154 toons[i].anim_mode = graphic_info[graphic].anim_mode;
155 toons[i].anim_start_frame = graphic_info[graphic].anim_start_frame;
157 toons[i].step_offset = graphic_info[graphic].step_offset;
158 toons[i].step_delay = graphic_info[graphic].step_delay;
160 toons[i].direction = image->parameter[GFX_ARG_DIRECTION];
161 toons[i].position = image->parameter[GFX_ARG_POSITION];
164 InitToonScreen(bitmap_db_toons,
165 BackToFront, PrepareBackbuffer, ToonNeedsRedraw,
167 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
171 static void InitToonControls()
173 struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[GAME_MODE_DEFAULT];
174 struct GlobalAnimMainControlInfo *anim = &ctrl->anim[ctrl->num_anims];
175 int mode_nr, anim_nr, part_nr;
176 int control = IMG_INTERNAL_GLOBAL_TOON_DEFAULT;
177 int num_toons = MAX_NUM_TOONS;
180 if (global.num_toons >= 0 && global.num_toons < MAX_NUM_TOONS)
181 num_toons = global.num_toons;
183 mode_nr = GAME_MODE_DEFAULT;
184 anim_nr = ctrl->num_anims;
187 anim->mode_nr = mode_nr;
188 anim->control_info = graphic_info[control];
191 anim->part_counter = 0;
192 anim->active_part_nr = 0;
194 anim->has_base = FALSE;
196 anim->init_delay_counter = 0;
198 anim->state = ANIM_STATE_INACTIVE;
202 for (i = 0; i < num_toons; i++)
204 struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
205 int graphic = IMG_TOON_1 + i;
206 int control = graphic;
209 part->anim_nr = anim_nr;
210 part->mode_nr = mode_nr;
211 part->graphic = graphic;
212 part->graphic_info = graphic_info[graphic];
213 part->control_info = graphic_info[control];
215 part->graphic_info.anim_delay *= part->graphic_info.step_delay;
217 part->control_info.init_delay_fixed = 0;
218 part->control_info.init_delay_random = 150;
220 part->control_info.x = ARG_UNDEFINED_VALUE;
221 part->control_info.y = ARG_UNDEFINED_VALUE;
223 part->initial_anim_sync_frame = 0;
225 part->step_delay = 0;
226 part->step_delay_value = graphic_info[control].step_delay;
228 part->state = ANIM_STATE_INACTIVE;
229 part->last_game_status = -1;
238 void InitGlobalAnimControls()
241 int mode_nr, anim_nr, part_nr;
242 int graphic, control;
246 ResetDelayCounter(&anim_sync_frame_delay);
248 for (m = 0; m < NUM_SPECIAL_GFX_ARGS; m++)
252 struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr];
259 for (a = 0; a < NUM_GLOBAL_ANIMS; a++)
261 struct GlobalAnimMainControlInfo *anim = &ctrl->anim[anim_nr];
262 int ctrl_id = GLOBAL_ANIM_ID_CONTROL_FIRST + a;
264 control = global_anim_info[ctrl_id].graphic[GLOBAL_ANIM_ID_PART_BASE][m];
266 // if no base animation parameters defined, use default values
267 if (control == IMG_UNDEFINED)
268 control = IMG_INTERNAL_GLOBAL_ANIM_DEFAULT;
271 anim->mode_nr = mode_nr;
272 anim->control_info = graphic_info[control];
275 anim->part_counter = 0;
276 anim->active_part_nr = 0;
278 anim->has_base = FALSE;
280 anim->init_delay_counter = 0;
282 anim->state = ANIM_STATE_INACTIVE;
286 for (p = 0; p < NUM_GLOBAL_ANIM_PARTS_ALL; p++)
288 struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
290 graphic = global_anim_info[a].graphic[p][m];
291 control = global_anim_info[ctrl_id].graphic[p][m];
293 if (graphic == IMG_UNDEFINED || graphic_info[graphic].bitmap == NULL ||
294 control == IMG_UNDEFINED)
298 printf("::: mode == %d, anim = %d, part = %d [%d, %d, %d] [%d]\n",
299 m, a, p, mode_nr, anim_nr, part_nr, control);
303 part->anim_nr = anim_nr;
304 part->mode_nr = mode_nr;
305 part->graphic = graphic;
306 part->graphic_info = graphic_info[graphic];
307 part->control_info = graphic_info[control];
309 part->initial_anim_sync_frame = 0;
311 part->step_delay = 0;
312 part->step_delay_value = graphic_info[control].step_delay;
314 part->state = ANIM_STATE_INACTIVE;
315 part->last_game_status = -1;
317 if (p < GLOBAL_ANIM_ID_PART_BASE)
325 anim->has_base = TRUE;
329 if (anim->num_parts > 0 || anim->has_base)
340 void DrawGlobalAnimExt(int drawing_stage)
344 if (game_status == GAME_MODE_LOADING)
345 do_animations = FALSE;
347 if (!do_animations || !setup.toons)
350 if (drawing_stage == DRAW_GLOBAL_ANIM_STAGE_1)
353 for (mode_nr = 0; mode_nr < NUM_SPECIAL_GFX_ARGS; mode_nr++)
355 struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr];
358 if (mode_nr != GFX_SPECIAL_ARG_DEFAULT &&
359 mode_nr != game_status)
362 for (anim_nr = 0; anim_nr < ctrl->num_anims; anim_nr++)
364 struct GlobalAnimMainControlInfo *anim = &ctrl->anim[anim_nr];
365 struct GraphicInfo *c = &anim->control_info;
366 int part_first, part_last;
369 if (!(anim->state & ANIM_STATE_RUNNING))
372 part_first = part_last = anim->active_part_nr;
374 if (c->anim_mode & ANIM_ALL || anim->num_parts == 0)
376 int num_parts = anim->num_parts + (anim->has_base ? 1 : 0);
379 part_last = num_parts - 1;
382 for (part_nr = part_first; part_nr <= part_last; part_nr++)
384 struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
385 struct GraphicInfo *g = &part->graphic_info;
388 int width = g->width;
389 int height = g->height;
397 if (!(part->state & ANIM_STATE_RUNNING))
400 if (part->drawing_stage != drawing_stage)
409 else if (part->x > part->viewport_width - g->width)
410 width -= (part->x - (part->viewport_width - g->width));
418 else if (part->y > part->viewport_height - g->height)
419 height -= (part->y - (part->viewport_height - g->height));
421 dst_x += part->viewport_x;
422 dst_y += part->viewport_y;
424 sync_frame = anim_sync_frame - part->initial_anim_sync_frame;
425 frame = getAnimationFrame(g->anim_frames, g->anim_delay,
426 g->anim_mode, g->anim_start_frame,
429 getFixedGraphicSource(part->graphic, frame, &src_bitmap,
435 BlitToScreenMasked(src_bitmap, src_x, src_y, width, height,
442 void DrawGlobalAnim(int drawing_stage)
444 if (!do_animations || !setup.toons)
447 DrawGlobalAnimExt(drawing_stage);
450 boolean SetGlobalAnimPart_Viewport(struct GlobalAnimPartControlInfo *part)
456 boolean changed = FALSE;
458 if (part->last_game_status == game_status)
461 part->last_game_status = game_status;
463 part->drawing_stage = DRAW_GLOBAL_ANIM_STAGE_1;
465 if (part->control_info.class == get_hash_from_key("window") ||
466 part->control_info.class == get_hash_from_key("border"))
470 viewport_width = WIN_XSIZE;
471 viewport_height = WIN_YSIZE;
473 part->drawing_stage = DRAW_GLOBAL_ANIM_STAGE_2;
475 else if (part->control_info.class == get_hash_from_key("door_1"))
479 viewport_width = DXSIZE;
480 viewport_height = DYSIZE;
482 else if (part->control_info.class == get_hash_from_key("door_2"))
486 viewport_width = VXSIZE;
487 viewport_height = VYSIZE;
489 else // default: "playfield"
491 viewport_x = REAL_SX;
492 viewport_y = REAL_SY;
493 viewport_width = FULL_SXSIZE;
494 viewport_height = FULL_SYSIZE;
497 if (viewport_x != part->viewport_x ||
498 viewport_y != part->viewport_y ||
499 viewport_width != part->viewport_width ||
500 viewport_height != part->viewport_height)
502 part->viewport_x = viewport_x;
503 part->viewport_y = viewport_y;
504 part->viewport_width = viewport_width;
505 part->viewport_height = viewport_height;
513 int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state)
515 struct GraphicInfo *g = &part->graphic_info;
516 struct GraphicInfo *c = &part->control_info;
517 boolean viewport_changed = SetGlobalAnimPart_Viewport(part);
519 if (viewport_changed)
520 state |= ANIM_STATE_RESTART;
522 if (state & ANIM_STATE_RESTART)
524 ResetDelayCounterExt(&part->step_delay, anim_sync_frame);
526 part->init_delay_counter =
527 (c->init_delay_fixed + GetSimpleRandom(c->init_delay_random));
529 part->anim_delay_counter =
530 (c->anim_delay_fixed + GetSimpleRandom(c->anim_delay_random));
532 part->initial_anim_sync_frame =
533 (g->anim_global_sync ? 0 : anim_sync_frame + part->init_delay_counter);
535 if (c->direction & MV_HORIZONTAL)
537 int pos_bottom = part->viewport_height - g->height;
539 if (c->position == POS_TOP)
541 else if (c->position == POS_UPPER)
542 part->y = GetSimpleRandom(pos_bottom / 2);
543 else if (c->position == POS_MIDDLE)
544 part->y = pos_bottom / 2;
545 else if (c->position == POS_LOWER)
546 part->y = pos_bottom / 2 + GetSimpleRandom(pos_bottom / 2);
547 else if (c->position == POS_BOTTOM)
548 part->y = pos_bottom;
550 part->y = GetSimpleRandom(pos_bottom);
552 if (c->direction == MV_RIGHT)
554 part->step_xoffset = c->step_offset;
555 part->x = -g->width + part->step_xoffset;
559 part->step_xoffset = -c->step_offset;
560 part->x = part->viewport_width + part->step_xoffset;
563 part->step_yoffset = 0;
565 else if (c->direction & MV_VERTICAL)
567 int pos_right = part->viewport_width - g->width;
569 if (c->position == POS_LEFT)
571 else if (c->position == POS_RIGHT)
574 part->x = GetSimpleRandom(pos_right);
576 if (c->direction == MV_DOWN)
578 part->step_yoffset = c->step_offset;
579 part->y = -g->height + part->step_yoffset;
583 part->step_yoffset = -c->step_offset;
584 part->y = part->viewport_height + part->step_yoffset;
587 part->step_xoffset = 0;
594 part->step_xoffset = 0;
595 part->step_yoffset = 0;
598 if (c->x != ARG_UNDEFINED_VALUE)
600 if (c->y != ARG_UNDEFINED_VALUE)
603 if (c->step_xoffset != ARG_UNDEFINED_VALUE)
604 part->step_xoffset = c->step_xoffset;
605 if (c->step_yoffset != ARG_UNDEFINED_VALUE)
606 part->step_yoffset = c->step_yoffset;
609 if (part->init_delay_counter > 0)
611 part->init_delay_counter--;
613 return ANIM_STATE_WAITING;
616 if ((part->x <= -g->width && part->step_xoffset <= 0) ||
617 (part->x >= part->viewport_width && part->step_xoffset >= 0) ||
618 (part->y <= -g->height && part->step_yoffset <= 0) ||
619 (part->y >= part->viewport_height && part->step_yoffset >= 0))
620 return ANIM_STATE_RESTART;
622 if (part->anim_delay_counter > 0)
624 part->anim_delay_counter--;
626 if (part->anim_delay_counter == 0)
628 part->post_delay_counter =
629 (c->post_delay_fixed + GetSimpleRandom(c->post_delay_random));
631 if (part->post_delay_counter > 0)
632 return ANIM_STATE_RUNNING;
634 return ANIM_STATE_RESTART | ANIM_STATE_RUNNING;
638 if (part->post_delay_counter > 0)
640 part->post_delay_counter--;
642 if (part->post_delay_counter == 0)
643 return ANIM_STATE_RESTART;
645 return ANIM_STATE_WAITING;
648 if (!DelayReachedExt(&part->step_delay, part->step_delay_value,
650 return ANIM_STATE_RUNNING;
654 static unsigned int last_counter = -1;
655 unsigned int counter = Counter();
657 printf("::: NEXT ANIM PART [%d, %d]\n",
658 anim_sync_frame, counter - last_counter);
660 last_counter = counter;
664 part->x += part->step_xoffset;
665 part->y += part->step_yoffset;
667 return ANIM_STATE_RUNNING;
670 void HandleGlobalAnim_Main(struct GlobalAnimMainControlInfo *anim, int action)
672 struct GlobalAnimPartControlInfo *part;
673 struct GraphicInfo *c = &anim->control_info;
674 boolean skip = FALSE;
677 printf("::: HandleGlobalAnim_Main: %d, %d => %d\n",
678 anim->mode_nr, anim->nr, anim->num_parts);
679 printf("::: %d, %d, %d\n", global.num_toons, setup.toons, num_toons);
683 printf("::: %s(%d): %d, %d, %d [%d]\n",
684 (action == ANIM_START ? "ANIM_START" :
685 action == ANIM_CONTINUE ? "ANIM_CONTINUE" :
686 action == ANIM_STOP ? "ANIM_STOP" : "(should not happen)"),
688 anim->state & ANIM_STATE_RESTART,
689 anim->state & ANIM_STATE_WAITING,
690 anim->state & ANIM_STATE_RUNNING,
697 anim->state = ANIM_STATE_RESTART;
698 anim->part_counter = 0;
699 anim->active_part_nr = 0;
705 if (anim->state == ANIM_STATE_INACTIVE)
711 anim->state = ANIM_STATE_INACTIVE;
720 if (c->anim_mode & ANIM_ALL || anim->num_parts == 0)
722 int num_parts = anim->num_parts + (anim->has_base ? 1 : 0);
726 printf("::: HandleGlobalAnim_Main: %d, %d => %d\n",
727 anim->mode_nr, anim->nr, num_parts);
730 for (i = 0; i < num_parts; i++)
732 part = &anim->part[i];
737 anim->state = ANIM_STATE_RUNNING;
738 part->state = ANIM_STATE_RESTART;
744 if (part->state == ANIM_STATE_INACTIVE)
750 part->state = ANIM_STATE_INACTIVE;
762 part->state = HandleGlobalAnim_Part(part, part->state);
771 if (anim->state & ANIM_STATE_RESTART) // directly after restart
772 anim->active_part_nr = getGlobalAnimationPart(anim);
774 part = &anim->part[anim->active_part_nr];
776 part->state = ANIM_STATE_RUNNING;
778 anim->state = HandleGlobalAnim_Part(part, anim->state);
780 if (anim->state & ANIM_STATE_RESTART)
781 anim->part_counter++;
784 void HandleGlobalAnim_Mode(struct GlobalAnimControlInfo *ctrl, int action)
789 printf("::: HandleGlobalAnim_Mode: %d => %d\n",
790 ctrl->nr, ctrl->num_anims);
793 for (i = 0; i < ctrl->num_anims; i++)
794 HandleGlobalAnim_Main(&ctrl->anim[i], action);
797 void HandleGlobalAnim(int action)
800 printf("::: HandleGlobalAnim [mode == %d]\n", game_status);
803 HandleGlobalAnim_Mode(&global_anim_ctrl[GAME_MODE_DEFAULT], action);
804 HandleGlobalAnim_Mode(&global_anim_ctrl[game_status], action);
809 // HandleAnimation(ANIM_START);
812 printf("::: InitAnimation\n");
817 InitGlobalAnimControls();
819 HandleGlobalAnim(ANIM_START);
821 do_animations = TRUE;
826 // HandleAnimation(ANIM_STOP);
829 printf("::: StopAnimation\n");
832 HandleGlobalAnim(ANIM_STOP);
834 do_animations = FALSE;
837 static void DoAnimationExt()
840 printf("::: DoAnimation [%d, %d]\n", anim_sync_frame, Counter());
844 WaitUntilDelayReached(&anim_sync_frame_delay, anim_sync_frame_delay_value);
847 if (DelayReached(&anim_sync_frame_delay, anim_sync_frame_delay_value))
851 HandleGlobalAnim(ANIM_CONTINUE);
854 // force screen redraw in next frame to continue drawing global animations
855 redraw_mask = REDRAW_ALL;
861 // HandleAnimation(ANIM_CONTINUE);
864 // force screen redraw in next frame to continue drawing global animations
865 redraw_mask = REDRAW_ALL;