rocks_n_diamonds-0.9
[rocksndiamonds.git] / src / misc.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  ©1995 Artsoft Development                               *
5 *        Holger Schemel                                    *
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 *----------------------------------------------------------*
12 *  misc.c                                                  *
13 *                                                          *
14 *  Letzte Aenderung: 15.06.1995                            *
15 ***********************************************************/
16
17 #include "misc.h"
18 #include "tools.h"
19 #include "sound.h"
20 #include <pwd.h>
21 #include <unistd.h>
22 #include <time.h>
23 #include <sys/time.h>
24 #include <sys/param.h>
25 #include <sys/types.h>
26
27 void microsleep(unsigned long usec)
28 {
29   struct timeval delay;
30
31   delay.tv_sec  = usec / 1000000;
32   delay.tv_usec = usec % 1000000;
33
34   if (select(0,NULL,NULL,NULL,&delay)!=0)
35     fprintf(stderr,"%s: in function microsleep: select failed!\n",
36             progname);
37 }
38
39 unsigned long be2long(unsigned long *be)        /* big-endian -> longword */
40 {
41   unsigned char *ptr = (unsigned char *)be;
42
43   return(ptr[0]<<24 | ptr[1]<<16 | ptr[2]<<8 | ptr[3]);
44 }
45
46 char *int2str(int ct, int nr)
47 {
48   static char str[20];
49
50   sprintf(str,"%09d",ct);
51   return(&str[strlen(str)-nr]);
52 }
53
54 unsigned int RND(unsigned int max)
55 {
56   return(rand() % max);
57 }
58
59 unsigned int InitRND(long seed)
60 {
61   struct timeval current_time;
62
63   if (seed==NEW_RANDOMIZE)
64   {
65     gettimeofday(&current_time,NULL);
66     srand((unsigned int) current_time.tv_usec);
67     return((unsigned int) current_time.tv_usec);
68   }
69   else
70   {
71     srand((unsigned int) seed);
72     return((unsigned int) seed);
73   }
74 }
75
76 char *GetLoginName()
77 {
78   struct passwd *pwd;
79
80   if (!(pwd=getpwuid(getuid())))
81     return("ANONYMOUS");
82   else
83     return(pwd->pw_name);
84 }
85
86 static struct AnimInfo toon[NUM_TOONS] =
87 {
88   DWARF_XSIZE, DWARF_YSIZE,
89   DWARF_X, DWARF_Y,
90   DWARF_FRAMES,
91   DWARF_FPS,
92   DWARF_STEPSIZE,
93   FALSE,
94   ANIMDIR_RIGHT,
95   ANIMPOS_DOWN,
96
97   DWARF_XSIZE, DWARF_YSIZE,
98   DWARF_X, DWARF2_Y,
99   DWARF_FRAMES,
100   DWARF_FPS,
101   DWARF_STEPSIZE,
102   FALSE,
103   ANIMDIR_LEFT,
104   ANIMPOS_DOWN,
105
106   JUMPER_XSIZE, JUMPER_YSIZE,
107   JUMPER_X, JUMPER_Y,
108   JUMPER_FRAMES,
109   JUMPER_FPS,
110   JUMPER_STEPSIZE,
111   FALSE,
112   ANIMDIR_LEFT,
113   ANIMPOS_DOWN,
114
115   CLOWN_XSIZE, CLOWN_YSIZE,
116   CLOWN_X, CLOWN_Y,
117   CLOWN_FRAMES,
118   CLOWN_FPS,
119   CLOWN_STEPSIZE,
120   FALSE,
121   ANIMDIR_UP,
122   ANIMPOS_ANY,
123
124   BIRD_XSIZE, BIRD_YSIZE,
125   BIRD1_X, BIRD1_Y,
126   BIRD_FRAMES,
127   BIRD_FPS,
128   BIRD_STEPSIZE,
129   TRUE,
130   ANIMDIR_RIGHT,
131   ANIMPOS_UPPER,
132
133   BIRD_XSIZE, BIRD_YSIZE,
134   BIRD2_X, BIRD2_Y,
135   BIRD_FRAMES,
136   BIRD_FPS,
137   BIRD_STEPSIZE,
138   TRUE,
139   ANIMDIR_LEFT,
140   ANIMPOS_UPPER
141 };
142
143 void InitAnimation()
144 {
145   HandleAnimation(ANIM_START);
146 }
147
148 void StopAnimation()
149 {
150   HandleAnimation(ANIM_STOP);
151 }
152
153 void DoAnimation()
154 {
155   HandleAnimation(ANIM_CONTINUE);
156 }
157
158 void HandleAnimation(int mode)
159 {
160   static long animstart_delay = -1;
161   static long animstart_delay_value = 0;
162   static BOOL anim_restart = TRUE;
163   static BOOL reset_delay = TRUE;
164   static int toon_nr = 0;
165
166   if (!toons_on || game_status==PLAYING)
167     return;
168
169   switch(mode)
170   {
171     case ANIM_START:
172       anim_restart = TRUE;
173       reset_delay = TRUE;
174       return;
175       break;
176     case ANIM_CONTINUE:
177       break;
178     case ANIM_STOP:
179       redraw_mask |= REDRAW_FIELD;
180       BackToFront();
181       return;
182       break;
183     default:
184       break;
185   }
186
187   if (reset_delay)
188   {
189     animstart_delay = Counter();
190     animstart_delay_value = RND(500);
191     reset_delay = FALSE;
192   }
193
194   if (anim_restart)
195   {
196     if (!DelayReached(&animstart_delay,animstart_delay_value))
197       return;
198
199     toon_nr = RND(NUM_TOONS);
200   }
201
202   anim_restart = reset_delay = AnimateToon(toon_nr,anim_restart);
203 }
204
205 BOOL AnimateToon(int toon_nr, BOOL restart)
206 {
207   static pos_x = 0, pos_y = 0;
208   static delta_x = 0, delta_y = 0;
209   static int frame = 0, frame_step = 1;
210   static BOOL horiz_move, vert_move;
211   static long anim_delay = 0;
212   static int anim_delay_value = 0;
213   struct AnimInfo *anim = &toon[toon_nr];
214   static int width,height;
215   static int pad_x,pad_y;
216   static int cut_x,cut_y;
217   static int src_x, src_y;
218   static int dest_x, dest_y;
219
220   if (restart)
221   {
222     horiz_move = (anim->direction & (ANIMDIR_LEFT | ANIMDIR_RIGHT));
223     vert_move = (anim->direction & (ANIMDIR_UP | ANIMDIR_DOWN));
224     anim_delay_value = 100/anim->frames_per_second;
225     frame = 0;
226
227     if (horiz_move)
228     {
229       if (anim->position==ANIMPOS_UP)
230         pos_y = 0;
231       else if (anim->position==ANIMPOS_DOWN)
232         pos_y = FULL_SYSIZE-anim->height;
233       else if (anim->position==ANIMPOS_UPPER)
234         pos_y = RND((FULL_SYSIZE-anim->height)/2);
235       else
236         pos_y = RND(FULL_SYSIZE-anim->height);
237
238       if (anim->direction==ANIMDIR_RIGHT)
239       {
240         delta_x = anim->stepsize;
241         pos_x = -anim->width+delta_x;
242       }
243       else
244       {
245         delta_x = -anim->stepsize;
246         pos_x = FULL_SXSIZE+delta_x;
247       }
248       delta_y = 0;
249     }
250     else
251     {
252       if (anim->position==ANIMPOS_LEFT)
253         pos_x = 0;
254       else if (anim->position==ANIMPOS_RIGHT)
255         pos_x = FULL_SXSIZE-anim->width;
256       else
257         pos_x = RND(FULL_SXSIZE-anim->width);
258
259       if (anim->direction==ANIMDIR_DOWN)
260       {
261         delta_y = anim->stepsize;
262         pos_y = -anim->height+delta_y;
263       }
264       else
265       {
266         delta_y = -anim->stepsize;
267         pos_y = FULL_SYSIZE+delta_y;
268       }
269       delta_x = 0;
270     }
271   }
272
273   if (pos_x <= -anim->width  - anim->stepsize ||
274       pos_x >=  FULL_SXSIZE  + anim->stepsize ||
275       pos_y <= -anim->height - anim->stepsize ||
276       pos_y >=  FULL_SYSIZE  + anim->stepsize)
277     return(TRUE);
278
279   if (!DelayReached(&anim_delay,anim_delay_value))
280   {
281     if (game_status==HELPSCREEN && !restart)
282       DrawAnim(src_x+cut_x,src_y+cut_y, width,height,
283                REAL_SX+dest_x,REAL_SY+dest_y, pad_x,pad_y);
284
285     return(FALSE);
286   }
287
288   if (pos_x<-anim->width)
289     pos_x = -anim->width;
290   else if (pos_x>FULL_SXSIZE)
291     pos_x = FULL_SXSIZE;
292   if (pos_y<-anim->height)
293     pos_y = -anim->height;
294   else if (pos_y>FULL_SYSIZE)
295     pos_y = FULL_SYSIZE;
296
297   pad_x = (horiz_move ? anim->stepsize : 0);
298   pad_y = (vert_move  ? anim->stepsize : 0);
299   src_x = anim->src_x + frame * anim->width;
300   src_y = anim->src_y;
301   dest_x = pos_x;
302   dest_y = pos_y;
303   cut_x = cut_y = 0;
304   width  = anim->width;
305   height = anim->height;
306
307   if (pos_x<0)
308   {
309     dest_x = 0;
310     width += pos_x;
311     cut_x = -pos_x;
312   }
313   else if (pos_x>FULL_SXSIZE-anim->width)
314     width -= (pos_x - (FULL_SXSIZE-anim->width));
315
316   if (pos_y<0)
317   {
318     dest_y = 0;
319     height += pos_y;
320     cut_y = -pos_y;
321   }
322   else if (pos_y>FULL_SYSIZE-anim->height)
323     height -= (pos_y - (FULL_SYSIZE-anim->height));
324
325   DrawAnim(src_x+cut_x,src_y+cut_y, width,height,
326            REAL_SX+dest_x,REAL_SY+dest_y, pad_x,pad_y);
327
328   pos_x += delta_x;
329   pos_y += delta_y;
330   frame += frame_step;
331
332   if (frame<0 || frame>=anim->frames)
333   {
334     if (anim->pingpong)
335     {
336       frame_step *= -1;
337       frame = (frame<0 ? 1 : anim->frames-2);
338     }
339     else
340       frame = (frame<0 ? anim->frames-1 : 0);
341   }
342
343   return(FALSE);
344 }
345
346 void DrawAnim(int src_x, int src_y, int width, int height,
347               int dest_x, int dest_y, int pad_x, int pad_y)
348 {
349   int buf_x = DOOR_GFX_PAGEX3, buf_y = DOOR_GFX_PAGEY1;
350
351   XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,dest_x-pad_x,dest_y-pad_y,
352             width+2*pad_x,height+2*pad_y, buf_x,buf_y);
353   XSetClipOrigin(display,clip_gc[PIX_TOONS],dest_x-src_x,dest_y-src_y);
354   XCopyArea(display,pix[PIX_TOONS],backbuffer,clip_gc[PIX_TOONS],
355             src_x,src_y, width,height, dest_x,dest_y);
356   XCopyArea(display,backbuffer,window,gc, dest_x-pad_x,dest_y-pad_y,
357             width+2*pad_x,height+2*pad_y, dest_x-pad_x,dest_y-pad_y);
358
359   BackToFront();
360
361   XCopyArea(display,pix[PIX_DB_DOOR],backbuffer,gc, buf_x,buf_y,
362             width+2*pad_x,height+2*pad_y, dest_x-pad_x,dest_y-pad_y);
363
364 /*
365   XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,dest_x-pad_x,dest_y-pad_y,
366             width+2*pad_x,height+2*pad_y, buf_x,buf_y);
367   XSetClipOrigin(display,clip_gc[PIX_TOONS],
368                  buf_x-src_x+pad_x,buf_y-src_y+pad_y);
369   XCopyArea(display,pix[PIX_TOONS],pix[PIX_DB_DOOR],clip_gc[PIX_TOONS],
370             src_x,src_y, width,height, buf_x+pad_x,buf_y+pad_y);
371   XCopyArea(display,pix[PIX_DB_DOOR],window,gc, buf_x,buf_y,
372             width+2*pad_x,height+2*pad_y, dest_x-pad_x,dest_y-pad_y);
373 */
374
375   XFlush(display);
376 }