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