⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 worms.c

📁 此书为Visual C++ 高级编程技术OpenGL篇
💻 C
字号:
#include <math.h>
#include <stdlib.h>
#include <sys/types.h>
#include <time.h>
#include <string.h>
#include <GL/glaux.h>

#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;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -