Esempio n. 1
0
static void do_twinkle(Display *dpy, Window window) {
  Colormap cmap;
  XWindowAttributes xgwa;
  int got_color = 0;
  XColor color[maxps];
  XColor bgcolor;
  int p,f,nt, sx,sy, resets,lastresets,cnt;

  XClearWindow (dpy, window);
  XGetWindowAttributes (dpy, window, &xgwa);
  cmap = xgwa.colormap;
  scrwid = xgwa.width;
  scrhei = xgwa.height;

  /* Setup colours */
  hsv_to_rgb (0.0, 0.0, 0.0, &bgcolor.red, &bgcolor.green, &bgcolor.blue);
  got_color = XAllocColor (dpy, cmap, &bgcolor);
  for (p=0;p<ps;p++) {
        if (!mono_p)
          hsv_to_rgb (random()%360, .6+.4*myrnd(), .6+.4*myrnd(), &color[p].red, &color[p].green, &color[p].blue);
          /* hsv_to_rgb (random()%360, 1.0, 1.0, &color[p].red, &color[p].green, &color[p].blue);   for stronger colours! */
        if ((!mono_p) && (got_color = XAllocColor (dpy, cmap, &color[p]))) {
        } else {
          if (p>0)
            color[p]=color[0];
          else
            color[p].pixel=default_fg_pixel;
        }
  }

  /* Set up parameter movements for the different forcefields */
  name[1] = "Velocity";
  op[1] = 1; damp[1] = .999; force[1] = .002;
  name[2] = "Rotation";
  op[2] = 0; damp[2] = .999; force[2] = .002;
  name[3] = "Drip";
  op[3] = 1; damp[3] = .999; force[3] = .005;
  name[4] = "Dribble";
  op[4] = 1; damp[4] = .999; force[4] = .005;
  name[5] = "Slide";
  op[5] = 0; damp[5] = .999; force[5] = .002;
  name[6] = "Accelerate";
  op[6] = 1.0; damp[6] = .999; force[6] = .005;
  name[7] = "xDisplace";
  op[7] = 0; damp[7] = .999; force[7] = .005;
  name[8] = "yDisplace";
  op[8] = 0; damp[8] = .999; force[8] = .005;
  /* 0 and 9 are options for splitting displacements [no var] */
  name[0] = "Split";
  op[0] = 0; damp[0] = 0; force[0] = 0;
  name[9] = "2d/3d split";
  op[9] = 0; damp[9] = 0; force[9] = 0;

  /* Initialise parameters to optimum, all off */
  for (f=0;f<fs;f++) {
    var[f]=op[f];
    fon[f]=0;
  }

  /* Initialise stars */
  for (p=0;p<ps;p++)
    stars_newp(p);

  /* tx[nt],ty[nt] remeber earlier screen plots (tails of stars)
     which are deleted when nt comes round again */
  nt=0;
  resets=0;

  while (1) {

      /* Move current points */
      lastresets=resets;
      resets=0;
      for (p=0;p<ps;p++) {
        /* Erase old */
        XSetForeground (dpy, draw_gc, bgcolor.pixel);
        XDrawPoint(dpy,window,draw_gc,tx[nt],ty[nt]);

        /* Move */
        stars_move(p);
        /* If moved off screen, create a new one */
        if (cx[p]<-1.0 || cx[p]>+1.0 ||
            cy[p]<-1.0 || cy[p]>+1.0 ||
            fabs(cx[p])<.001 || fabs(cy[p])<.001) {
          stars_newp(p);
          resets++;
        } else if (myrnd()>0.99) /* Reset at random */
          stars_newp(p);

        /* Draw point */
        sx=stars_scrpos_x(p);
        sy=stars_scrpos_y(p);
        XSetForeground (dpy, draw_gc, color[p].pixel);
        XDrawPoint(dpy,window,draw_gc,sx,sy);

        /* Remember it for removal later */
        tx[nt]=sx;
        ty[nt]=sy;
        nt=(nt+1)%(ps*ts);
      }

      /* Adjust force fields */
      cnt=0;
      for (f=0;f<fs;f++) {

        if (meters) { /* Remove meter from display */
          XSetForeground(dpy, draw_gc, bgcolor.pixel);
          stars_draw_meter(dpy,window,draw_gc,f);
        }

        /* Adjust forcefield's parameter */
        var[f]=stars_perturb(var[f],op[f],damp[f],force[f]);

        if (myrnd()>0.998) /* Turn it on/off ? */
          fon[f]=(myrnd()<0.0);
          /* fon[f]=!fon[f]; */

        if (meters) { /* Redraw the meter */
          XSetForeground(dpy, draw_gc, color[f].pixel);
          stars_draw_meter(dpy,window,draw_gc,f);
        }

        if (fon[f])
          cnt++;
      }
      if (cnt==0) { /* Ensure at least one is on! */
        f=random() % fs;
        fon[f]=1;
      }
      if (meters) {
        XSetForeground(dpy, draw_gc, bgcolor.pixel);
        XDrawRectangle(dpy,window,draw_gc,0,0,lastresets*5,3);
        XSetForeground(dpy, draw_gc, default_fg_pixel);
        XDrawRectangle(dpy,window,draw_gc,0,0,resets*5,3);
      }
/*      if (resets*5>scrwid) {
       Turn one off a field if too many points are flying off screen */
      /* This was a problem when one of the force-fields was acting wrong,
         but not really needed any more unless we need to debug new ones ...! */
        /* for (f=0;f<fs;f++)
            if (fon[f])
            printf("%i",f);
          printf("\n");
          XSync (dpy, False);
          screenhack_handle_events (dpy);
         sleep(1);
        do { // In fact this bit might go wrong if
          f=random() % fs; // we have not ensured at least one is on (above)
        } while (!fon[f]);
        fon[f]=0;
      }            */

        XSync (dpy, False);
        screenhack_handle_events (dpy);

  }

}
Esempio n. 2
0
static unsigned long
whirlwindwarp_draw (Display *dpy, Window window, void *closure)
{
  struct state *st = (struct state *) closure;

  /* time_t lastframe = time((time_t) 0); */

  if (!st->initted) {
    st->initted = 1;

    XClearWindow (st->dpy, st->window);
    XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
    st->scrwid = st->xgwa.width;
    st->scrhei = st->xgwa.height;

    st->starsize=st->scrhei/480;
    if (st->starsize<=0)
      st->starsize=1;

    /* Setup colours */
    hsv_to_rgb (0.0, 0.0, 0.0, &st->bgcolor.red, &st->bgcolor.green, &st->bgcolor.blue);
    st->got_color = XAllocColor (st->dpy, st->xgwa.colormap, &st->bgcolor);
    st->colsavailable=0;
    for (st->p=0;st->p<st->ps;st->p++) {
      if (!mono_p)
        hsv_to_rgb (random()%360, .6+.4*myrnd(), .6+.4*myrnd(), &st->color[st->p].red, &st->color[st->p].green, &st->color[st->p].blue);
      /* hsv_to_rgb (random()%360, 1.0, 1.0, &color[p].red, &color[p].green, &color[p].blue);   for stronger colours! */
      if ((!mono_p) && (st->got_color = XAllocColor (st->dpy, st->xgwa.colormap, &st->color[st->p]))) {
        st->colsavailable=st->p;
      } else {
        if (st->colsavailable>0) /* assign colours from those already allocated */
          st->color[st->p]=st->color[ st->p % st->colsavailable ];
        else
          st->color[st->p].pixel=st->default_fg_pixel;
      }
    }

  /* Set up central (optimal) points for each different forcefield */
  st->op[1] = 1; st->name[1] = "Warp";
  st->op[2] = 0; st->name[2] = "Rotation";
  st->op[3] = 1; st->name[3] = "Horizontal asymptote";
  st->op[4] = 0; st->name[4] = "Vertical asymptote";
  st->op[5] = 1; st->name[5] = "Vertical asymptote right";
  st->op[6] = 1; st->name[6] = "Squirge x";
  st->op[7] = 1; st->name[7] = "Squirge y";
  st->op[0] = 0; st->name[0] = "Split number (inactive)";
  st->op[8] = 0; st->name[8] = "Split velocity x";
  st->op[9] = 0; st->name[9] = "Split velocity y";
  st->op[10] = 0; st->name[10] = "Horizontal wave amplitude";
  st->op[11] = myrnd()*3.141; st->name[11] = "Horizontal wave phase (inactive)";
  st->op[12] = 0.01; st->name[12] = "Horizontal wave frequency (inactive)";
  st->op[13] = 0; st->name[13] = "Vertical wave amplitude";
  st->op[14] = myrnd()*3.141; st->name[14] = "Vertical wave phase (inactive)";
  st->op[15] = 0.01; st->name[15] = "Vertical wave frequency (inactive)";

  /* Initialise parameters to optimum, all off */
  for (st->f=0;st->f<fs;st->f++) {
    st->var[st->f]=st->op[st->f];
    st->fon[st->f]=( myrnd()>0.5 ? 1 : 0 );
    st->acc[st->f]=0.02 * myrnd();
    st->vel[st->f]=0;
  }

  /* Initialise stars */
  for (st->p=0;st->p<st->ps;st->p++)
    stars_newp(st, st->p);

  /* tx[nt],ty[nt] remember earlier screen plots (tails of stars)
     which are deleted when nt comes round again */
  st->nt = 0;
  st->resets = 0;

  st->hue = 180 + 180*myrnd();

  gettimeofday(&st->lastframe, NULL);

  }


    if (myrnd()>0.75) {
      /* Change one of the allocated colours to something near the current hue. */
      /* By changing a random colour, we sometimes get a tight colour spread, sometime a diverse one. */
      int pp = st->colsavailable * (0.5+myrnd()/2);
      hsv_to_rgb (st->hue, .6+.4*myrnd(), .6+.4*myrnd(), &st->color[pp].red, &st->color[pp].green, &st->color[pp].blue);
      if ((!mono_p) && (st->got_color = XAllocColor (st->dpy, st->xgwa.colormap, &st->color[pp]))) {
      }
      st->hue = st->hue + 0.5 + myrnd()*9.0;
      if (st->hue<0) st->hue+=360;
      if (st->hue>=360) st->hue-=360;
    }

      /* Move current points */
      st->lastresets=st->resets;
      st->resets=0;
      for (st->p=0;st->p<st->ps;st->p++) {
        /* Erase old */
        XSetForeground (st->dpy, st->draw_gc, st->bgcolor.pixel);
        /* XDrawPoint(dpy,window,draw_gc,tx[nt],ty[nt]); */
        XFillRectangle(st->dpy,st->window,st->draw_gc,st->tx[st->nt],st->ty[st->nt],st->starsize,st->starsize);

        /* Move */
        stars_move(st, st->p);
        /* If moved off screen, create a new one */
        if (st->cx[st->p]<=-0.9999 || st->cx[st->p]>=+0.9999 ||
            st->cy[st->p]<=-0.9999 || st->cy[st->p]>=+0.9999 ||
            fabs(st->cx[st->p])<.0001 || fabs(st->cy[st->p])<.0001) {
          stars_newp(st, st->p);
          st->resets++;
        } else if (myrnd()>0.99) /* Reset at random */
          stars_newp(st, st->p);

        /* Draw point */
        st->sx=stars_scrpos_x(st, st->p);
        st->sy=stars_scrpos_y(st, st->p);
        XSetForeground (st->dpy, st->draw_gc, st->color[st->p].pixel);
        /* XDrawPoint(dpy,window,draw_gc,sx,sy); */
        XFillRectangle(st->dpy,st->window,st->draw_gc,st->sx,st->sy,st->starsize,st->starsize);

        /* Remember it for removal later */
        st->tx[st->nt]=st->sx;
        st->ty[st->nt]=st->sy;
        st->nt=(st->nt+1)%(st->ps*st->ts);
      }

      /* Adjust force fields */
      st->cnt=0;
      for (st->f=0;st->f<fs;st->f++) {

        if (st->meters) { /* Remove meter from display */
          XSetForeground(st->dpy, st->draw_gc, st->bgcolor.pixel);
          stars_draw_meter(st,st->f);
        }

        /* Adjust forcefield's parameter */
        if (st->fon[st->f]) {
          /* This configuration produces var[f]s usually below 0.01 */
          st->acc[st->f]=stars_perturb(st->acc[st->f],0,0.98,0.005);
          st->vel[st->f]=stars_perturb(st->vel[st->f]+0.03*st->acc[st->f],0,0.995,0.0);
          st->var[st->f]=st->op[st->f]+(st->var[st->f]-st->op[st->f])*0.9995+0.001*st->vel[st->f];
        }
        /* fprintf(stderr,"f=%i fon=%i acc=%f vel=%f var=%f\n",f,fon[f],acc[f],vel[f],var[f]); */

        /* Decide whether to turn this forcefield on or off. */
        /* prob_on makes the "splitting" effects less likely than the rest */
        #define prob_on ( st->f==8 || st->f==9 ? 0.999975 : 0.9999 )
        if ( st->fon[st->f]==0 && myrnd()>prob_on ) {
          turn_on_field(st, st->f);
        } else if ( st->fon[st->f]!=0 && myrnd()>0.99 && fabs(st->var[st->f]-st->op[st->f])<0.0005 && fabs(st->vel[st->f])<0.005 /* && fabs(acc[f])<0.01 */ ) {
          /* We only turn it off if it has gently returned to its optimal (as opposed to rapidly passing through it). */
          st->fon[st->f] = 0;
        }

        if (st->meters) { /* Redraw the meter */
          XSetForeground(st->dpy, st->draw_gc, st->color[st->f].pixel);
          stars_draw_meter(st,st->f);
        }

        if (st->fon[st->f])
          st->cnt++;
      }

      /* Ensure at least three forcefields are on.
       * BUG: Picking randomly might not be enough since 0,11,12,14 and 15 do nothing!
       * But then what's wrong with a rare gentle twinkle?!
      */
      if (st->cnt<3) {
        st->f=random() % fs;
        turn_on_field(st, st->f);
      }

      if (st->meters) {
        XSetForeground(st->dpy, st->draw_gc, st->bgcolor.pixel);
        XDrawRectangle(st->dpy,st->window,st->draw_gc,0,0,st->lastresets*5,3);
        XSetForeground(st->dpy, st->draw_gc, st->default_fg_pixel);
        XDrawRectangle(st->dpy,st->window,st->draw_gc,0,0,st->resets*5,3);
      }

      /* Cap frames per second; do not go above specified fps: */
      {
        unsigned long this_delay = 0;
        int maxfps = 200;
        long utimeperframe = 1000000/maxfps;
        struct timeval now;
        long timediff;
        gettimeofday(&now, NULL);
        timediff = now.tv_sec*1000000 + now.tv_usec - st->lastframe.tv_sec*1000000 - st->lastframe.tv_usec;
        if (timediff < utimeperframe) {
          /* fprintf(stderr,"sleeping for %i\n",utimeperframe-timediff); */
          this_delay = (utimeperframe-timediff);
        }
        st->lastframe = now;

        return this_delay;
      }
}