Mercurial > ~darius > hgwebdir.cgi > paradise_client
view planets.c @ 3:5a977ccbc7a9 default tip
Empty changelog
author | darius |
---|---|
date | Sat, 06 Dec 1997 05:41:29 +0000 |
parents | |
children |
line wrap: on
line source
/* $Id: planets.c,v 1.1.1.1 1997/12/06 05:41:30 darius Exp $ */ /* * planets.c * * Kevin P. Smith 2/21/89 * * This file contains the galaxy definition as well as some support for * determining when parts of the galactic map need to be redrawn. */ #include "copyright2.h" #include <stdio.h> #include <math.h> #include "Wlib.h" #include "defs.h" #include "struct.h" #include "data.h" #include "proto.h" /* define to get profiling info, to better set DEPTH and DETAIL [BDyess] */ /*#define PROFILE1 /* maxdepth printed */ /*#define PROFILE2 /* every PLREDRAW setting printed (VERBOSE) */ /* Note: DETAIL * MUST * be a factor of GWIDTH. */ #define DETAIL 80 /* Size of redraw array */ #define RADIUS 2 /* number of adjacent cells to register in */ #define SIZE 2500 #define DEPTH 8 #ifdef PROFILE1 #define ADDPLANET(i,j,k) { \ for(z=0;z<DEPTH;z++) { \ if(redraws[i][j][z] == (char)-1) { \ redraws[i][j][z] = k; \ break; \ } \ } z++; \ if(z > maxdepth) maxdepth = z; \ } #else /* not PROFILEing */ #define ADDPLANET(i,j,k) { \ for(z=0;z<DEPTH;z++) { \ if(redraws[i][j][z] == (char)-1) { \ redraws[i][j][z]=k; \ break; \ } \ } \ } #endif /* PROFILE1 */ #define LEFT 1 /* position flags for corner guessing */ #define RIGHT 2 #define TOP 4 #define BOTTOM 8 struct _star { int s_x, s_y; int s_color; }; static void redrawStarSector P((struct _star star_sector[16])); /* planets may be on top of each other or very close, so more than one planet can exist in a given block. The 3rd dimension is for a list of planets. [BDyess] */ char redraws[DETAIL][DETAIL][DEPTH]; static int initialized = 0; /* since planets may be moved, the redraw matrix must be updated. This function is for updating just one planet. This should help the moving planet efficiency problems quite a bit. [BDyess] */ void initOnePlanet(pl) struct planet *pl; { } /* rewritten to repair UNBELIEVABLE inefficiencies in the original [BDyess] */ void initPlanets() { register int i, j, k, x, y, z, r, s; struct planet *pl; #ifdef PROFILE1 int maxdepth = 0; #endif /* PROFILE1 */ /* initialize lookup array */ for (i = 0; i < DETAIL; i++) { for (j = 0; j < DETAIL; j++) { for (k = 0; k < DEPTH; k++) { redraws[i][j][k] = -1; } } } /* check all the planets. If part of the planet falls inside a box in the lookup array, add it to the refresh list for that box. [BDyess] */ for (k = 0, pl = planets; k < nplanets; k++, pl++) { x = pl->pl_x; y = pl->pl_y; i = x / SIZE - 3; j = y / SIZE - 2; /* fill cells around the target cell with the planetnum like so: **** ** x** **** ** ** taller than wide because of text **** [BDyess] */ for (r = 0; r < 5; r++) { i++; if (i <= 0) continue; if (i >= DETAIL) break; for (s = 0; s < 7; s++) { j += s; if (j <= 0) continue; if (j >= DETAIL) break; ADDPLANET(i, j, k) j -= s; } } #if 0 /* this works, and allows the radius around the hot spot to be changed. It's disabled because a less-flexible piece of code (above) is a bit faster. Plus, it's hard to generalize about that extra added lines. [BDyess] */ ADDPLANET(i, j, k) for (r = 1; r <= RADIUS; r++) { /* draw box sides in all four directions */ /* bottom */ i += r; ADDPLANET(i, j, k) for (s = 1; s <= r; s++) { j += s; ADDPLANET(i, j, k) j -= 2 * s; ADDPLANET(i, j, k) j += s; } /* top */ i -= 2 * r; ADDPLANET(i, j, k) for (s = 1; s <= r; s++) { j += s; ADDPLANET(i, j, k) j -= 2 * s; ADDPLANET(i, j, k) j += s; } /* left */ i += r; j += r; ADDPLANET(i, j, k) for (s = 1; s < r; s++) { i += s; ADDPLANET(i, j, k) i -= 2 * s; ADDPLANET(i, j, k) i += s; } /* right */ j -= 2 * r; ADDPLANET(i, j, k) for (s = 1; s < r; s++) { i += s; ADDPLANET(i, j, k) i -= 2 * s; ADDPLANET(i, j, k) i += s; } } #endif /* 0 */ } initialized = 1; #ifdef PROFILE1 printf("max depth = %d\n", maxdepth); #endif /* PROFILE1 */ } void checkRedraw(x, y) int x, y; { int j; char i; if (!initialized || x < 0 || y < 0 || x >= blk_gwidth || y >= blk_gwidth) return; x /= SIZE; y /= SIZE; for (j = 0; j < DEPTH; j++) { i = redraws[x][y][j]; if (i == (char) -1) return; planets[i].pl_flags |= PLREDRAW; #ifdef PROFILE2 printf("setting PLREDRAW flag for %s\n", planets[i].pl_name); #endif /* PROFILE2 */ } } /* NOTE: this has been rewritten -- see below */ #define NUMSTARS 1600 static int starsX[NUMSTARS]; static int starsY[NUMSTARS]; void _initStars() { register int i; for (i = 0; i < NUMSTARS; i++) { starsX[i] = (i % 40) * 5000 + random() % 5000; starsY[i] = (i / 40) * 5000 + random() % 5000; } } void _drawStars() { int i; int x, y; for (i = 0; i < NUMSTARS; i++) { x = starsX[i] - me->p_x; y = starsY[i] - me->p_y; if (ABS(x) < 10000 && ABS(y) < 10000) { x = x / SCALE + WINSIDE / 2; y = y / SCALE + WINSIDE / 2; W_DrawPoint(w, x, y, W_White); W_CacheClearArea(w, x, y, 1, 1); } } } /* * This rewrite improves drawStars() by a factor of about 30 (according to * gprof) */ /* blk_gwidth/(WINSIDE * SCALE) == 10 for blk_gwidth == 200000 */ static struct _star stars[10][10][16]; void initStars() { register int i, j, k; for (i = 0; i < 10; i++) { for (j = 0; j < 10; j++) { for (k = 0; k < 16; k++) { stars[i][j][k].s_x = i * (WINSIDE * SCALE) + random() % (WINSIDE * SCALE); stars[i][j][k].s_y = j * (WINSIDE * SCALE) + random() % (WINSIDE * SCALE); stars[i][j][k].s_color = randcolor(); } } } } int randcolor() { switch (random() % 10) { case 0:return W_Yellow; case 1: return W_Red; case 2: return W_Green; case 3: return W_Cyan; default: return W_White; } } void drawStars() { /* note: cpp symbols in expressions (WINSIDE*SCALE) will be precalculated by any C optimizer */ int sectorx = me->p_x / (WINSIDE * SCALE), sectory = me->p_y / (WINSIDE * SCALE); int sector_offx = me->p_x - sectorx * (WINSIDE * SCALE), sector_offy = me->p_y - sectory * (WINSIDE * SCALE); int l = 0, r = 0, t = 0, b = 0; if (sector_offx < 0) { /* goddamn rounding towards 0 */ sectorx--; sector_offx += WINSIDE * SCALE; } if (sector_offy < 0) { /* goddamn rounding towards 0 */ sectory--; sector_offy += WINSIDE * SCALE; } #define MAXSECTOR (blk_gwidth/(WINSIDE*SCALE)) /* at worst we have to redraw 4 star sectors */ /* draw the one we're in */ /* check first to make sure it's valid. This is mainly important for if it tries to redraw and we're already dead */ if (sectorx < 0 || sectory < 0) return; l = sector_offx < (WINSIDE * SCALE) / 2 && sectorx > 0; r = sector_offx > (WINSIDE * SCALE) / 2 && sectorx + 1 < MAXSECTOR; t = sector_offy < (WINSIDE * SCALE) / 2 && sectory > 0; b = sector_offy > (WINSIDE * SCALE) / 2 && sectory + 1 < MAXSECTOR; if (t) { if (l) /* redraw upper-left sector */ redrawStarSector(stars[sectorx - 1][sectory - 1]); /* redraw upper sector */ redrawStarSector(stars[sectorx][sectory - 1]); if (r) /* redraw upper-right sector */ redrawStarSector(stars[sectorx + 1][sectory - 1]); } if (l) /* redraw left sector */ redrawStarSector(stars[sectorx - 1][sectory]); /* redraw center sector */ redrawStarSector(stars[sectorx][sectory]); if (r) /* redraw right sector */ redrawStarSector(stars[sectorx + 1][sectory]); if (b) { if (l) /* redraw bottom-left sector */ redrawStarSector(stars[sectorx - 1][sectory + 1]); /* redraw bottom sector */ redrawStarSector(stars[sectorx][sectory + 1]); if (r) /* redraw bottom-right sector */ redrawStarSector(stars[sectorx + 1][sectory + 1]); } W_FlushPointCaches(w); } static void redrawStarSector(star_sector) struct _star star_sector[16]; { register i, dx, dy, dxx, dyy; register struct _star *s; static int warpflag = 0; /* assume starting out not in warp */ static int streaksOn = 0, lastspeed = 0, lastsubspeed = 0, updates = 0; static int streaklength = 1; if (warpStreaks) { if (warpflag != (me->p_flags & PFWARP)) { /* change in warp state */ streaksOn = 1; warpflag = (me->p_flags & PFWARP); } if (streaksOn) { if (warpflag && (me->p_speed < lastspeed || (me->p_speed == lastspeed && me->p_subspeed <= lastsubspeed))) { /* finished accelerating */ updates++; if (updates > 5) { lastspeed = me->p_speed; lastsubspeed = me->p_subspeed; updates = 0; streaksOn = 0; redrawStarSector(star_sector); return; } } else if (streaklength == 1 || (!warpflag && ((me->p_speed > lastspeed) || (me->p_speed == lastspeed && me->p_subspeed >= lastsubspeed)))) { /* finished decelerating */ updates++; if (updates > 5) { lastspeed = me->p_speed; lastsubspeed = me->p_subspeed; updates = 0; streaksOn = 0; streaklength = 1; redrawStarSector(star_sector); return; } } else updates = 0; lastspeed = me->p_speed; lastsubspeed = me->p_subspeed; /* draw the streaks */ if (warpflag) streaklength += 3; else streaklength--; dxx = (int) (Cos[me->p_dir] * streaklength); dyy = (int) (Sin[me->p_dir] * streaklength); for (i = 0, s = star_sector; i < 16; i++, s++) { dx = s->s_x - me->p_x; dy = s->s_y - me->p_y; if (ABS(dx) > (SCALE * WINSIDE / 2) || ABS(dy) > (SCALE * WINSIDE / 2)) continue; dx = dx / SCALE + WINSIDE / 2; dy = dy / SCALE + WINSIDE / 2; W_CacheLine(w, dx, dy, dx - dxx, dy - dyy, s->s_color); clearline[0][clearlcount] = dx; clearline[1][clearlcount] = dy; clearline[2][clearlcount] = dx - dxx; clearline[3][clearlcount] = dy - dyy; clearlcount++; } return; } } for (i = 0, s = star_sector; i < 16; i++, s++) { dx = s->s_x - me->p_x; dy = s->s_y - me->p_y; if (ABS(dx) > (SCALE * WINSIDE / 2) || ABS(dy) > (SCALE * WINSIDE / 2)) continue; dx = dx / SCALE + WINSIDE / 2; dy = dy / SCALE + WINSIDE / 2; W_CachePoint(w, dx, dy, s->s_color); #ifndef AMIGA /* this is a minor kludge: as long as there are less then 128 stars in a sector these cached requests will not actually be written to the X server until the next redraw cycle begins. */ W_CacheClearArea(w, dx, dy, 1, 1); #else clearline[0][clearlcount] = dx; clearline[1][clearlcount] = dy; clearline[2][clearlcount] = dx; clearline[3][clearlcount] = dy; clearlcount++; #endif } } #if 0 void clearStars() { int i; int x, y; for (i = 0; i < NUMSTARS; i++) { x = starsX[i] - me->p_x; y = starsY[i] - me->p_y; if (ABS(x) < 10000 && ABS(y) < 10000) { x = x / SCALE + WINSIDE / 2; y = y / SCALE + WINSIDE / 2; W_CacheClearArea(w, x, y, 1, 1); } } } #endif