3
|
1 /* $Id: planets.c,v 1.1.1.1 1997/12/06 05:41:30 darius Exp $ */
|
|
2
|
|
3 /*
|
|
4 * planets.c
|
|
5 *
|
|
6 * Kevin P. Smith 2/21/89
|
|
7 *
|
|
8 * This file contains the galaxy definition as well as some support for
|
|
9 * determining when parts of the galactic map need to be redrawn.
|
|
10 */
|
|
11 #include "copyright2.h"
|
|
12
|
|
13 #include <stdio.h>
|
|
14 #include <math.h>
|
|
15 #include "Wlib.h"
|
|
16 #include "defs.h"
|
|
17 #include "struct.h"
|
|
18 #include "data.h"
|
|
19 #include "proto.h"
|
|
20
|
|
21 /* define to get profiling info, to better set DEPTH and DETAIL [BDyess] */
|
|
22 /*#define PROFILE1 /* maxdepth printed */
|
|
23 /*#define PROFILE2 /* every PLREDRAW setting printed (VERBOSE) */
|
|
24
|
|
25 /* Note: DETAIL * MUST * be a factor of GWIDTH. */
|
|
26 #define DETAIL 80 /* Size of redraw array */
|
|
27 #define RADIUS 2 /* number of adjacent cells to register in */
|
|
28 #define SIZE 2500
|
|
29 #define DEPTH 8
|
|
30 #ifdef PROFILE1
|
|
31 #define ADDPLANET(i,j,k) { \
|
|
32 for(z=0;z<DEPTH;z++) { \
|
|
33 if(redraws[i][j][z] == (char)-1) { \
|
|
34 redraws[i][j][z] = k; \
|
|
35 break; \
|
|
36 } \
|
|
37 } z++; \
|
|
38 if(z > maxdepth) maxdepth = z; \
|
|
39 }
|
|
40 #else /* not PROFILEing */
|
|
41 #define ADDPLANET(i,j,k) { \
|
|
42 for(z=0;z<DEPTH;z++) { \
|
|
43 if(redraws[i][j][z] == (char)-1) { \
|
|
44 redraws[i][j][z]=k; \
|
|
45 break; \
|
|
46 } \
|
|
47 } \
|
|
48 }
|
|
49 #endif /* PROFILE1 */
|
|
50
|
|
51 #define LEFT 1 /* position flags for corner guessing */
|
|
52 #define RIGHT 2
|
|
53 #define TOP 4
|
|
54 #define BOTTOM 8
|
|
55
|
|
56 struct _star {
|
|
57 int s_x, s_y;
|
|
58 int s_color;
|
|
59 };
|
|
60
|
|
61 static void redrawStarSector P((struct _star star_sector[16]));
|
|
62
|
|
63 /*
|
|
64 planets may be on top of each other or very close, so more than one planet
|
|
65 can exist in a given block. The 3rd dimension is for a list of planets.
|
|
66 [BDyess]
|
|
67 */
|
|
68 char redraws[DETAIL][DETAIL][DEPTH];
|
|
69 static int initialized = 0;
|
|
70
|
|
71 /*
|
|
72 since planets may be moved, the redraw matrix must be updated. This
|
|
73 function is for updating just one planet. This should help the moving
|
|
74 planet efficiency problems quite a bit. [BDyess]
|
|
75 */
|
|
76 void
|
|
77 initOnePlanet(pl)
|
|
78 struct planet *pl;
|
|
79 {
|
|
80 }
|
|
81
|
|
82 /*
|
|
83 rewritten to repair UNBELIEVABLE inefficiencies in the original [BDyess]
|
|
84 */
|
|
85 void
|
|
86 initPlanets()
|
|
87 {
|
|
88 register int i, j, k, x, y, z, r, s;
|
|
89 struct planet *pl;
|
|
90 #ifdef PROFILE1
|
|
91 int maxdepth = 0;
|
|
92 #endif /* PROFILE1 */
|
|
93
|
|
94 /* initialize lookup array */
|
|
95 for (i = 0; i < DETAIL; i++) {
|
|
96 for (j = 0; j < DETAIL; j++) {
|
|
97 for (k = 0; k < DEPTH; k++) {
|
|
98 redraws[i][j][k] = -1;
|
|
99 }
|
|
100 }
|
|
101 }
|
|
102
|
|
103 /*
|
|
104 check all the planets. If part of the planet falls inside a box in
|
|
105 the lookup array, add it to the refresh list for that box. [BDyess]
|
|
106 */
|
|
107 for (k = 0, pl = planets; k < nplanets; k++, pl++) {
|
|
108 x = pl->pl_x;
|
|
109 y = pl->pl_y;
|
|
110 i = x / SIZE - 3;
|
|
111 j = y / SIZE - 2;
|
|
112 /*
|
|
113 fill cells around the target cell with the planetnum like so: ****
|
|
114
|
|
115 **
|
|
116
|
|
117 x** ****
|
|
118
|
|
119 **
|
|
120
|
|
121 ** taller than wide because of text ****
|
|
122
|
|
123 [BDyess]
|
|
124 */
|
|
125 for (r = 0; r < 5; r++) {
|
|
126 i++;
|
|
127 if (i <= 0)
|
|
128 continue;
|
|
129 if (i >= DETAIL)
|
|
130 break;
|
|
131 for (s = 0; s < 7; s++) {
|
|
132 j += s;
|
|
133 if (j <= 0)
|
|
134 continue;
|
|
135 if (j >= DETAIL)
|
|
136 break;
|
|
137 ADDPLANET(i, j, k)
|
|
138 j -= s;
|
|
139 }
|
|
140 }
|
|
141 #if 0 /* this works, and allows the radius around
|
|
142 the hot spot to be changed. It's disabled
|
|
143 because a less-flexible piece of code
|
|
144 (above) is a bit faster. Plus, it's hard
|
|
145 to generalize about that extra added
|
|
146 lines. [BDyess] */
|
|
147 ADDPLANET(i, j, k)
|
|
148 for (r = 1; r <= RADIUS; r++) {
|
|
149 /* draw box sides in all four directions */
|
|
150 /* bottom */
|
|
151 i += r;
|
|
152 ADDPLANET(i, j, k)
|
|
153 for (s = 1; s <= r; s++) {
|
|
154 j += s;
|
|
155 ADDPLANET(i, j, k)
|
|
156 j -= 2 * s;
|
|
157 ADDPLANET(i, j, k)
|
|
158 j += s;
|
|
159 }
|
|
160 /* top */
|
|
161 i -= 2 * r;
|
|
162 ADDPLANET(i, j, k)
|
|
163 for (s = 1; s <= r; s++) {
|
|
164 j += s;
|
|
165 ADDPLANET(i, j, k)
|
|
166 j -= 2 * s;
|
|
167 ADDPLANET(i, j, k)
|
|
168 j += s;
|
|
169 }
|
|
170 /* left */
|
|
171 i += r;
|
|
172 j += r;
|
|
173 ADDPLANET(i, j, k)
|
|
174 for (s = 1; s < r; s++) {
|
|
175 i += s;
|
|
176 ADDPLANET(i, j, k)
|
|
177 i -= 2 * s;
|
|
178 ADDPLANET(i, j, k)
|
|
179 i += s;
|
|
180 }
|
|
181 /* right */
|
|
182 j -= 2 * r;
|
|
183 ADDPLANET(i, j, k)
|
|
184 for (s = 1; s < r; s++) {
|
|
185 i += s;
|
|
186 ADDPLANET(i, j, k)
|
|
187 i -= 2 * s;
|
|
188 ADDPLANET(i, j, k)
|
|
189 i += s;
|
|
190 }
|
|
191 }
|
|
192 #endif /* 0 */
|
|
193 }
|
|
194 initialized = 1;
|
|
195 #ifdef PROFILE1
|
|
196 printf("max depth = %d\n", maxdepth);
|
|
197 #endif /* PROFILE1 */
|
|
198 }
|
|
199
|
|
200 void
|
|
201 checkRedraw(x, y)
|
|
202 int x, y;
|
|
203 {
|
|
204 int j;
|
|
205 char i;
|
|
206
|
|
207 if (!initialized || x < 0 || y < 0 || x >= blk_gwidth || y >= blk_gwidth)
|
|
208 return;
|
|
209 x /= SIZE;
|
|
210 y /= SIZE;
|
|
211 for (j = 0; j < DEPTH; j++) {
|
|
212 i = redraws[x][y][j];
|
|
213 if (i == (char) -1)
|
|
214 return;
|
|
215 planets[i].pl_flags |= PLREDRAW;
|
|
216 #ifdef PROFILE2
|
|
217 printf("setting PLREDRAW flag for %s\n", planets[i].pl_name);
|
|
218 #endif /* PROFILE2 */
|
|
219 }
|
|
220 }
|
|
221
|
|
222
|
|
223 /* NOTE: this has been rewritten -- see below */
|
|
224
|
|
225 #define NUMSTARS 1600
|
|
226
|
|
227 static int starsX[NUMSTARS];
|
|
228 static int starsY[NUMSTARS];
|
|
229
|
|
230 void
|
|
231 _initStars()
|
|
232 {
|
|
233 register int i;
|
|
234
|
|
235 for (i = 0; i < NUMSTARS; i++) {
|
|
236 starsX[i] = (i % 40) * 5000 + random() % 5000;
|
|
237 starsY[i] = (i / 40) * 5000 + random() % 5000;
|
|
238 }
|
|
239 }
|
|
240
|
|
241 void
|
|
242 _drawStars()
|
|
243 {
|
|
244 int i;
|
|
245 int x, y;
|
|
246
|
|
247 for (i = 0; i < NUMSTARS; i++) {
|
|
248 x = starsX[i] - me->p_x;
|
|
249 y = starsY[i] - me->p_y;
|
|
250 if (ABS(x) < 10000 && ABS(y) < 10000) {
|
|
251 x = x / SCALE + WINSIDE / 2;
|
|
252 y = y / SCALE + WINSIDE / 2;
|
|
253 W_DrawPoint(w, x, y, W_White);
|
|
254 W_CacheClearArea(w, x, y, 1, 1);
|
|
255 }
|
|
256 }
|
|
257 }
|
|
258
|
|
259 /*
|
|
260 * This rewrite improves drawStars() by a factor of about 30 (according to
|
|
261 * gprof)
|
|
262 */
|
|
263
|
|
264 /* blk_gwidth/(WINSIDE * SCALE) == 10 for blk_gwidth == 200000 */
|
|
265 static struct _star stars[10][10][16];
|
|
266
|
|
267 void
|
|
268 initStars()
|
|
269 {
|
|
270 register int i, j, k;
|
|
271
|
|
272 for (i = 0; i < 10; i++) {
|
|
273 for (j = 0; j < 10; j++) {
|
|
274 for (k = 0; k < 16; k++) {
|
|
275 stars[i][j][k].s_x = i * (WINSIDE * SCALE) + random() % (WINSIDE * SCALE);
|
|
276 stars[i][j][k].s_y = j * (WINSIDE * SCALE) + random() % (WINSIDE * SCALE);
|
|
277 stars[i][j][k].s_color = randcolor();
|
|
278 }
|
|
279 }
|
|
280 }
|
|
281 }
|
|
282
|
|
283 int
|
|
284 randcolor()
|
|
285 {
|
|
286 switch (random() % 10) {
|
|
287 case 0:return W_Yellow;
|
|
288 case 1:
|
|
289 return W_Red;
|
|
290 case 2:
|
|
291 return W_Green;
|
|
292 case 3:
|
|
293 return W_Cyan;
|
|
294 default:
|
|
295 return W_White;
|
|
296 }
|
|
297 }
|
|
298
|
|
299 void
|
|
300 drawStars()
|
|
301 {
|
|
302 /*
|
|
303 note: cpp symbols in expressions (WINSIDE*SCALE) will be precalculated
|
|
304 by any C optimizer
|
|
305 */
|
|
306 int sectorx = me->p_x / (WINSIDE * SCALE), sectory = me->p_y / (WINSIDE * SCALE);
|
|
307 int sector_offx = me->p_x - sectorx * (WINSIDE * SCALE), sector_offy = me->p_y - sectory * (WINSIDE * SCALE);
|
|
308 int l = 0, r = 0, t = 0, b = 0;
|
|
309
|
|
310 if (sector_offx < 0) { /* goddamn rounding towards 0 */
|
|
311 sectorx--;
|
|
312 sector_offx += WINSIDE * SCALE;
|
|
313 }
|
|
314 if (sector_offy < 0) { /* goddamn rounding towards 0 */
|
|
315 sectory--;
|
|
316 sector_offy += WINSIDE * SCALE;
|
|
317 }
|
|
318 #define MAXSECTOR (blk_gwidth/(WINSIDE*SCALE))
|
|
319
|
|
320 /* at worst we have to redraw 4 star sectors */
|
|
321
|
|
322 /* draw the one we're in */
|
|
323 /*
|
|
324 check first to make sure it's valid. This is mainly important for if
|
|
325 it tries to redraw and we're already dead
|
|
326 */
|
|
327 if (sectorx < 0 || sectory < 0)
|
|
328 return;
|
|
329
|
|
330 l = sector_offx < (WINSIDE * SCALE) / 2 && sectorx > 0;
|
|
331 r = sector_offx > (WINSIDE * SCALE) / 2 && sectorx + 1 < MAXSECTOR;
|
|
332 t = sector_offy < (WINSIDE * SCALE) / 2 && sectory > 0;
|
|
333 b = sector_offy > (WINSIDE * SCALE) / 2 && sectory + 1 < MAXSECTOR;
|
|
334
|
|
335 if (t) {
|
|
336 if (l) /* redraw upper-left sector */
|
|
337 redrawStarSector(stars[sectorx - 1][sectory - 1]);
|
|
338
|
|
339 /* redraw upper sector */
|
|
340 redrawStarSector(stars[sectorx][sectory - 1]);
|
|
341
|
|
342 if (r) /* redraw upper-right sector */
|
|
343 redrawStarSector(stars[sectorx + 1][sectory - 1]);
|
|
344 }
|
|
345 if (l) /* redraw left sector */
|
|
346 redrawStarSector(stars[sectorx - 1][sectory]);
|
|
347
|
|
348 /* redraw center sector */
|
|
349 redrawStarSector(stars[sectorx][sectory]);
|
|
350
|
|
351 if (r) /* redraw right sector */
|
|
352 redrawStarSector(stars[sectorx + 1][sectory]);
|
|
353
|
|
354 if (b) {
|
|
355 if (l) /* redraw bottom-left sector */
|
|
356 redrawStarSector(stars[sectorx - 1][sectory + 1]);
|
|
357
|
|
358 /* redraw bottom sector */
|
|
359 redrawStarSector(stars[sectorx][sectory + 1]);
|
|
360
|
|
361 if (r) /* redraw bottom-right sector */
|
|
362 redrawStarSector(stars[sectorx + 1][sectory + 1]);
|
|
363 }
|
|
364 W_FlushPointCaches(w);
|
|
365 }
|
|
366
|
|
367 static void
|
|
368 redrawStarSector(star_sector)
|
|
369 struct _star star_sector[16];
|
|
370 {
|
|
371 register i, dx, dy, dxx, dyy;
|
|
372 register struct _star *s;
|
|
373 static int warpflag = 0; /* assume starting out not in warp */
|
|
374 static int streaksOn = 0, lastspeed = 0, lastsubspeed = 0, updates = 0;
|
|
375 static int streaklength = 1;
|
|
376
|
|
377 if (warpStreaks) {
|
|
378 if (warpflag != (me->p_flags & PFWARP)) { /* change in warp state */
|
|
379 streaksOn = 1;
|
|
380 warpflag = (me->p_flags & PFWARP);
|
|
381 }
|
|
382 if (streaksOn) {
|
|
383 if (warpflag && (me->p_speed < lastspeed ||
|
|
384 (me->p_speed == lastspeed && me->p_subspeed <= lastsubspeed))) {
|
|
385 /* finished accelerating */
|
|
386 updates++;
|
|
387 if (updates > 5) {
|
|
388 lastspeed = me->p_speed;
|
|
389 lastsubspeed = me->p_subspeed;
|
|
390 updates = 0;
|
|
391 streaksOn = 0;
|
|
392 redrawStarSector(star_sector);
|
|
393 return;
|
|
394 }
|
|
395 } else if (streaklength == 1 || (!warpflag && ((me->p_speed > lastspeed) ||
|
|
396 (me->p_speed == lastspeed && me->p_subspeed >= lastsubspeed)))) {
|
|
397 /* finished decelerating */
|
|
398 updates++;
|
|
399 if (updates > 5) {
|
|
400 lastspeed = me->p_speed;
|
|
401 lastsubspeed = me->p_subspeed;
|
|
402 updates = 0;
|
|
403 streaksOn = 0;
|
|
404 streaklength = 1;
|
|
405 redrawStarSector(star_sector);
|
|
406 return;
|
|
407 }
|
|
408 } else
|
|
409 updates = 0;
|
|
410 lastspeed = me->p_speed;
|
|
411 lastsubspeed = me->p_subspeed;
|
|
412 /* draw the streaks */
|
|
413 if (warpflag)
|
|
414 streaklength += 3;
|
|
415 else
|
|
416 streaklength--;
|
|
417 dxx = (int) (Cos[me->p_dir] * streaklength);
|
|
418 dyy = (int) (Sin[me->p_dir] * streaklength);
|
|
419 for (i = 0, s = star_sector; i < 16; i++, s++) {
|
|
420 dx = s->s_x - me->p_x;
|
|
421 dy = s->s_y - me->p_y;
|
|
422 if (ABS(dx) > (SCALE * WINSIDE / 2) || ABS(dy) > (SCALE * WINSIDE / 2))
|
|
423 continue;
|
|
424
|
|
425 dx = dx / SCALE + WINSIDE / 2;
|
|
426 dy = dy / SCALE + WINSIDE / 2;
|
|
427 W_CacheLine(w, dx, dy, dx - dxx, dy - dyy, s->s_color);
|
|
428
|
|
429 clearline[0][clearlcount] = dx;
|
|
430 clearline[1][clearlcount] = dy;
|
|
431 clearline[2][clearlcount] = dx - dxx;
|
|
432 clearline[3][clearlcount] = dy - dyy;
|
|
433 clearlcount++;
|
|
434 }
|
|
435 return;
|
|
436 }
|
|
437 }
|
|
438 for (i = 0, s = star_sector; i < 16; i++, s++) {
|
|
439 dx = s->s_x - me->p_x;
|
|
440 dy = s->s_y - me->p_y;
|
|
441 if (ABS(dx) > (SCALE * WINSIDE / 2) || ABS(dy) > (SCALE * WINSIDE / 2))
|
|
442 continue;
|
|
443
|
|
444 dx = dx / SCALE + WINSIDE / 2;
|
|
445 dy = dy / SCALE + WINSIDE / 2;
|
|
446 W_CachePoint(w, dx, dy, s->s_color);
|
|
447 #ifndef AMIGA
|
|
448 /*
|
|
449 this is a minor kludge: as long as there are less then 128 stars
|
|
450 in a sector these cached requests will not actually be written to
|
|
451 the X server until the next redraw cycle begins.
|
|
452 */
|
|
453 W_CacheClearArea(w, dx, dy, 1, 1);
|
|
454 #else
|
|
455 clearline[0][clearlcount] = dx;
|
|
456 clearline[1][clearlcount] = dy;
|
|
457 clearline[2][clearlcount] = dx;
|
|
458 clearline[3][clearlcount] = dy;
|
|
459 clearlcount++;
|
|
460 #endif
|
|
461 }
|
|
462 }
|
|
463
|
|
464 #if 0
|
|
465 void
|
|
466 clearStars()
|
|
467 {
|
|
468 int i;
|
|
469 int x, y;
|
|
470
|
|
471 for (i = 0; i < NUMSTARS; i++) {
|
|
472 x = starsX[i] - me->p_x;
|
|
473 y = starsY[i] - me->p_y;
|
|
474 if (ABS(x) < 10000 && ABS(y) < 10000) {
|
|
475 x = x / SCALE + WINSIDE / 2;
|
|
476 y = y / SCALE + WINSIDE / 2;
|
|
477 W_CacheClearArea(w, x, y, 1, 1);
|
|
478 }
|
|
479 }
|
|
480 }
|
|
481 #endif
|