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 /* base.c - handle movement, etc. of the base. */
15 
16 #ifdef HAVE_CONFIG_H
17 #include <config.h>
18 #endif
19 
20 #include "vaders.h"
21 
22 extern int paused;
23 Boolean basedestroyed;
24 
25 static Boolean showingexplosion = FALSE;
26 
27 void DrawBuildings();
28 
29 #define BASEY (gameheight-base->height)
30 
31 typedef struct _BaseRec {
32   int x;			/* Location. */
33   int v;			/* velocity */
34   int width, height;		/* box of this base. */
35   XImage *shape_image;		/* an XImage for the spaceship */
36 } BaseRec, *Base;
37 
38 BaseRec baserec;
39 
40 Base base = &baserec;
41 
42 XImage *explosion;
43 
44 #define BaseNearPoint(base, x, y)	\
45   ((base)->x <= (x) && (x) < (base)->x + (base)->width  && \
46    y <= BASEY + (base)->height && y > BASEY)
47 
48 #include "base1.bit"
49 #include "base2.bit"
50 #include "explode1.bit"
51 #include "explode2.bit"
52 
ReadBaseImage()53 int ReadBaseImage()
54 {
55 /*
56   unsigned int width, height;
57   int x_hot, y_hot;
58   char *data, filename[255];
59   int status;
60 */
61 
62   base->width = (scale == 1) ? base1_width : base2_width;
63   base->height = (scale == 1) ? base1_height : base2_height;
64 
65   base->shape_image = XCreateImage(dpy,
66 				   DefaultVisual(dpy, DefaultScreen(dpy)),
67 				   1,
68 				   XYBitmap,
69 				   0,
70 				   (scale == 1) ? base1_bits : base2_bits,
71 				   base->width, base->height,
72 				   8, 0);
73 
74   base->shape_image->bitmap_bit_order = LSBFirst;
75   base->shape_image->byte_order = LSBFirst;
76 
77   explosion = XCreateImage(dpy,
78 			   DefaultVisual(dpy, DefaultScreen(dpy)),
79 			   1,
80 			   XYBitmap,
81 			   0,
82 			   (scale == 1) ? explode1_bits : explode2_bits,
83 			   (scale == 1) ? explode1_width : explode2_width,
84 			   (scale == 1) ? explode1_height : explode2_height,
85 			   8, 0);
86   explosion->bitmap_bit_order = LSBFirst;
87   explosion->byte_order = LSBFirst;
88 
89   return BitmapSuccess;
90 }
91 
InitBase()92 void InitBase()
93 {
94     if( ReadBaseImage() != BitmapSuccess) {
95       fprintf(stderr, "Error reading base image.\n");
96       exit(20);
97     }
98     basedestroyed = TRUE;
99     showingexplosion = FALSE;
100     basetimerid = 0;
101     base->v = 0;
102 }
103 
104 
105 
PaintBase(GC gc)106 void PaintBase(GC gc)
107 {
108   XPutImage(dpy, gamewindow, gc, base->shape_image,
109 	    0, 0, base->x, gameheight-base->height, base->width, base->height);
110 }
111 
112 
ShowBase(int i,GC gc)113 void ShowBase(int i, GC gc)
114 {
115   XPutImage(dpy, labelwindow, gc, base->shape_image,
116 	    0, 0, i*(base->width+2), gameheight/2-(3*base->height),
117 	    base->width, base->height);
118 }
119 
PaintBasesLeft()120 void PaintBasesLeft()
121 {
122   int i;
123   XDrawString(dpy, labelwindow, scoregc,
124 	      0, gameheight-(4*base->height),
125 	      "Bases", 5);
126   for(i = 0; i < basesleft; i++) {
127     ShowBase(i, basegc);
128   }
129 }
130 
131 
ShowExplosion(gc)132 void ShowExplosion(gc)
133 GC gc;
134 {
135   XPutImage(dpy, gamewindow, gc, explosion,
136 	      0, 0, base->x, gameheight-base->height, explosion->width, explosion->height);
137 }
138 
DestroyBase()139 void DestroyBase()
140 {
141   if(!paused) {
142     PaintBase(backgc);
143     basedestroyed = TRUE;
144     showingexplosion = TRUE;
145     ShowExplosion(basegc);
146     if (basetimerid) XtRemoveTimeOut(basetimerid);
147     basetimerid = XtAddTimeOut(1000, MoveBase, (Opaque) MoveBase);
148   }
149 }
150 
151 
ShotHitsBase(x,y)152 Boolean ShotHitsBase(x,y)
153 int x,y;
154 {
155   if(!basedestroyed && BaseNearPoint(base, x, y)) {
156     DestroyBase();
157     return TRUE;
158   }
159   return FALSE;
160 }
161 
ResetGame()162 void ResetGame()
163 {
164   static Arg args[1];
165 
166   spacer_shown = 0;
167   SuspendTimers();
168   XClearWindow(dpy, gamewindow);
169   paused = 1;
170   InitScore();
171   basesleft--;
172   level = 1;
173   CreateVaders(level);
174   spacer_counter = 1000;
175   numshots = 0;
176   numvshots = 0;
177   PaintAllVaders();
178   PaintBasesLeft();
179   InitBuildings();
180   DrawBuildings();
181   lastscore = 0;
182   PaintScore();
183   XSync(dpy, 0);
184   basedestroyed = FALSE;
185   base->x = base->v = 0;
186   showingexplosion = FALSE;
187   PaintBase(basegc);
188   XtSetArg(args[0], XtNlabel, _(" Start"));
189   XtSetValues(pausebutton, args, 1);
190 }
191 
192 /*ARGSUSED*/
MoveBase(closure,id)193 void MoveBase(closure, id)
194 Opaque closure;
195 XtIntervalId id;
196 {
197   if (closure != (Opaque) MoveBase) return;
198   if(!paused) {
199     if (basedestroyed) {
200       if (showingexplosion) {
201 	ShowExplosion(backgc);
202 	showingexplosion = FALSE;
203 	basetimerid = XtAddTimeOut(2000, MoveBase, (Opaque) MoveBase);
204 	return;
205       }
206       if (basesleft <= 0) {
207 	ResetGame();
208 	return;
209       }
210       base->x = 0;
211       basesleft--;
212       ShowBase(basesleft, backgc);
213       PaintBase(basegc);
214       PaintScore();
215       basedestroyed = FALSE;
216       base->v = 0;
217     }
218 
219     if (!paused)
220       basetimerid = XtAddTimeOut(basewait, MoveBase, (Opaque) MoveBase);
221     if(base->v) {
222       PaintBase(backgc);
223       base->x += base->v;
224       base->x = (base->x < 0) ? 0 :
225       ((base->x > gamewidth-base->width) ? gamewidth-base->width : base->x);
226       PaintBase(basegc);
227     }
228   }
229 }
230 
MoveLeft()231 void MoveLeft()
232 {
233   if(!paused) base->v= -scale;
234 }
235 
236 
MoveRight()237 void MoveRight()
238 {
239   if(!paused) base->v = scale;
240 }
241 
242 
Stop()243 void Stop()
244 {
245   if(!paused)
246     base->v = 0;
247 }
248 
249 
Fire()250 void Fire()
251 {
252     if (!basedestroyed&&!paused) AddShot(base->x+base->width/2, gameheight-base->height);
253 }
254 
255 /* this part is for the buildings */
256 
257 #define NUMBUILDINGS 4
258 #define HUNKROWS 4
259 #define NUMHUNKS 10
260 #define HUNKWIDTH (2*scale)
261 #define HUNKHEIGHT (4*scale)
262 #define buildingwidth HUNKWIDTH*NUMHUNKS
263 #define buildingheight HUNKHEIGHT*HUNKROWS
264 
265 typedef struct {
266   int x,y;
267   Boolean hunks[HUNKROWS][NUMHUNKS];
268 } BuildingRec, *Building;
269 
270 BuildingRec buildings[NUMBUILDINGS];
271 
272 
DrawBuildingHunk(building,r,c,gc)273 void DrawBuildingHunk(building, r, c, gc)
274 Building building;
275 int r,c;
276 GC gc;
277 {
278   int x, y;
279 
280   x = building->x+c*HUNKWIDTH;
281   y = gameheight-scale*45+r*HUNKHEIGHT;
282 
283   XFillRectangle(dpy, gamewindow, gc, x, y, HUNKWIDTH, HUNKHEIGHT);
284 }
285 
ToastHunk(building,r,c)286 void ToastHunk(building,r,c)
287 Building building;
288 int r,c;
289 {
290   building->hunks[r][c] = FALSE;
291   DrawBuildingHunk(building, r, c, backgc);
292 }
293 
ShotHitsBuilding(x,y)294 Boolean ShotHitsBuilding(x, y)
295 int x,y;
296 {
297   int i, r, c;
298   Building building;
299 
300   for(i=0; i< NUMBUILDINGS; i++) {
301     building = &buildings[i];
302     if(x>=building->x && x<building->x+buildingwidth &&
303        y>=gameheight-scale*45 && y<gameheight-scale*45+buildingheight) {
304       r = (y-(gameheight-scale*45))/HUNKHEIGHT;
305       c = (x-building->x)/HUNKWIDTH;
306       if (r<0 || r>=HUNKROWS)
307 	printf(_("Error in row"));
308       if (c<0 || c>=NUMHUNKS)
309 	printf(_("Error in column"));
310       if(building->hunks[r][c]) {
311 	ToastHunk(building, r,c);
312 	return TRUE;
313       }
314       return FALSE;
315     }
316   }
317   return FALSE;
318 }
319 
InitBuildings()320 void InitBuildings()
321 {
322   int i, j, k;
323 
324   for(i=0; i< NUMBUILDINGS; i++) {
325     buildings[i].x = i*((gamewidth ?
326 			 (scale*(VWIDTH-70)) :
327 			 (gamewidth-scale*70)))/4+scale*35+(HUNKWIDTH*NUMHUNKS)/2;
328     for (j=0; j<HUNKROWS; j++)
329       for (k = 0; k < NUMHUNKS; k++)
330 	buildings[i].hunks[j][k] = TRUE;
331   }
332   j--;
333 
334   for(i=0; i< NUMBUILDINGS; i++) {
335     buildings[i].hunks[0][0] = FALSE;
336     buildings[i].hunks[0][NUMHUNKS-1] = FALSE;
337     for (k = 3; k < NUMHUNKS-3; k++)
338 	buildings[i].hunks[j][k] = FALSE;
339   }
340 }
341 
DrawBuildings()342 void DrawBuildings()
343 {
344   int i, j, k;
345 
346   for(i=0; i< NUMBUILDINGS; i++) {
347     for (j=0; j<HUNKROWS; j++)
348       for (k = 0; k < NUMHUNKS; k++)
349 	if(buildings[i].hunks[j][k]) DrawBuildingHunk(&buildings[i], j, k, buildinggc);
350   }
351 }
352