comparison planets.c @ 3:5a977ccbc7a9 default tip

Empty changelog
author darius
date Sat, 06 Dec 1997 05:41:29 +0000
parents
children
comparison
equal deleted inserted replaced
2:fba0b6e6cdc7 3:5a977ccbc7a9
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