Mercurial > ~darius > hgwebdir.cgi > paradise_client
diff 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 diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/planets.c Sat Dec 06 05:41:29 1997 +0000 @@ -0,0 +1,481 @@ +/* $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