Mercurial > ~darius > hgwebdir.cgi > paradise_client
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 |