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