1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
18 /* values for toon animation */
20 #define ANIM_CONTINUE 1
24 static struct ToonScreenInfo screen_info;
27 /* ========================================================================= */
28 /* generic animation frame calculation */
29 /* ========================================================================= */
31 int getAnimationFrame(int num_frames, int delay, int mode, int start_frame,
36 sync_frame += start_frame * delay;
38 if (mode & ANIM_LOOP) /* normal, looping animation */
40 frame = (sync_frame % (delay * num_frames)) / delay;
42 else if (mode & ANIM_LINEAR) /* normal, non-looping animation */
44 frame = sync_frame / delay;
46 if (frame > num_frames - 1)
47 frame = num_frames - 1;
49 else if (mode & ANIM_PINGPONG) /* use border frames once */
51 int max_anim_frames = 2 * num_frames - 2;
53 frame = (sync_frame % (delay * max_anim_frames)) / delay;
54 frame = (frame < num_frames ? frame : max_anim_frames - frame);
56 else if (mode & ANIM_PINGPONG2) /* use border frames twice */
58 int max_anim_frames = 2 * num_frames;
60 frame = (sync_frame % (delay * max_anim_frames)) / delay;
61 frame = (frame < num_frames ? frame : max_anim_frames - frame - 1);
64 if (mode & ANIM_REVERSE) /* use reverse animation direction */
65 frame = num_frames - frame - 1;
71 /* ========================================================================= */
72 /* toon animation functions */
73 /* ========================================================================= */
75 void InitToonScreen(Bitmap *save_buffer,
76 void (*update_function)(void),
77 void (*prepare_backbuffer_function)(void),
78 boolean (*redraw_needed_function)(void),
79 struct ToonInfo *toons, int num_toons,
80 int startx, int starty,
81 int width, int height,
82 int frame_delay_value)
84 screen_info.save_buffer = save_buffer;
85 screen_info.update_function = update_function;
86 screen_info.prepare_backbuffer_function = prepare_backbuffer_function;
87 screen_info.redraw_needed_function = redraw_needed_function;
88 screen_info.toons = toons;
89 screen_info.num_toons = num_toons;
90 screen_info.startx = startx;
91 screen_info.starty = starty;
92 screen_info.width = width;
93 screen_info.height = height;
94 screen_info.frame_delay_value = frame_delay_value;
97 void DrawAnim(Bitmap *toon_bitmap, GC toon_clip_gc,
98 int src_x, int src_y, int width, int height,
99 int dest_x, int dest_y, int pad_x, int pad_y)
101 int buf_x = DOOR_GFX_PAGEX3, buf_y = DOOR_GFX_PAGEY1;
104 /* special method to avoid flickering interference with BackToFront() */
105 BlitBitmap(backbuffer, screen_info.save_buffer, dest_x-pad_x, dest_y-pad_y,
106 width+2*pad_x, height+2*pad_y, buf_x, buf_y);
107 SetClipOrigin(toon_bitmap, toon_clip_gc, dest_x-src_x, dest_y-src_y);
108 BlitBitmapMasked(toon_bitmap, backbuffer,
109 src_x, src_y, width, height, dest_x, dest_y);
110 BlitBitmap(backbuffer, window, dest_x-pad_x, dest_y-pad_y,
111 width+2*pad_x, height+2*pad_y, dest_x-pad_x, dest_y-pad_y);
113 screen_info.update_function();
115 BlitBitmap(screen_info.save_buffer, backbuffer, buf_x, buf_y,
116 width+2*pad_x, height+2*pad_y, dest_x-pad_x, dest_y-pad_y);
118 /* normal method, causing flickering interference with BackToFront() */
119 BlitBitmap(backbuffer, screen_info.save_buffer, dest_x-pad_x, dest_y-pad_y,
120 width+2*pad_x, height+2*pad_y, buf_x, buf_y);
121 SetClipOrigin(toon_bitmap,toon_clip_gc, buf_x-src_x+pad_x,buf_y-src_y+pad_y);
122 BlitBitmapMasked(toon_bitmap, screen_info.save_buffer,
123 src_x, src_y, width, height, buf_x+pad_x, buf_y+pad_y);
124 BlitBitmap(screen_info.save_buffer, window, buf_x, buf_y,
125 width+2*pad_x, height+2*pad_y, dest_x-pad_x, dest_y-pad_y);
131 boolean AnimateToon(int toon_nr, boolean restart)
133 static unsigned long animation_frame_counter = 0;
134 static int pos_x = 0, pos_y = 0;
135 static int delta_x = 0, delta_y = 0;
136 static int frame = 0;
137 static boolean horiz_move, vert_move;
138 static unsigned long anim_delay = 0;
139 static unsigned long anim_delay_value = 0;
140 static int width,height;
141 static int pad_x,pad_y;
142 static int cut_x,cut_y;
143 static int src_x, src_y;
144 static int dest_x, dest_y;
145 struct ToonInfo *anim = &screen_info.toons[toon_nr];
146 Bitmap *anim_bitmap = screen_info.toons[toon_nr].bitmap;
147 GC anim_clip_gc = anim_bitmap->stored_clip_gc;
151 horiz_move = (anim->direction & (ANIMDIR_LEFT | ANIMDIR_RIGHT));
152 vert_move = (anim->direction & (ANIMDIR_UP | ANIMDIR_DOWN));
153 anim_delay_value = anim->move_delay * screen_info.frame_delay_value;
155 frame = getAnimationFrame(anim->anim_frames, anim->anim_delay,
156 anim->anim_mode, anim->start_frame,
157 animation_frame_counter++);
161 if (anim->position == ANIMPOS_UP)
163 else if (anim->position == ANIMPOS_DOWN)
164 pos_y = screen_info.height - anim->height;
165 else if (anim->position == ANIMPOS_UPPER)
166 pos_y = SimpleRND((screen_info.height - anim->height) / 2);
168 pos_y = SimpleRND(screen_info.height - anim->height);
170 if (anim->direction == ANIMDIR_RIGHT)
172 delta_x = anim->stepsize;
173 pos_x = -anim->width + delta_x;
177 delta_x = -anim->stepsize;
178 pos_x = screen_info.width + delta_x;
184 if (anim->position == ANIMPOS_LEFT)
186 else if (anim->position == ANIMPOS_RIGHT)
187 pos_x = screen_info.width - anim->width;
189 pos_x = SimpleRND(screen_info.width - anim->width);
191 if (anim->direction == ANIMDIR_DOWN)
193 delta_y = anim->stepsize;
194 pos_y = -anim->height + delta_y;
198 delta_y = -anim->stepsize;
199 pos_y = screen_info.width + delta_y;
205 if (pos_x <= -anim->width - anim->stepsize ||
206 pos_x >= screen_info.width + anim->stepsize ||
207 pos_y <= -anim->height - anim->stepsize ||
208 pos_y >= screen_info.height + anim->stepsize)
211 if (!DelayReached(&anim_delay, anim_delay_value))
213 if (screen_info.redraw_needed_function() && !restart)
214 DrawAnim(anim_bitmap, anim_clip_gc,
215 src_x + cut_x, src_y + cut_y,
217 screen_info.startx + dest_x,
218 screen_info.starty + dest_y,
224 if (pos_x < -anim->width)
225 pos_x = -anim->width;
226 else if (pos_x > screen_info.width)
227 pos_x = screen_info.width;
228 if (pos_y < -anim->height)
229 pos_y = -anim->height;
230 else if (pos_y > screen_info.height)
231 pos_y = screen_info.height;
233 pad_x = (horiz_move ? anim->stepsize : 0);
234 pad_y = (vert_move ? anim->stepsize : 0);
235 src_x = anim->src_x + frame * anim->width;
241 height = anim->height;
249 else if (pos_x > screen_info.width - anim->width)
250 width -= (pos_x - (screen_info.width - anim->width));
258 else if (pos_y > screen_info.height - anim->height)
259 height -= (pos_y - (screen_info.height - anim->height));
261 DrawAnim(anim_bitmap, anim_clip_gc,
262 src_x + cut_x, src_y + cut_y,
264 screen_info.startx + dest_x,
265 screen_info.starty + dest_y,
271 frame = getAnimationFrame(anim->anim_frames, anim->anim_delay,
272 anim->anim_mode, anim->start_frame,
273 animation_frame_counter++);
278 void HandleAnimation(int mode)
280 static unsigned long animstart_delay = -1;
281 static unsigned long animstart_delay_value = 0;
282 static boolean anim_restart = TRUE;
283 static boolean reset_delay = TRUE;
284 static int toon_nr = 0;
293 screen_info.prepare_backbuffer_function();
303 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
305 /* Redraw background even when in direct drawing mode */
306 draw_mode = setup.direct_draw;
307 setup.direct_draw = FALSE;
308 screen_info.update_function();
309 setup.direct_draw = draw_mode;
319 animstart_delay = Counter();
320 animstart_delay_value = SimpleRND(3000);
326 if (!DelayReached(&animstart_delay, animstart_delay_value))
329 toon_nr = SimpleRND(screen_info.num_toons);
332 anim_restart = reset_delay = AnimateToon(toon_nr,anim_restart);
337 HandleAnimation(ANIM_START);
342 HandleAnimation(ANIM_STOP);
347 HandleAnimation(ANIM_CONTINUE);