static void rock_compute (struct state *st, struct rock *rock) { double factor = st->depths [rock->depth]; double rsize = rock->real_size * factor; rock->size = (int) (rsize + 0.5); rock->diff = (int) GETZDIFF(rock->depth); rock->x = st->midx + (st->coss [rock->theta] * rock->r * factor); rock->y = st->midy + (st->sins [rock->theta] * rock->r * factor); if (st->move_p) { double move_factor = (((double) MOVE_STYLE) - (((double) rock->depth) / (((double) (MAX_DEPTH + 1)) * ((double) DEPTH_SCALE)))); /* move_factor is 0 when the rock is close, 1 when far */ rock->x += (((double) st->dep_x) * move_factor); rock->y += (((double) st->dep_y) * move_factor); } }
void draw_bouboule(ModeInfo * mi) /****************/ { Display *display = MI_DISPLAY(mi); Window window = MI_WINDOW(mi); GC gc = MI_GC(mi); int i, diff = 0; double CX, CY, CZ, SX, SY, SZ; Star *star; XArc *arc, *arcleft = (XArc *) NULL; StarField *sp; #if (ADAPT_ERASE == 1) struct timeval tv1; struct timeval tv2; #endif #if ((USEOLDXARCS == 0) || (ADAPT_ERASE == 1)) short x_1, y_1, x_2, y_2; /* bounding rectangle around the old starfield, * for erasing with the smallest rectangle * instead of filling the whole screen */ int maxdiff = 0; /* maximal distance between left and right */ /* star in 3d mode, otherwise 0 */ #endif if (starfield == NULL) return; sp = &starfield[MI_SCREEN(mi)]; if (sp->star == NULL) return; MI_IS_DRAWN(mi) = True; #if ((USEOLDXARCS == 0) || (ADAPT_ERASE == 1)) if (MI_IS_USE3D(mi)) { maxdiff = (int) MAXDIFF; } x_1 = (int) sp->x.value - (int) sp->sizex.value - sp->max_star_size - maxdiff; y_1 = (int) sp->y.value - (int) sp->sizey.value - sp->max_star_size; x_2 = 2 * ((int) sp->sizex.value + sp->max_star_size + maxdiff); y_2 = 2 * ((int) sp->sizey.value + sp->max_star_size); #endif /* We make variables vary. */ sinvary(&sp->thetax); sinvary(&sp->thetay); sinvary(&sp->thetaz); sinvary(&sp->x); sinvary(&sp->y); if (MI_IS_USE3D(mi)) sinvary(&sp->z); /* A little trick to prevent the bouboule from being * bigger than the screen */ sp->sizex.maximum = MIN(((double) sp->width) - sp->x.value, sp->x.value); sp->sizex.minimum = sp->sizex.maximum / 3.0; /* Another trick to make the ball not too flat */ sp->sizey.minimum = MAX(sp->sizex.value / MAX_SIZEX_SIZEY, sp->sizey.maximum / 3.0); sp->sizey.maximum = MIN(sp->sizex.value * MAX_SIZEX_SIZEY, MIN(((double) sp->height) - sp->y.value, sp->y.value)); sinvary(&sp->sizex); sinvary(&sp->sizey); /* * We calculate the rotation matrix values. We just make the * rotation on the fly, without using a matrix. * Star positions are recorded as unit vectors pointing in various * directions. We just make them all rotate. */ CX = cos(sp->thetax.value); SX = sin(sp->thetax.value); CY = cos(sp->thetay.value); SY = sin(sp->thetay.value); CZ = cos(sp->thetaz.value); SZ = sin(sp->thetaz.value); for (i = 0; i < sp->NbStars; i++) { star = &(sp->star[i]); arc = &(sp->xarc[i]); if (MI_IS_USE3D(mi)) { arcleft = &(sp->xarcleft[i]); /* to help the eyes, the starfield is always as wide as */ /* deep, so .sizex.value can be used. */ diff = (int) GETZDIFF(sp->sizex.value * ((SY * CX) * star->x + (SX) * star->y + (CX * CY) * star->z) + sp->z.value); } arc->x = (short) ((sp->sizex.value * ((CY * CZ - SX * SY * SZ) * star->x + (-CX * SZ) * star->y + (SY * CZ + SZ * SX * CY) * star->z) + sp->x.value)); arc->y = (short) ((sp->sizey.value * ((CY * SZ + SX * SY * CZ) * star->x + (CX * CZ) * star->y + (SY * SZ - SX * CY * CZ) * star->z) + sp->y.value)); if (MI_IS_USE3D(mi)) { arcleft->x = (short) ((sp->sizex.value * ((CY * CZ - SX * SY * SZ) * star->x + (-CX * SZ) * star->y + (SY * CZ + SZ * SX * CY) * star->z) + sp->x.value)); arcleft->y = (short) ((sp->sizey.value * ((CY * SZ + SX * SY * CZ) * star->x + (CX * CZ) * star->y + (SY * SZ - SX * CY * CZ) * star->z) + sp->y.value)); arc->x += diff; arcleft->x -= diff; } if (star->size != 0) { arc->x -= star->size; arc->y -= star->size; if (MI_IS_USE3D(mi)) { arcleft->x -= star->size; arcleft->y -= star->size; } } } /* First, we erase the previous starfield */ if (MI_IS_INSTALL(mi) && MI_IS_USE3D(mi)) XSetForeground(display, gc, MI_NONE_COLOR(mi)); else XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); #if (ADAPT_ERASE == 1) if (sp->hasbeenchecked == 0) { /* We just calculate which method is the faster and eventually free * the oldxarc list */ if (sp->xarc_time > ADAPT_ARC_PREFERED * sp->rect_time) { sp->hasbeenchecked = -2; /* XFillRectangle mode */ free(sp->oldxarc); sp->oldxarc = (XArc *) NULL; if (MI_IS_USE3D(mi)) { free(sp->oldxarcleft); sp->oldxarcleft = (XArc *) NULL; } } else { sp->hasbeenchecked = -1; /* XFillArcs mode */ } } if (sp->hasbeenchecked == -2) { /* Erasing is done with XFillRectangle */ XFillRectangle(display, window, gc, x_1, y_1, x_2, y_2); } else if (sp->hasbeenchecked == -1) { /* Erasing is done with XFillArcs */ XFillArcs(display, window, gc, sp->oldxarc, sp->NbStars); if (MI_IS_USE3D(mi)) XFillArcs(display, window, gc, sp->oldxarcleft, sp->NbStars); } else { long usec; if (sp->hasbeenchecked > ADAPT_CHECKS) { GETTIMEOFDAY(&tv1); XFillRectangle(display, window, gc, x_1, y_1, x_2, y_2); GETTIMEOFDAY(&tv2); usec = (tv2.tv_sec - tv1.tv_sec) * 1000000; if (usec + tv2.tv_usec - tv1.tv_usec > 0) { sp->rect_time += usec + tv2.tv_usec - tv1.tv_usec; sp->hasbeenchecked--; } } else { GETTIMEOFDAY(&tv1); XFillArcs(display, window, gc, sp->oldxarc, sp->NbStars); if (MI_IS_USE3D(mi)) XFillArcs(display, window, gc, sp->oldxarcleft, sp->NbStars); GETTIMEOFDAY(&tv2); usec = (tv2.tv_sec - tv1.tv_sec) * 1000000; if (usec + tv2.tv_usec - tv1.tv_usec > 0) { sp->xarc_time += usec + tv2.tv_usec - tv1.tv_usec; sp->hasbeenchecked--; } } } #else #if (USEOLDXARCS == 1) XFillArcs(display, window, gc, sp->oldxarc, sp->NbStars); if (MI_IS_USE3D(mi)) XFillArcs(display, window, gc, sp->oldxarcleft, sp->NbStars); #else XFillRectangle(display, window, gc, x_1, y_1, x_2, y_2); #endif #endif /* Then we draw the new one */ if (MI_IS_USE3D(mi)) { if (MI_IS_INSTALL(mi)) XSetFunction(display, gc, GXor); XSetForeground(display, gc, MI_RIGHT_COLOR(mi)); XFillArcs(display, window, gc, sp->xarc, sp->NbStars); XSetForeground(display, gc, MI_LEFT_COLOR(mi)); XFillArcs(display, window, gc, sp->xarcleft, sp->NbStars); if (MI_IS_INSTALL(mi)) XSetFunction(display, gc, GXcopy); } else { XSetForeground(display, gc, sp->color); XFillArcs(display, window, gc, sp->xarc, sp->NbStars); } #if ((USEOLDXARCS == 1) || (ADAPT_ERASE == 1)) #if (ADAPT_ERASE == 1) if (sp->hasbeenchecked >= -1) { arc = sp->xarc; sp->xarc = sp->oldxarc; sp->oldxarc = arc; if (MI_IS_USE3D(mi)) { arcleft = sp->xarcleft; sp->xarcleft = sp->oldxarcleft; sp->oldxarcleft = arcleft; } } #else arc = sp->xarc; sp->xarc = sp->oldxarc; sp->oldxarc = arc; if (MI_IS_USE3D(mi)) { arcleft = sp->xarcleft; sp->xarcleft = sp->oldxarcleft; sp->oldxarcleft = arcleft; } #endif #endif /* We set up the color for the next drawing */ if (!MI_IS_USE3D(mi) && MI_NPIXELS(mi) > 2 && (++sp->colorchange >= COLOR_CHANGES)) { sp->colorchange = 0; if (++sp->colorp >= MI_NPIXELS(mi)) sp->colorp = 0; sp->color = MI_PIXEL(mi, sp->colorp); } }
static void worm_doit(ModeInfo * mi, int which, unsigned long color) { Display *display = MI_DISPLAY(mi); Window window = MI_WINDOW(mi); GC gc = MI_GC(mi); wormstruct *wp = &worms[MI_SCREEN(mi)]; wormstuff *ws = &wp->worm[which]; int x, y, z; int diff; ws->tail++; if (ws->tail == wp->wormlength) ws->tail = 0; x = ws->circ[ws->tail].x; y = ws->circ[ws->tail].y; if (MI_WIN_IS_USE3D(mi)) { diff = ws->diffcirc[ws->tail]; if (MI_WIN_IS_INSTALL(mi)) { XSetForeground(display, gc, MI_NONE_COLOR(mi)); XFillRectangle(display, window, gc, x - diff, y, wp->circsize, wp->circsize); XFillRectangle(display, window, gc, x + diff, y, wp->circsize, wp->circsize); } else { XClearArea(display, window, x - diff, y, wp->circsize, wp->circsize, False); XClearArea(display, window, x + diff, y, wp->circsize, wp->circsize, False); } } else XClearArea(display, window, x, y, wp->circsize, wp->circsize, False); if (LRAND() & 1) ws->dir = (ws->dir + 1) % SEGMENTS; else ws->dir = (ws->dir + SEGMENTS - 1) % SEGMENTS; x = (ws->x + IRINT((float) wp->circsize * costab[ws->dir]) + wp->xsize) % wp->xsize; y = (ws->y + IRINT((float) wp->circsize * sintab[ws->dir]) + wp->ysize) % wp->ysize; ws->circ[ws->tail].x = x; ws->circ[ws->tail].y = y; ws->x = x; ws->y = y; if (MI_WIN_IS_USE3D(mi)) { if (LRAND() & 1) ws->dir2 = (ws->dir2 + 1) % SEGMENTS; else ws->dir2 = (ws->dir2 + SEGMENTS - 1) % SEGMENTS; /* for the z-axis the wrap-around looks bad, so worms should just turn around. */ z = (int) (ws->z + wp->circsize * sintab[ws->dir2]); if (z < 0 || z >= wp->zsize) z = (int) (ws->z - wp->circsize * sintab[ws->dir2]); diff = (int) (GETZDIFF(z) + 0.5); /* ROUND */ ws->diffcirc[ws->tail] = diff; ws->z = z; /* right eye */ color = 0; wp->rects[color * wp->maxsize + wp->size[color]].x = x + diff; wp->rects[color * wp->maxsize + wp->size[color]].y = y; wp->size[color]++; /* left eye */ color = 1; wp->rects[color * wp->maxsize + wp->size[color]].x = x - diff; wp->rects[color * wp->maxsize + wp->size[color]].y = y; wp->size[color]++; #if 0 if (ws->redrawing) { /* Too hard for now */ int j; for (j = 0; j < REDRAWSTEP; j++) { int k = (ws->tail - ws->redrawpos + wp->wormlength) % wp->wormlength; color = 0; wp->rects[color * wp->maxsize + wp->size[color]].x = ws->circ[k].x + ws->diffcirc[k]; wp->rects[color * wp->maxsize + wp->size[color]].y = ws->circ[k].y; wp->size[color]++; color = 1; wp->rects[color * wp->maxsize + wp->size[color]].x = ws->circ[k].x - ws->diffcirc[k]; wp->rects[color * wp->maxsize + wp->size[color]].y = ws->circ[k].y; wp->size[color]++; if (++(ws->redrawpos) >= wp->wormlength) { ws->redrawing = 0; break; } } } #endif } else { wp->rects[color * wp->maxsize + wp->size[color]].x = x; wp->rects[color * wp->maxsize + wp->size[color]].y = y; wp->size[color]++; if (ws->redrawing) { int j; ws->redrawpos++; /* Compensates for the changed ws->tail since the last callback. */ for (j = 0; j < REDRAWSTEP; j++) { int k = (ws->tail - ws->redrawpos + wp->wormlength) % wp->wormlength; wp->rects[color * wp->maxsize + wp->size[color]].x = ws->circ[k].x; wp->rects[color * wp->maxsize + wp->size[color]].y = ws->circ[k].y; wp->size[color]++; if (++(ws->redrawpos) >= wp->wormlength) { ws->redrawing = 0; break; } } } } }