www.pudn.com > mworms.rar > WORMS.C


#include  
#include  
#include  
#include  
#include  
#include  
 
#ifdef WIN32 
#define drand48() (((float) rand())/((float) RAND_MAX))  
#define srand48() (srand(time(NULL))) 
#endif 
 
/* operational constants */ 
#define RADIAN .0174532 
#define CIRCLE_POINTS 25 
#define PI 3.1415926535897 
#define SIDETOLERANCE .01 
#define INITH 500 
#define INITW 500 
 
/* worm options */ 
#define SEGMENTS 20 
#define SEG_RADIUS 0.01 
#define STEPSIZE 0.01 
#define MAXTURN (20 * RADIAN)        /* in radians */ 
#define MAXWORMS 400 
#define INITWORMS 40 
#define MARKTICKS 100 
 
typedef struct worm_s { 
  float dir;                   /* direction in radians */ 
  float segx[SEGMENTS];        /* location of segments. */ 
  float segy[SEGMENTS]; 
  GLfloat *color;              /* pointer to the RGB color of the worm */ 
  int head;                    /* which elt of seg[xy] is currently head */ 
                               /* the tail is always (head+1 % SEGMENTS) */ 
} worm_t; 
 
 
const GLfloat colors[][3] = { 
  { 255,   0,   0},  { 238,   0,   0},  { 205,   0,   0},   
  {   0, 255,   0},  {   0, 238,   0},  {   0, 205,   0}, 
  {   0,   0, 255},  {   0,   0, 238},  {   0,   0, 205}, 
  { 255, 255,   0},  { 238, 238,   0},  { 205, 205,   0}, 
  {   0, 255, 255},  {   0, 238, 238},  {   0, 205, 205}, 
  { 255,   0, 255},  { 238,   0, 238},  { 205,   0, 205}, 
}; 
 
#define COLORS 18 
 
/* define's for the menu item numbers */ 
#define MENU_NULL          0 
#define MENU_FILLED        1 
#define MENU_UNFILLED      2 
#define MENU_QUIT          3 
 
/* flag to determine how to draw worms; set by popup menu -- starts out 
   filled in 
 */ 
int filled = 1; 
 
/* the global worm array */ 
worm_t worms[MAXWORMS]; 
int curworms = 0; 
 
/* global window extent variables */ 
GLfloat gleft = -1.0, gright = 1.0, gtop = 1.0, gbottom = -1.0; 
GLint wsize, hsize; 
 
/* globals for marking */ 
float markx, marky; 
int marktime; 
 
void drawCircle(float x0, float y0, float radius) 
{ 
  int i; 
  float angle; 
 
  /* a table of offsets for a circle (used in drawCircle) */ 
  static float circlex[CIRCLE_POINTS]; 
  static float circley[CIRCLE_POINTS]; 
  static int   inited = 0; 
 
  if (! inited) { 
    for (i = 0; i < CIRCLE_POINTS; i++) { 
      angle = 2.0 * PI * i / CIRCLE_POINTS; 
      circlex[i] = cos(angle); 
      circley[i] = sin(angle); 
    } 
    inited++; 
  }; 
 
  if (filled) 
    glBegin(GL_POLYGON); 
  else 
    glBegin(GL_LINE_LOOP); 
  for(i = 0; i < CIRCLE_POINTS; i++) 
    glVertex2f((radius * circlex[i]) + x0, (radius * circley[i]) + y0); 
  glEnd(); 
 
  return; 
} 
 
void drawWorm(worm_t *theworm) 
{ 
  int i; 
 
  glColor3fv(theworm->color); 
  for (i = 0; i < SEGMENTS; i++) 
    drawCircle(theworm->segx[i], theworm->segy[i], SEG_RADIUS); 
  return; 
} 
 
void myinit(void) 
{ 
  int i, j, thecolor; 
  float thedir; 
 
  srand48(time(NULL)); 
 
  curworms = INITWORMS; 
   
  for (j = 0; j < curworms; j++) { 
    /* divide the circle up into a number of pieces, and send one worm 
       each direction. 
     */ 
    worms[j].dir = ((2.0 * PI) / curworms) * j; 
    thedir = worms[j].dir; 
 
    worms[j].segx[0] = 0.0; 
    worms[j].segy[0] = 0.0; 
 
    for (i = 1; i < SEGMENTS; i++) { 
      worms[j].segx[i] = worms[j].segx[i-1] + (STEPSIZE * cos(thedir)); 
      worms[j].segy[i] = worms[j].segx[i-1] + (STEPSIZE * sin(thedir)); 
    }; 
    worms[j].head = (SEGMENTS - 1); 
 
    /* make this worm one of the predefined colors */ 
    thecolor = (int) COLORS * drand48(); 
    worms[j].color = (GLfloat *)colors[thecolor]; 
  }; 
} 
 
