1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * ©1995 Artsoft Development *
6 * 33659 Bielefeld-Senne *
7 * Telefon: (0521) 493245 *
8 * eMail: aeglos@valinor.owl.de *
9 * aeglos@uni-paderborn.de *
10 * q99492@pbhrzx.uni-paderborn.de *
11 *----------------------------------------------------------*
13 ***********************************************************/
22 #include <sys/param.h>
23 #include <sys/types.h>
25 void microsleep(unsigned long usec)
29 delay.tv_sec = usec / 1000000;
30 delay.tv_usec = usec % 1000000;
32 if (select(0,NULL,NULL,NULL,&delay)!=0)
33 fprintf(stderr,"%s: in function microsleep: select failed!\n",
37 long mainCounter(int mode)
39 static struct timeval base_time = { 0, 0 };
40 struct timeval current_time;
43 gettimeofday(¤t_time,NULL);
44 if (mode == INIT_COUNTER || current_time.tv_sec < base_time.tv_sec)
45 base_time = current_time;
47 counter_ms = (current_time.tv_sec - base_time.tv_sec)*1000
48 + (current_time.tv_usec - base_time.tv_usec)/1000;
50 if (mode == READ_COUNTER_100)
51 return(counter_ms/10); /* return 1/100 secs since last init */
52 else /* READ_COUNTER_1000 */
53 return(counter_ms); /* return 1/1000 secs since last init */
56 void InitCounter() /* set counter back to zero */
58 mainCounter(INIT_COUNTER);
61 long Counter() /* returns 1/100 secs since last call of InitCounter() */
63 return(mainCounter(READ_COUNTER_100));
66 long Counter2() /* returns 1/1000 secs since last call of InitCounter() */
68 return(mainCounter(READ_COUNTER_1000));
71 void WaitCounter(long value) /* wait for counter to reach value */
75 while((wait=value-Counter())>0)
76 microsleep(wait*10000);
79 void WaitCounter2(long value) /* wait for counter to reach value */
83 while((wait=value-Counter2())>0)
84 microsleep(wait*1000);
87 void Delay(long value)
92 BOOL DelayReached(long *counter_var, int delay)
94 long actual_counter = Counter();
96 if (actual_counter >= *counter_var+delay || actual_counter < *counter_var)
98 *counter_var = actual_counter;
105 BOOL FrameReached(long *frame_counter_var, int frame_delay)
107 long actual_frame_counter = FrameCounter;
109 if (actual_frame_counter >= *frame_counter_var+frame_delay
110 || actual_frame_counter < *frame_counter_var)
112 *frame_counter_var = actual_frame_counter;
119 unsigned long be2long(unsigned long *be) /* big-endian -> longword */
121 unsigned char *ptr = (unsigned char *)be;
123 return(ptr[0]<<24 | ptr[1]<<16 | ptr[2]<<8 | ptr[3]);
126 char *int2str(int ct, int nr)
130 sprintf(str,"%09d",ct);
131 return(&str[strlen(str)-nr]);
134 unsigned int SimpleRND(unsigned int max)
136 static unsigned long root = 654321;
137 struct timeval current_time;
139 gettimeofday(¤t_time,NULL);
140 root = root * 4253261 + current_time.tv_sec + current_time.tv_usec;
144 unsigned int RND(unsigned int max)
146 return(rand() % max);
149 unsigned int InitRND(long seed)
151 struct timeval current_time;
153 if (seed==NEW_RANDOMIZE)
155 gettimeofday(¤t_time,NULL);
156 srand((unsigned int) current_time.tv_usec);
157 return((unsigned int) current_time.tv_usec);
161 srand((unsigned int) seed);
162 return((unsigned int) seed);
170 if (!(pwd=getpwuid(getuid())))
173 return(pwd->pw_name);
178 HandleAnimation(ANIM_START);
183 HandleAnimation(ANIM_STOP);
188 HandleAnimation(ANIM_CONTINUE);
191 void HandleAnimation(int mode)
193 static long animstart_delay = -1;
194 static long animstart_delay_value = 0;
195 static BOOL anim_restart = TRUE;
196 static BOOL reset_delay = TRUE;
197 static int toon_nr = 0;
201 if (!toons_on || game_status==PLAYING)
206 if (!toons_on || tape.playing || tape.recording)
219 /* Fill empty backbuffer for animation functions */
220 if (direct_draw_on && game_status==PLAYING)
224 drawto_field = backbuffer;
226 for(xx=0;xx<SCR_FIELDX;xx++)
227 for(yy=0;yy<SCR_FIELDY;yy++)
228 DrawScreenField(xx,yy);
229 DrawLevelElement(JX,JY,EL_SPIELFIGUR);
231 drawto_field = window;
239 redraw_mask |= REDRAW_FIELD;
241 /* Redraw background even when in direct drawing mode */
242 draw_mode = direct_draw_on;
243 direct_draw_on = FALSE;
247 direct_draw_on = draw_mode;
257 animstart_delay = Counter();
258 animstart_delay_value = SimpleRND(500);
264 if (!DelayReached(&animstart_delay,animstart_delay_value))
267 toon_nr = SimpleRND(NUM_TOONS);
270 anim_restart = reset_delay = AnimateToon(toon_nr,anim_restart);
273 BOOL AnimateToon(int toon_nr, BOOL restart)
275 static pos_x = 0, pos_y = 0;
276 static delta_x = 0, delta_y = 0;
277 static int frame = 0, frame_step = 1;
278 static BOOL horiz_move, vert_move;
279 static long anim_delay = 0;
280 static int anim_delay_value = 0;
281 static int width,height;
282 static int pad_x,pad_y;
283 static int cut_x,cut_y;
284 static int src_x, src_y;
285 static int dest_x, dest_y;
286 static struct AnimInfo toon[NUM_TOONS] =
288 {DWARF_XSIZE, DWARF_YSIZE,
297 {DWARF_XSIZE, DWARF_YSIZE,
306 {JUMPER_XSIZE, JUMPER_YSIZE,
315 {CLOWN_XSIZE, CLOWN_YSIZE,
324 {BIRD_XSIZE, BIRD_YSIZE,
333 {BIRD_XSIZE, BIRD_YSIZE,
342 struct AnimInfo *anim = &toon[toon_nr];
346 horiz_move = (anim->direction & (ANIMDIR_LEFT | ANIMDIR_RIGHT));
347 vert_move = (anim->direction & (ANIMDIR_UP | ANIMDIR_DOWN));
348 anim_delay_value = 100/anim->frames_per_second;
353 if (anim->position==ANIMPOS_UP)
355 else if (anim->position==ANIMPOS_DOWN)
356 pos_y = FULL_SYSIZE-anim->height;
357 else if (anim->position==ANIMPOS_UPPER)
358 pos_y = SimpleRND((FULL_SYSIZE-anim->height)/2);
360 pos_y = SimpleRND(FULL_SYSIZE-anim->height);
362 if (anim->direction==ANIMDIR_RIGHT)
364 delta_x = anim->stepsize;
365 pos_x = -anim->width+delta_x;
369 delta_x = -anim->stepsize;
370 pos_x = FULL_SXSIZE+delta_x;
376 if (anim->position==ANIMPOS_LEFT)
378 else if (anim->position==ANIMPOS_RIGHT)
379 pos_x = FULL_SXSIZE-anim->width;
381 pos_x = SimpleRND(FULL_SXSIZE-anim->width);
383 if (anim->direction==ANIMDIR_DOWN)
385 delta_y = anim->stepsize;
386 pos_y = -anim->height+delta_y;
390 delta_y = -anim->stepsize;
391 pos_y = FULL_SYSIZE+delta_y;
397 if (pos_x <= -anim->width - anim->stepsize ||
398 pos_x >= FULL_SXSIZE + anim->stepsize ||
399 pos_y <= -anim->height - anim->stepsize ||
400 pos_y >= FULL_SYSIZE + anim->stepsize)
403 if (!DelayReached(&anim_delay,anim_delay_value))
405 if (game_status==HELPSCREEN && !restart)
406 DrawAnim(src_x+cut_x,src_y+cut_y, width,height,
407 REAL_SX+dest_x,REAL_SY+dest_y, pad_x,pad_y);
412 if (pos_x<-anim->width)
413 pos_x = -anim->width;
414 else if (pos_x>FULL_SXSIZE)
416 if (pos_y<-anim->height)
417 pos_y = -anim->height;
418 else if (pos_y>FULL_SYSIZE)
421 pad_x = (horiz_move ? anim->stepsize : 0);
422 pad_y = (vert_move ? anim->stepsize : 0);
423 src_x = anim->src_x + frame * anim->width;
429 height = anim->height;
437 else if (pos_x>FULL_SXSIZE-anim->width)
438 width -= (pos_x - (FULL_SXSIZE-anim->width));
446 else if (pos_y>FULL_SYSIZE-anim->height)
447 height -= (pos_y - (FULL_SYSIZE-anim->height));
449 DrawAnim(src_x+cut_x,src_y+cut_y, width,height,
450 REAL_SX+dest_x,REAL_SY+dest_y, pad_x,pad_y);
456 if (frame<0 || frame>=anim->frames)
461 frame = (frame<0 ? 1 : anim->frames-2);
464 frame = (frame<0 ? anim->frames-1 : 0);
470 void DrawAnim(int src_x, int src_y, int width, int height,
471 int dest_x, int dest_y, int pad_x, int pad_y)
473 int buf_x = DOOR_GFX_PAGEX3, buf_y = DOOR_GFX_PAGEY1;
476 /* special method to avoid flickering interference with BackToFront() */
477 XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,dest_x-pad_x,dest_y-pad_y,
478 width+2*pad_x,height+2*pad_y, buf_x,buf_y);
479 XSetClipOrigin(display,clip_gc[PIX_TOONS],dest_x-src_x,dest_y-src_y);
480 XCopyArea(display,pix[PIX_TOONS],backbuffer,clip_gc[PIX_TOONS],
481 src_x,src_y, width,height, dest_x,dest_y);
482 XCopyArea(display,backbuffer,window,gc, dest_x-pad_x,dest_y-pad_y,
483 width+2*pad_x,height+2*pad_y, dest_x-pad_x,dest_y-pad_y);
485 XCopyArea(display,pix[PIX_DB_DOOR],backbuffer,gc, buf_x,buf_y,
486 width+2*pad_x,height+2*pad_y, dest_x-pad_x,dest_y-pad_y);
488 /* normal method, causing flickering interference with BackToFront() */
489 XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,dest_x-pad_x,dest_y-pad_y,
490 width+2*pad_x,height+2*pad_y, buf_x,buf_y);
491 XSetClipOrigin(display,clip_gc[PIX_TOONS],
492 buf_x-src_x+pad_x,buf_y-src_y+pad_y);
493 XCopyArea(display,pix[PIX_TOONS],pix[PIX_DB_DOOR],clip_gc[PIX_TOONS],
494 src_x,src_y, width,height, buf_x+pad_x,buf_y+pad_y);
495 XCopyArea(display,pix[PIX_DB_DOOR],window,gc, buf_x,buf_y,
496 width+2*pad_x,height+2*pad_y, dest_x-pad_x,dest_y-pad_y);