1 /*
2 Copyright notice:
3 
4 This is mine.  I'm only letting you use it.  Period.  Feel free to rip off
5 any of the code you see fit, but have the courtesy to give me credit.
6 Otherwise great hairy beasties will rip your eyes out and eat your flesh
7 when you least expect it.
8 
9 Jonny Goldman <jonathan@think.com>
10 
11 Wed May  8 1991
12 */
13 
14 /* vaders.c - handle movement, etc. of the vaders. */
15 
16 #ifdef HAVE_CONFIG_H
17 #include <config.h>
18 #endif
19 
20 #include "vaders.h"
21 
22 #define NUMTYPES	3	/* How many types of vaders there are. */
23 #define NUMROWS		5	/* number of rows of vaders */
24 #define NUMVADERS	11	/* Maximum of vaders of each type. */
25 #define BASEY 10
26 #define VADERWIDTH	(14*scale)
27 #define VADERHEIGHT	(12*scale)
28 #define VADERYINC	(8*scale)
29 
30 static XImage *Vader_Image[NUMTYPES][2];	/* XImages for the vaders. */
31 
32 extern int basex;		/* Base location */
33 
34 static int tick = 0;
35 static int vaderwaitinit;
36 
37 typedef struct _VaderRec {
38   int x, y;			/* Location. */
39   int vx, vy;			/* Velocity. */
40   int width, height;		/* size of this Vader. */
41   GC gc;			/* graphics context */
42   XImage *shape_image[2];
43   int value;
44   Boolean alive;
45   Boolean exploded;
46 } VaderRec, *Vader;
47 
48 VaderRec vaders[NUMROWS][NUMVADERS];
49 
50 int numvaders = 0;		/* Number of vaders existing. */
51 
52 
53 typedef struct _BaseRec {
54   int x;			/* Location. */
55   int v;			/* velocity */
56   int width, height;		/* box of this base. */
57   XImage *shape_image;		/* an XImage for the spaceship */
58 } BaseRec, *Base;
59 
60 extern Base base;
61 
62 XImage *Explode_image;
63 
64 /* indicates pad around vader bitmap for better collision detection */
65 #define VADERPAD 	scale
66 
67 #define PointInVader(vader, x, y)	\
68   (x >= (vader)->x+VADERPAD && y >= (vader)->y &&		\
69    x <= (vader)->x + (vader)->width-VADERPAD  && y <= (vader)->y + (vader)->height)
70 
PaintVader(vader,gc)71 static void PaintVader(vader, gc)
72      Vader vader;
73      GC gc;
74 {
75   int rx, ry, w, h;
76 
77   w = vader->width;
78   h = vader->height;
79 
80   rx = vader->x;
81   ry = vader->y;
82 
83   XPutImage(dpy, gamewindow, gc, vader->shape_image[tick],
84 	    0, 0, rx, ry, w, h);
85 }
86 
PaintExplodedVader(vader,gc)87 static void PaintExplodedVader(vader, gc)
88      Vader vader;
89      GC gc;
90 {
91   int rx, ry, w, h;
92 
93   w = Explode_image->width;
94   h = Explode_image->height;
95 
96   rx = vader->x;
97   ry = vader->y;
98 
99   XPutImage(dpy, gamewindow, gc, Explode_image,
100 	    0, 0, rx, ry, w, h);
101 }
102 
DestroyVader(vader)103 static void DestroyVader(vader)
104 Vader vader;
105 {
106   PaintVader(vader, backgc);
107   score += vader->value;
108   PaintScore();
109   numvaders--;
110   switch (numvaders) {
111   case 32:
112   case 16:
113   case 8:
114   case 4:
115   case 2:
116   case 1:
117     vaderwait /= 2; break;
118   }
119   vader->alive = FALSE;
120   vader->exploded = TRUE;
121   PaintExplodedVader(vader, vader->gc);
122 }
123 
124 
125 
ShotHitsVader(x,y)126 Boolean ShotHitsVader(x, y)
127      int x, y;
128 {
129   register Vader vader;
130   int i, j;
131 
132   for(j = 0; j < NUMROWS; j++)
133     for (i=0 ; i<NUMVADERS ; i++) {
134       vader = &vaders[j][i];
135       if(vader->alive && PointInVader(vader, x, y)) {
136 	DestroyVader(vader);
137 	return TRUE;
138     }
139   }
140   return FALSE;
141 }
142 
143 
144 
PaintAllVaders()145 void PaintAllVaders()
146 {
147   int i, j;
148   Vader vader;
149 
150   for(j = 0; j < NUMROWS; j++)
151     for (i=0 ; i< NUMVADERS ; i++) {
152       vader = &vaders[j][i];
153       if(vader->alive) PaintVader(vader, vader->gc);
154     }
155 }
156 
157 /* add some random shot */
158 
SFire()159 void SFire()
160 {
161   register Vader vader;
162   int i, j, c;
163 
164   for(j = 0, c = random()%NUMVADERS; j < NUMVADERS; j++) {
165     for (i= NUMROWS-1; i>=0; i--) {
166       vader = &vaders[i][(c+j)%NUMVADERS];
167       if(vader->alive) {
168 	AddVshot(vader->x+vader->width/2, vader->y+vader->height);
169 	return;
170       }
171     }
172   }
173 }
174 
VaderBoop(tick)175 void VaderBoop(tick)
176 int tick;
177 {
178   XKeyboardControl vals;
179 
180   vals.bell_duration = vaderwait/2;
181   vals.bell_pitch = tick ? 60 : 40;
182 
183   XChangeKeyboardControl(dpy, KBBellPitch | KBBellDuration, &vals);
184   XBell(dpy, 100);
185 }
186 
187 static int createvaderp = FALSE;
188 
189 /*ARGSUSED*/
MoveVaders(closure,id)190 void MoveVaders(closure, id)
191      Opaque closure;
192      XtIntervalId id;
193 {
194   register Vader vader;
195   register int i, j;
196   Boolean reversep;
197 
198   reversep = FALSE;
199 
200   if (closure != (Opaque) MoveVaders) return;
201   if (createvaderp) {
202     createvaderp = FALSE;
203     CreateVaders(level);
204   }
205   if (numvaders == 0 && numvshots == 0) {
206     vadertimerid = XtAddTimeOut(2000, MoveVaders, (Opaque) MoveVaders);
207     level++;
208     createvaderp = TRUE;
209     InitBuildings();
210     DrawBuildings();
211   } else {
212     vadertimerid = XtAddTimeOut(vaderwait, MoveVaders, (Opaque) MoveVaders);
213     /* this is the way to do it, but on the Sun it SUCKS!
214     VaderBoop(tick);
215     */
216     if((random()%1000)>900) SFire();
217     for(j = 0; j < NUMROWS; j++)
218       for (i=0 ; i< NUMVADERS ; i++) {
219 	vader = &vaders[j][i];
220 	if (vader->exploded) {
221 	  PaintExplodedVader(vader, backgc);
222 	  vader->exploded = FALSE;
223 	}
224 	else if (vader->alive) {
225 	  if (vader->vx > 0)
226 	    (void)ShotHitsBuilding(vader->x+vader->width, vader->y+vader->height);
227 	  else
228 	    (void)ShotHitsBuilding(vader->x, vader->y+vader->height);
229 	  vader->x += vader->vx;
230 	  if ((vader->x < (VADERWIDTH-vader->width)/2 && vader->vx < 0) ||
231 	      (vader->x > gamewidth-VADERWIDTH && vader->vx > 0))
232 	    reversep = TRUE;
233 	  tick = tick ? 0 : 1;
234 	  PaintVader(vader, vader->gc);
235 	  tick = tick ? 0 : 1;
236 	}
237       }
238     tick = tick ? 0 : 1;
239     if (reversep) {
240       for(j = 0; j < NUMROWS; j++)
241 	for (i=0 ; i< NUMVADERS ; i++) {
242 	  vader = &vaders[j][i];
243 	  if (vader->alive) {
244 	    PaintVader(vader, backgc);
245 	    vader->vx = -vader->vx;
246 	    vader->y = vader->y + VADERYINC;
247 	    PaintVader(vader, vader->gc);
248 	    if(vader->y >= gameheight-base->height+vader->height) {
249 	      ResetGame();
250 	      return;
251 	    }
252 	  }
253 	}
254     }
255   }
256 }
257 
258 #include "vader1a1.bit"
259 #include "vader1b1.bit"
260 #include "vader1a2.bit"
261 #include "vader1b2.bit"
262 #include "vader2a1.bit"
263 #include "vader2b1.bit"
264 #include "vader2a2.bit"
265 #include "vader2b2.bit"
266 #include "vader3a1.bit"
267 #include "vader3b1.bit"
268 #include "vader3a2.bit"
269 #include "vader3b2.bit"
270 #include "vexplod1.bit"
271 #include "vexplod2.bit"
272 
ReadVaderImages()273 int ReadVaderImages()
274 {
275   if (scale == 1) {
276     Vader_Image[0][0] = XCreateImage(dpy,
277 				     DefaultVisual(dpy, DefaultScreen(dpy)),
278 				     1,
279 				     XYBitmap,
280 				     0,
281 				     vader1a1_bits,
282 				     vader1a1_width, vader1a1_height,
283 				     8, 0);
284     Vader_Image[0][0]->bitmap_bit_order = LSBFirst;
285     Vader_Image[0][0]->byte_order = LSBFirst;
286 
287     Vader_Image[0][1] = XCreateImage(dpy,
288 				     DefaultVisual(dpy, DefaultScreen(dpy)),
289 				     1,
290 				     XYBitmap,
291 				     0,
292 				     vader1b1_bits,
293 				     vader1b1_width, vader1b1_height,
294 				     8, 0);
295     Vader_Image[0][1]->bitmap_bit_order = LSBFirst;
296     Vader_Image[0][1]->byte_order = LSBFirst;
297 
298     Vader_Image[1][0] = XCreateImage(dpy,
299 				     DefaultVisual(dpy, DefaultScreen(dpy)),
300 				     1,
301 				     XYBitmap,
302 				     0,
303 				     vader2a1_bits,
304 				     vader2a1_width, vader2a1_height,
305 				     8, 0);
306     Vader_Image[1][0]->bitmap_bit_order = LSBFirst;
307     Vader_Image[1][0]->byte_order = LSBFirst;
308 
309     Vader_Image[1][1] = XCreateImage(dpy,
310 				     DefaultVisual(dpy, DefaultScreen(dpy)),
311 				     1,
312 				     XYBitmap,
313 				     0,
314 				     vader2b1_bits,
315 				     vader2b1_width, vader2b1_height,
316 				     8, 0);
317     Vader_Image[1][1]->bitmap_bit_order = LSBFirst;
318     Vader_Image[1][1]->byte_order = LSBFirst;
319 
320     Vader_Image[2][0] = XCreateImage(dpy,
321 				     DefaultVisual(dpy, DefaultScreen(dpy)),
322 				     1,
323 				     XYBitmap,
324 				     0,
325 				     vader3a1_bits,
326 				     vader3a1_width, vader3a1_height,
327 				     8, 0);
328     Vader_Image[2][0]->bitmap_bit_order = LSBFirst;
329     Vader_Image[2][0]->byte_order = LSBFirst;
330 
331     Vader_Image[2][1] = XCreateImage(dpy,
332 				     DefaultVisual(dpy, DefaultScreen(dpy)),
333 				     1,
334 				     XYBitmap,
335 				     0,
336 				     vader3b1_bits,
337 				     vader3b1_width, vader3b1_height,
338 				     8, 0);
339     Vader_Image[2][1]->bitmap_bit_order = LSBFirst;
340     Vader_Image[2][1]->byte_order = LSBFirst;
341 
342     Explode_image = XCreateImage(dpy,
343 				 DefaultVisual(dpy, DefaultScreen(dpy)),
344 				 1,
345 				 XYBitmap,
346 				 0,
347 				 vexplode1_bits,
348 				 vexplode1_width, vexplode1_height,
349 				 8, 0);
350 
351     Explode_image->bitmap_bit_order = LSBFirst;
352     Explode_image->byte_order = LSBFirst;
353   }
354   else {
355     Vader_Image[0][0] = XCreateImage(dpy,
356 				     DefaultVisual(dpy, DefaultScreen(dpy)),
357 				     1,
358 				     XYBitmap,
359 				     0,
360 				     vader1a2_bits,
361 				     vader1a2_width, vader1a2_height,
362 				     8, 0);
363     Vader_Image[0][0]->bitmap_bit_order = LSBFirst;
364     Vader_Image[0][0]->byte_order = LSBFirst;
365 
366     Vader_Image[0][1] = XCreateImage(dpy,
367 				     DefaultVisual(dpy, DefaultScreen(dpy)),
368 				     1,
369 				     XYBitmap,
370 				     0,
371 				     vader1b2_bits,
372 				     vader1b2_width, vader1b2_height,
373 				     8, 0);
374     Vader_Image[0][1]->bitmap_bit_order = LSBFirst;
375     Vader_Image[0][1]->byte_order = LSBFirst;
376 
377     Vader_Image[1][0] = XCreateImage(dpy,
378 				     DefaultVisual(dpy, DefaultScreen(dpy)),
379 				     1,
380 				     XYBitmap,
381 				     0,
382 				     vader2a2_bits,
383 				     vader2a2_width, vader2a2_height,
384 				     8, 0);
385     Vader_Image[1][0]->bitmap_bit_order = LSBFirst;
386     Vader_Image[1][0]->byte_order = LSBFirst;
387 
388     Vader_Image[1][1] = XCreateImage(dpy,
389 				     DefaultVisual(dpy, DefaultScreen(dpy)),
390 				     1,
391 				     XYBitmap,
392 				     0,
393 				     vader2b2_bits,
394 				     vader2b2_width, vader2b2_height,
395 				     8, 0);
396     Vader_Image[1][1]->bitmap_bit_order = LSBFirst;
397     Vader_Image[1][1]->byte_order = LSBFirst;
398 
399     Vader_Image[2][0] = XCreateImage(dpy,
400 				     DefaultVisual(dpy, DefaultScreen(dpy)),
401 				     1,
402 				     XYBitmap,
403 				     0,
404 				     vader3a2_bits,
405 				     vader3a2_width, vader3a2_height,
406 				     8, 0);
407     Vader_Image[2][0]->bitmap_bit_order = LSBFirst;
408     Vader_Image[2][0]->byte_order = LSBFirst;
409 
410     Vader_Image[2][1] = XCreateImage(dpy,
411 				     DefaultVisual(dpy, DefaultScreen(dpy)),
412 				     1,
413 				     XYBitmap,
414 				     0,
415 				     vader3b2_bits,
416 				     vader3b2_width, vader3b2_height,
417 				     8, 0);
418     Vader_Image[2][1]->bitmap_bit_order = LSBFirst;
419     Vader_Image[2][1]->byte_order = LSBFirst;
420 
421     Explode_image = XCreateImage(dpy,
422 				 DefaultVisual(dpy, DefaultScreen(dpy)),
423 				 1,
424 				 XYBitmap,
425 				 0,
426 				 vexplode2_bits,
427 				 vexplode2_width, vexplode2_height,
428 				 8, 0);
429 
430     Explode_image->bitmap_bit_order = LSBFirst;
431     Explode_image->byte_order = LSBFirst;
432   }
433 
434   return BitmapSuccess;
435 }
436 
437 
CreateVaders(level)438 void CreateVaders(level)
439 int level;
440 {
441   int offset, i, j;
442   Vader vader;
443 
444   offset = MIN(level, 8);
445   vaderwait = vaderwaitinit;
446   numvaders = NUMROWS*NUMVADERS;
447   for (j = 0; j < NUMROWS; j++)
448     for (i = 0; i < NUMVADERS; i++) {
449       vader = &vaders[j][i];
450       vader->x = 3 + VADERWIDTH*i+(VADERWIDTH-vader->width)/2;
451       vader->y = VADERHEIGHT*(offset+j);
452       vader->vx = scale;
453       vader->alive = TRUE;
454       vader->exploded = FALSE;
455     }
456 }
457 
InitVaders()458 void InitVaders()
459 {
460   int i, j, k, width, height;
461   Vader vader;
462 
463   level = 1;
464   if (ReadVaderImages() != BitmapSuccess) {
465     fprintf(stderr, _("Error reading Invader images\n"));
466     exit(10);
467   }
468 
469   for (j = 0; j < NUMROWS; j++) {
470     switch (j) {
471     case 0:
472       k = 0; break;
473     case 1:
474     case 2:
475       k = 1; break;
476     case 3:
477     case 4:
478       k = 2; break;
479     }
480     width = Vader_Image[k][0]->width;
481     height = Vader_Image[k][0]->height;
482     for (i = 0; i < NUMVADERS; i++) {
483       vader = &vaders[j][i];
484       vader->shape_image[0] = Vader_Image[k][0];
485       vader->shape_image[1] = Vader_Image[k][1];
486       vader->gc = vadergc[k];
487       vader->width = width;
488       vader->height = height;
489       vader->value = 10*(3-k);
490     }
491   }
492   vaderwaitinit = vaderwait;
493   CreateVaders(level);
494   vadertimerid = 0;
495 }
496