void warpWorms(void) 
{ 
  register int j, head; 
 
  for (j = 0; j < curworms; j++) { 
    head = worms[j].head; 
 
    if (worms[j].segx[head] < gleft) 
      worms[j].segx[head] = gleft; 
    if (worms[j].segx[head] > gright) 
      worms[j].segx[head] = gright; 
    if (worms[j].segx[head] > gtop) 
      worms[j].segx[head] = gtop; 
    if (worms[j].segx[head] < gbottom) 
      worms[j].segx[head] = gbottom;       
  } 
} 
 
void CALLBACK myreshape (GLsizei w, GLsizei h) 
{ 
  float ratiow = (float) w/INITW; 
  float ratioh = (float) h/INITH; 
 
  glViewport(0,0,w,h); 
  glMatrixMode(GL_PROJECTION); 
  glLoadIdentity(); 
 
  gleft = -1 * ratiow; 
  gright = 1 * ratiow; 
  gbottom = -1 * ratioh; 
  gtop = 1 * ratioh; 
 
  gluOrtho2D(gleft, gright, gbottom, gtop); 
  warpWorms(); 
 
  glMatrixMode(GL_MODELVIEW); 
  glLoadIdentity(); 
 
  wsize = w; hsize = h; 
 
  return; 
} 
 
void updateWorm(worm_t *theworm) 
{ 
  int newhead; 
  float prevx, prevy; 
  float newh = -1, newv = -1; 
  float num, denom; 
 
  newhead = (theworm->head + 1) % SEGMENTS; 
 
  prevx = theworm->segx[theworm->head]; 
  prevy = theworm->segy[theworm->head]; 
 
  if (marktime) { 
    num = marky - prevy; 
    denom = markx - prevx; 
    theworm->dir = atan2(num,denom); 
  }; 
 
  theworm->dir += (MAXTURN - (2 * MAXTURN * (float) drand48())); 
 
  theworm->segx[newhead] = prevx + (STEPSIZE * cos(theworm->dir)); 
  theworm->segy[newhead] = prevy + (STEPSIZE * sin(theworm->dir)); 
 
  if (theworm->segx[newhead] <= gleft) 
    theworm->dir = 0; 
  if (theworm->segx[newhead] >= gright) 
    theworm->dir = (180 * RADIAN); 
  if (theworm->segy[newhead] >= gtop) 
    theworm->dir = (270 * RADIAN); 
  if (theworm->segy[newhead] <= gbottom) 
    theworm->dir = (90 * RADIAN); 
 
  if ((newv >= 0) || (newh >= 0)) { 
    newh = (newh<0) ? 0 : newh; 
    newv = (newv<0) ? 0 : newv; 
  }; 
 
  theworm->head = newhead; 
}   
 
void CALLBACK myidle (void) 
{ 
  register int i, tail; 
 
  if (marktime) 
    marktime--; 
 
  for (i = 0; i < curworms; i++) { 
    /* first find tail */ 
    tail = (worms[i].head + 1) % SEGMENTS; 
   
    /* erase tail */ 
    glColor3f(0.0, 0.0, 0.0); 
    drawCircle(worms[i].segx[tail], worms[i].segy[tail], SEG_RADIUS); 
 
    /* update head segment position and head pointer */ 
    updateWorm(&worms[i]); 
 
    /* draw head */ 
    glColor3f(worms[i].color[0]/255.0f, worms[i].color[1]/255.0f, worms[i].color[2]/255.0f); 
    drawCircle(worms[i].segx[worms[i].head], worms[i].segy[worms[i].head], 
	       SEG_RADIUS); 
  }; 
  glFlush(); 
  auxSwapBuffers(); 
  return; 
} 
 
void markSpot(int x, int y) 
{ 
  /* map into the corridinate space I am using */ 
  markx = (float)((x - wsize/2)*(gright - gleft)/wsize); 
  marky = -(float)((y - hsize/2)*(gtop - gbottom)/hsize); 
 
  marktime = MARKTICKS; 
} 
 
void CALLBACK mouse(AUX_EVENTREC *event) 
{ 
  GLint x, y; 
 
  x = event->data[AUX_MOUSEX]; 
  y = event->data[AUX_MOUSEY]; 
  markSpot(x,y); 
} 
 
int main(int argc, char **argv) 
{ 
  int fillmenu = 0; 
 
  auxInitDisplayMode(AUX_DOUBLE | AUX_RGB); 
  auxInitPosition(0, 0, INITW, INITH); 
  auxInitWindow("Worms"); 
  auxIdleFunc(myidle); 
  myinit(); 
  auxReshapeFunc(myreshape); 
  auxMouseFunc(AUX_LEFTBUTTON,AUX_MOUSEDOWN,mouse); 
  auxMainLoop(myidle); 
  return 0; 
}