home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h> /* For NULL */
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- #include <X11/cursorfont.h> /* For erasing cursor - not important */
- #include <math.h>
-
- /* Indexes for 1st dimension of obj */
- /* The order they are in is important */
- #define AST 0
- #define ENEMY 96
- #define ENEMYBUL 97
- #define FBUL 98
- #define LASTBUL 102
- #define SHIP 103
- #define LASTOBJ 103 /* Must be ship! See makeasts(). */
-
- /* Shapes */
- /* Order is important! See collide(). */
- #define ASTSHAPE1 0
- #define ASTSHAPE2 1
- #define ASTSHAPE3 2
- #define ENBULSH 3
- #define BULSHAPE 4
- #define SHIPSHAPE 5
- #define SHIPTHRSHAPE 6
- #define ENEMYSHAPE 7
- #define LASTSHAPE 7
-
- /* Masses */
- #define M_BIG 8.0
- #define M_MED 4.0
- #define M_SMALL 1.0
- #define M_SHIP 1.5
- #define M_ENEMY 1.0
- #define M_BULLET 0.1
-
- /* Keys */
- #define FIRE 'p'
- #define PAUSE 27 /* escape */
- #define SHIELD '`'
- #define THRUST 'o'
-
- #define BMAX 300 /* Max particles in a "boom" + 1 */
- #define letheight 20 /* height of font */
- #define pi 3.1415926535897932384
- #define SHIPSIZE 28
-
- typedef struct _Boom *Boom;
- struct _Boom {Boom next; int dur, part; double bcoord[BMAX][2], bvec[BMAX][2]};
- typedef struct {int shape, alive, time;
- double mass, x, y, xvel, yvel, rot, rotvel} Objtype;
- typedef struct {double angle; int length} PolarPair;
- typedef struct {double x, y, mag} Vector;
-
- /* Global variables: */
- Objtype obj[SHIP+1];
- /* In shapes pairs, 1st # is radians, 2nd is length in pixels.
- Degrees: 0 ->, pi/2 down, pi <-, 3*pi/2 up
- IF YOU CHANGE THE SHAPES, you MUST change numpairs & shapesize
- */
- PolarPair shapes[LASTSHAPE+1][11] =
- { {{0,0}, {3*pi/2,40}, {0,20}, {pi/4,28}, {pi/2,40}, /* just crossed 0-deg line */
- {3*pi/4,28},{pi,40},{5*pi/4,28},{3*pi/2,40},{7*pi/4,28},{0,20}},
- /* hexagon if you prefer
- {{0,0}, {3*pi/2, 20}, {pi/6, 20}, {pi/2, 20},
- {5*pi/6, 20}, {7*pi/6, 20}, {3*pi/2, 20}, {11*pi/6, 20}},
- */
- {{0,0}, {3*pi/2,20}, {0,10}, {pi/4,14}, {pi/2,20},
- {3*pi/4,14},{pi,20},{5*pi/4,14},{3*pi/2,20},{7*pi/4,14},{0,10}},
- {{0,0}, {3*pi/2,10}, {0,5}, {pi/4,7}, {pi/2,10},
- {3*pi/4,7},{pi,10},{5*pi/4,7},{3*pi/2,10},{7*pi/4,7},{0,5}},
- {{0,0}, {7*pi/4, 4}, {pi/4, 4}, {3*pi/4, 4}, {5*pi/4, 4}},
- {{0,0}, {0,10}},
- {{0,0}, {5*pi/4,28}, {0,20}, {pi/4,28},{3*pi/4,28},{pi,20},{7*pi/4,28}}, /* Ship */
- {{0,0}, {5*pi/4,28}, {0,20}, {pi/4,28},{3*pi/4,28},{pi,20},
- {7*pi/4,28}, {3*pi/4, 7}, {9*pi/8, 13}, {15*pi/8, 13}}, /* Thrusting ship */
- {{0,0}, {pi,20},{7*pi/4,28},{pi/4,28},{pi,20}}
- };
- Boom blist = NULL;
- double drawscale = 1, speedscale = 1;
- int width, height,
- energy, /* # of turns shield is good for */
- highscore = 0,
- nextbul = FBUL, /* Obj# of next bullet fired */
- numasts, oldscore = 99,
- rndint = 73, ships, score,
- numpairs[LASTSHAPE+1] = {11, 11, 11, 5, 2, 7, 10, 5},
- shapesize[LASTSHAPE+1] = {44, 21, 10, 2, 1, SHIPSIZE+1, 35, 20},
- shield_on;
-
- initasts()
- { int i;
- extern Objtype obj[SHIP+1];
-
- for (i = 0; i < LASTOBJ+1; i++)
- { obj[i].rot = 0;
- obj[i].rotvel = 0;
- }
- for (i = 0; i < ENEMY; i++)
- { obj[i].shape = ASTSHAPE1;
- }
- obj[SHIP].shape = SHIPSHAPE;
- obj[SHIP].mass = M_SHIP;
- obj[ENEMY].shape = ENEMYSHAPE;
- obj[ENEMY].mass = M_ENEMY;
- obj[ENEMYBUL].shape = ENBULSH;
- obj[ENEMYBUL].mass = M_BULLET;
- for (i = FBUL; i < LASTBUL+1; i++)
- { obj[i].shape = BULSHAPE;
- obj[i].mass = M_BULLET;
- } }
-
- makeasts(level)
- { int i;
- extern Objtype obj[SHIP+1];
- extern int numasts, rndint;
- extern double speedscale;
- unsigned char a;
-
- for (i = 0; i < SHIP; i++)
- obj[i].alive = 0; /* Erase objs from last level except ship */
- for (i = ENEMYBUL; i < LASTBUL+1; i++)
- obj[i].time = 0; /* No bullets in the air */
- for (i = 0; i < level+4; i++) /* Asteroids: */
- { a = rand(rndint); a>>=1; /* a = rand# from 0 to 127 */
- if (a > 63)
- obj[i].x = (double) a;
- else obj[i].x = (double) (width - a);
- a = rand(rndint); a>>=1; /* Now the same for y */
- if (a > 63)
- obj[i].y = (double) a;
- else obj[i].y = (double) height - a;
- a = rand(rndint); a = 4 - a>>5;
- obj[i].rot = (double) a;
- a = rand(rndint);
- obj[i].rotvel = ((double) a)/2048;
- a = rand(rndint);
- obj[i].xvel = cos((double) a);
- obj[i].yvel = sin((double) a);
- obj[i].shape = ASTSHAPE1;
- obj[i].mass = M_BIG;
- obj[i].alive = 1;
- }
- numasts = i;
- }
-
- makeenemy(level) /* Start an enemy ship */
- int level;
- { extern Objtype obj[SHIP+1];
- extern int height, rndint;
- unsigned char c;
-
- obj[ENEMY].alive = 1;
- obj[ENEMY].x = 0;
- obj[ENEMY].y = (double) height/4;
- c = rand(rndint); obj[ENEMY].y += (double) c; /* May put enemy outside window */
- obj[ENEMY].xvel = (double) level/2;
- obj[ENEMY].yvel = 0;
- }
-
- int nextast() /* Find next unused asteroid object */
- { extern Objtype obj[SHIP+1];
- int i;
- for (i = 0; obj[i].alive; i++); /* guaranteed to find one */
- return i;
- }
-
- int collide(i, j) /* Returns non-zero if i collided with j */
- /* Ship must be j! (See below) */
- int i, j;
- { extern Objtype obj[SHIP+1];
- extern int shapesize[LASTSHAPE+1];
- extern double drawscale;
- double mi, mj, /* Slopes of lines */
- ix1, ix2, iy1, iy2, jx1, jx2, jy1, jy2, /* Endpoints */
- roti, rotj,
- xcross, ycross, /* coord of intersection */
- z;
- int diff, xd, yd,
- a, b,
- shapei, shapej;
- xd = obj[i].x - obj[j].x;
- yd = obj[i].y - obj[j].y;
- diff = sqrt((double)(xd*xd + yd*yd));
- shapei = obj[i].shape; shapej = obj[j].shape;
- /* Note this will miss if drawscale is < 0 */
- if (diff < (shapesize[shapei] + shapesize[shapej])*drawscale)
- { /* If both are round objects, approximation is good */
- if (shapei < SHIPSHAPE && shapej < SHIPSHAPE) return 1;
- if (j == SHIP && shield_on) return 1; /* Ship always j! */
- roti = obj[i].rot; rotj = obj[j].rot;
- ix1 = (double) obj[i].x; iy1 = (double) obj[i].y;
- for (a = 1; a < numpairs[shapei]; a++)
- { ix2 = ix1 + (double) shapes[shapei][a].length * drawscale *
- cos(shapes[shapei][a].angle + roti);
- iy2 = iy1 + (double) shapes[shapei][a].length * drawscale *
- sin(shapes[shapei][a].angle + roti);
- if (ix1 == ix2)
- { printf("\nif1 = if2"); return 1;} /* Easy way out */
- mi = (iy2-iy1)/(ix2-ix1);
- z = mi*ix1;
- jx1 = (double) obj[j].x; jy1 = (double) obj[j].y;
- for (b = 1; b < numpairs[shapej]; b++)
- { jx2 = jx1 + (double) shapes[shapej][b].length *
- drawscale * cos(shapes[shapej][b].angle + rotj);
- jy2 = jy1 + (double) shapes[shapej][b].length *
- drawscale * sin(shapes[shapej][b].angle + rotj);
- if (jx1 == jx2)
- { ycross = ix1 + (jx1-ix1)*mi;
- if ((jx1-ix1) * (ix2-jx1) >= 0 &&
- (ycross-jy1)*(jy2-ycross) >= 0)
- return 1;
- else jx2 += .0001; /* Avoid divide by 0 */
- }
- mj = (jy2-jy1)/(jx2-jx1);
- if (mj == mi) goto Loopend; /* Parallel lines */
- xcross = (iy1 - jy1 + mj*jx1 - z) / (mj - mi);
- if ((xcross-ix1) * (ix2-xcross) > 0
- && (xcross-jx1) * (jx2-xcross) > 0) return 1;
- Loopend: jx1 = jx2; jy1 = jy2;
- }
- ix1 = ix2; iy1 = iy2;
- } }
- return 0;
- }
-
- blastpair(i, j) /* Generate random velocity vector v. */
- int i, j ; /* Add v to i, -v to j. */
- { extern int rndint;
- extern Objtype obj[SHIP+1];
- unsigned char c; /* for rand */
- double vx, vy;
- c = rand(rndint);
- /* c = 4 - c>>5; if you need angles from -3 to 4 */
- c>>2; /* possibly save some time on sin/cos */
- vx = cos((double) c); vy = sin((double) c);
- obj[i].xvel = obj[i].xvel + vx;
- obj[i].yvel = obj[i].yvel + vy;
- obj[j].xvel = obj[j].xvel - vx;
- obj[j].yvel = obj[j].yvel - vy;
- obj[i].rotvel = obj[i].rotvel + .05;
- obj[j].rotvel = obj[j].rotvel - .05;
- }
-
- /* dot product of 2 vectors */
- #define dot(i,j) (i.x*j.x + i.y*j.y)
- /* rotational inertia (constant eliminated) of obj. i */
- #define rotinert(i) (double) (obj[i].mass*shapesize[obj[i].shape]*shapesize[obj[i].shape])
-
- /* cause two objects to collide elastically */
- bounce(i, j)
- int i,j;
- {
- double rotrat, temp;
- extern Objtype obj[SHIP+1];
- Vector vi, vj, /* velocity of objs i, j */
- ij, /* vector from center of i to center of j */
- vi_ij, vj_ij, /* velocity of obj along vector ij */
- vipij, vjpij, /* velocity perpendicular to ij */
- vi_ijf, vj_ijf; /* post-collision velocity along ij */
-
- vi.x = obj[i].xvel; vi.y = obj[i].yvel;
- vj.x = obj[j].xvel; vj.y = obj[j].yvel;
- ij.x = obj[j].x - obj[i].x; ij.y = obj[j].y - obj[i].y;
- ij.mag = sqrt(ij.x*ij.x + ij.y*ij.y);
- /*
- Calculate velocities projected onto ij;
- vi_ij = vi*cos(a) = (vi dot ij) / |ij| */
- vi_ij.mag = dot(vi, ij) / ij.mag;
- vi_ij.x = (ij.x * vi_ij.mag) / ij.mag;
- vi_ij.y = (ij.y * vi_ij.mag) / ij.mag;
- vj_ij.mag = dot(vj, ij) / ij.mag;
- vj_ij.x = (ij.x * vj_ij.mag) / ij.mag;
- vj_ij.y = (ij.y * vj_ij.mag) / ij.mag;
- if (vi_ij.mag - vj_ij.mag < 0) /* Objs moving away from each other -
- Since objs are round (at least when bouncing), this means
- they are moving away from each other already. */
- return;
- /*
- Calculate component of velocities perpendicular to ij:
- |vipij| = |vi|*sin(a) = |vi x ij| / |ij|
- Same as
- |vipij| = |vi|*cos(pi/2 - a) = (vi dot (perp. to ij)) / |ij| */
- temp = vi.y*ij.x - vi.x*ij.y; /* - (cross product when 3rd coord is 0)*/
- temp /= (ij.mag*ij.mag);
- vipij.x = -ij.y*temp; vipij.y = ij.x*temp;
- temp = (vj.x*ij.y - vj.y*ij.x) / (ij.mag*ij.mag);
- vjpij.x = -ij.y*temp; vjpij.y = ij.x*temp;
- /*
- Calculate the linear elastic collision along ij:
- mass(i)*vi_ij + mass(j)*vj_ij = mass(i)*vi_ijf + mass(j)*vj_ijf
- vi_ij + vi_ijf = vj_ij + vj_ijf (derived by dividing equation
- for conservation of kinetic energy by eq. for cons. of momentum) */
- temp = obj[i].mass/obj[j].mass;
- vj_ijf.x = (temp * (2*vi_ij.x - vj_ij.x) + vj_ij.x) / (1 + temp);
- vj_ijf.y = (temp * (2*vi_ij.y - vj_ij.y) + vj_ij.y) / (1 + temp);
- vi_ijf.x = vj_ijf.x + vj_ij.x - vi_ij.x;
- vi_ijf.y = vj_ijf.y + vj_ij.y - vi_ij.y;
- /*
- Now, given vi_ijf and vj_ijf, add them to the perpendicular
- components to get final velocity vectors */
- obj[i].xvel = vi_ijf.x + vipij.x;
- obj[i].yvel = vi_ijf.y + vipij.y;
- obj[j].xvel = vj_ijf.x + vjpij.x;
- obj[j].yvel = vj_ijf.y + vjpij.y;
- /*
- Now calculate rotational velocity exchange */
- rotrat = rotinert(i)/rotinert(j);
- temp = rotrat * (2*obj[i].rotvel - obj[j].rotvel) / (1+rotrat);
- obj[i].rotvel = temp + obj[j].rotvel - obj[i].rotvel;
- obj[j].rotvel = temp;
- }
-
- botline(disp, window, gc) /* Print status line text */
- Display *disp;
- Drawable window;
- GC gc;
- { extern int highscore, ships, score;
- char text[70];
- sprintf(text, "Ships:%2d Score:%6d Shield: High:%6d",
- ships, score, highscore);
- XDrawImageString (disp, window, gc, 0, height+letheight,
- text, strlen(text));
- }
-
- printss(disp, window, gc) /* Print ships and score */
- Display *disp;
- Drawable window;
- GC gc;
- { extern int height, highscore, oldscore, ships, score;
- extern Objtype obj[SHIP+1]; /* to kill ship */
- char sstring[30];
-
- if (score != oldscore)
- { if (score/10000 > oldscore/10000)
- { ships++; botline(disp, window, gc);}
- if (score/10000 < oldscore/10000)
- { ships--; botline(disp, window, gc);
- if (!ships) obj[SHIP].alive = 0;
- }
- if (score > highscore) /* Separate if to avoid flashing */
- { highscore = score;
- sprintf(sstring, "%6d", highscore);
- XDrawImageString (disp, window, gc, 460,
- height+letheight, sstring, strlen(sstring));
- }
- sprintf(sstring, "%6d", score);
- XDrawImageString (disp, window, gc, 170, height+letheight,
- sstring, strlen(sstring));
- oldscore = score;
- }
-
- /* Draw shield energy bar */
- XFillRectangle(disp, window, gc, 340, height+8, energy>>1, 10);
- XClearArea(disp, window, 340+(energy>>1), height+8, 8, 10, False);
- }
-
- upscore(killer, up) /* Only award score for things the player shot */
- int killer, up;
- { extern int score;
- if (killer != ENEMYBUL && killer != SHIP)
- score = score + up;
- }
-
- /* boom, movebooms, drawbooms all by Peter Phillips */
- boom(ob, particles, duration)
- int ob;
- int particles;
- int duration;
- { extern int rndint;
- int i;
- unsigned int r1, r2;
- Boom b;
- double x, y;
- double angle, length;
-
- b = (Boom) malloc(sizeof(struct _Boom));
- b->dur = duration;
- b->part = particles;
- x = obj[ob].x;
- y = obj[ob].y;
- for (i = 0; i < particles; i++) {
- r1 = (rand(rndint) >> 2) % 100;
- r2 = (rand(rndint) >> 2) % 7;
-
- b->bcoord[i][0] = x;
- b->bcoord[i][1] = y;
- angle = r1 * pi / 50.0;
- length = 3 + r2;
- b->bvec[i][0] = cos(angle) * length + obj[ob].xvel;
- b->bvec[i][1] = sin(angle) * length + obj[ob].yvel;
- }
- b->next = blist;
- blist = b;
- }
-
- /* move the various booms that are active */
- movebooms()
- {
- int i;
- Boom b, prevb;
-
- prevb = NULL;
- b = blist;
- while (b != NULL) {
- b->dur--;
- if (b->dur < 0) { /* delete this boom */
- Boom temp;
-
- temp = b;
- if (prevb == NULL) {
- blist = b->next;
- } else {
- prevb->next = b->next;
- }
- b = b->next;
- free(temp);
- } else { /* move boom, advance list */
- for (i = 0; i < b->part; i++) {
- b->bcoord[i][0] += b->bvec[i][0];
- b->bcoord[i][1] += b->bvec[i][1];
- }
- prevb = b;
- b = b->next;
- }
- }
- }
-
- /* Draw the various booms */
- drawbooms(disp, window, gc)
- Display *disp;
- Drawable window;
- GC gc;
- {
- int i;
- Boom b;
- XPoint figure[BMAX];
-
- b = blist;
- while (b != NULL) {
- for (i = 0; i < b->part; i++) {
- figure[i].x = (int) b->bcoord[i][0];
- figure[i].y = (int) b->bcoord[i][1];
- }
- XDrawPoints(disp, window, gc, figure, b->part, CoordModeOrigin);
- b = b->next;
- }
- }
-
- deletebooms() /* delete all booms */
- { Boom b;
-
- b = blist;
- while (b != NULL)
- { b->dur = 0;
- b = b->next;
- } }
-
- killast(killer, i)
- int killer, i; /* i = Asteroid # to kill */
- { extern Objtype obj[SHIP+1];
- extern int numasts;
- int k, na, oldna;
-
- if (obj[i].shape == ASTSHAPE1)
- { na = nextast(); /* Could put 6 lines in a sub */
- obj[na].x = obj[i].x;
- obj[na].y = obj[i].y;
- obj[na].xvel = obj[i].xvel;
- obj[na].yvel = obj[i].yvel;
- obj[na].alive++;
- obj[na].shape = ASTSHAPE2;
- obj[na].mass = M_MED;
- obj[i].shape = ASTSHAPE2;
- obj[i].mass = M_MED;
- blastpair(i, na);
- boom(i, 30, 12);
- numasts++;
- upscore(killer, 25);
- }
- else if (obj[i].shape == ASTSHAPE2)
- {
- for (k = 0; k < 3; k++)
- { oldna = na;
- na = nextast();
- obj[na].x = obj[i].x;
- obj[na].y = obj[i].y;
- obj[na].xvel = obj[i].xvel;
- obj[na].yvel = obj[i].yvel;
- obj[na].alive++;
- obj[na].shape = ASTSHAPE3;
- obj[na].mass = M_SMALL;
- if (k == 1) blastpair(oldna,na);
- }
- obj[i].shape = ASTSHAPE3;
- obj[i].mass = M_SMALL;
- blastpair(na, i);
- boom(i, 20, 10);
- numasts = numasts + 3;
- upscore(killer, 50);
- }
- else if (obj[i].shape == ASTSHAPE3)
- { boom(i, 10, 8);
- obj[i].alive = 0; numasts--; upscore(killer, 100);}
- else /* enemy {ship or bullet} */
- { boom(i, 9, 7);
- obj[i].alive = 0; upscore(killer, 500);}
- }
- moveobjs(crash)
- int *crash;
- { extern Objtype obj[SHIP+1];
- extern int ships;
- extern double speedscale;
- int i, j; /* Indexes */
- double *temp;
-
- movebooms();
- for (i = 0; i < LASTOBJ+1; i++)
- if (obj[i].alive)
- { temp = &obj[i].x;
- *temp = *temp + obj[i].xvel*speedscale;
- while (*temp < 0) *temp = *temp + (double) width;
- while (*temp > width) *temp = *temp - (double) width;
- temp = &obj[i].y;
- *temp = *temp + obj[i].yvel*speedscale;
- while (*temp < 0) *temp = *temp + height;
- while (*temp > height) *temp = *temp - height;
- obj[i].rot = obj[i].rot + obj[i].rotvel;
- }
- for (i = 0; i < FBUL; i++)
- if (obj[i].alive)
- {
- if (obj[SHIP].alive && collide(i, SHIP))
- { if (shield_on) bounce(SHIP, i);
- else
- { *crash = 2;
- ships--; obj[SHIP].alive = 0;
- killast(SHIP, i);
- continue;
- } }
- for (j = ENEMYBUL; j < LASTBUL+1; j++)
- if (obj[j].alive && collide(i, j) &&
- (j != ENEMYBUL || (i != ENEMYBUL && i != ENEMY)))
- { obj[j].alive = 0; /* Kill the bullet */
- /* Don't have 2 bullets kill same asteroid */
- if (obj[i].alive) killast(j,i);
- }
- }
- }
-
- fire()
- { extern Objtype obj[SHIP+1];
- extern int width, nextbul;
- extern double drawscale, speedscale;
- double *shiprot, cosrot, sinrot;
-
- obj[nextbul].alive++;
- shiprot = &obj[SHIP].rot;
- cosrot = cos(*shiprot); sinrot = sin(*shiprot);
- obj[nextbul].x = obj[SHIP].x + 20 * cosrot * drawscale;
- obj[nextbul].y = obj[SHIP].y + 20 * sinrot * drawscale;
- obj[nextbul].xvel = obj[SHIP].xvel + 10 * cosrot;
- obj[nextbul].yvel = obj[SHIP].yvel + 10 * sinrot;
- obj[nextbul].rot = *shiprot;
- obj[nextbul].time = width/(speedscale*11); /* loops before bullet expires */
- nextbul++; if (nextbul == LASTBUL+1) nextbul = FBUL;
- }
-
- hyper()
- { extern Objtype obj[SHIP+1];
- extern int width, height, rndint;
- unsigned char c;
- unsigned int i;
-
- c = rand(rndint); i = c; i<<=2; /* 0 - 1024 */
- while (i > width) i -= width;
- obj[SHIP].x = (double) i;
- c = rand(rndint); i = c; i<<=2; /* 0 - 1024 */
- while (i > height) i -= height;
- obj[SHIP].y = (double) i;
- }
-
- vdraw(disp, window, gc, shape, x, y, rot)
- Display *disp;
- Drawable window;
- GC gc;
- int shape;
- double x, y, rot;
-
- { int line;
- extern PolarPair shapes[LASTSHAPE+1][11];
- extern int numpairs[LASTSHAPE+1];
- extern double drawscale;
- XPoint figure[20];
- figure[0].x = (int) x; figure[0].y = (int) y;
- for (line=1; line < numpairs[shape]; line++) /* 2 pairs = 1 line */
- { figure[line].x = (int) shapes[shape][line].length *
- cos(shapes[shape][line].angle + rot) * drawscale;
- figure[line].y = (int) shapes[shape][line].length *
- sin(shapes[shape][line].angle + rot) * drawscale;
- }
- XDrawLines (disp, window, gc, figure, numpairs[shape], CoordModePrevious);
- }
-
- main(argc, argv)
- int argc;
- char **argv;
- { Colormap cmap;
- Cursor cursor;
- Display *disp;
- Font font;
- GC gc, pmgc;
- KeySym key;
- Pixmap pixmap;
- Window window;
- XColor black, exact;
- XEvent event;
- XSizeHints hint;
- XWMHints wmhints;
- extern int width, height;
- int screen, depth;
- char text[30];
- unsigned long fg, bg;
-
- extern double drawscale, speedscale;
- extern int numasts, rndint, ships, score, oldscore;
- extern Objtype obj[SHIP+1];
- unsigned char c; /* for rand */
- double *temp, dx, dy, dist;
- int level, crashed, flashon, len, pause = 0, delay = 64,
- enemycount, counter, counterstart = 1,
- i, /* index for drawing objs, counting bullets */
- r; /* radius of shield circle */
-
- disp = XOpenDisplay(0);
- if (disp == (Display *) NULL)
- { fprintf(stderr, "Could not open display\n");
- exit(1);
- }
- screen = DefaultScreen(disp);
- bg = BlackPixel(disp, screen);
- fg = WhitePixel(disp, screen);
- hint.x = 150; hint.y = 200; hint.width = 550; hint.height = 550;
- hint.flags = PPosition | PSize;
- width = hint.width; height = hint.height-letheight-1;
- depth = DefaultDepth (disp, screen);
- window = XCreateSimpleWindow (disp, DefaultRootWindow(disp),
- hint.x, hint.y, hint.width, hint.height, 5, fg, bg);
- pixmap = XCreatePixmap (disp, window, width, height, depth);
- XSetStandardProperties (disp, window, "asteroids", "asteroids", None,
- argv, argc, &hint);
- gc = XCreateGC (disp, window, 0, 0);
- XSetGraphicsExposures(disp, gc, 0); /* IMPORTANT! If you do not
- specifically ask not to get Expose events, every XCopyArea
- will generate one, & the event queue will fill up. */
- font = XLoadFont(disp, "10x20\0"); /* If you don't have this
- font, try replacing it with 9x15\0 */
- XSetFont(disp, gc, font);
- pmgc = XCreateGC (disp, window, 0, 0);
- XSetBackground (disp, gc, bg);
- XSetForeground (disp, gc, fg);
- XSetForeground (disp, pmgc, bg); /* fg of pixmap is bg of window */
- wmhints.flags = InputHint;
- wmhints.input = True;
- XSetWMHints(disp, window, &wmhints); /* Thanks to Doug Merritt */
- XSelectInput (disp, window,
- KeyPressMask | KeyReleaseMask | StructureNotifyMask);
- XMapRaised (disp, window);
-
- /* Erase cursor. Just delete next 5 lines if any error. */
- cmap = XDefaultColormap(disp, screen);
- XAllocNamedColor(disp, cmap, "Black", &exact, &black);
- cursor = XCreateFontCursor(disp, XC_dot);
- XRecolorCursor(disp, cursor, &black, &black);
- XDefineCursor(disp, window, cursor);
-
- XFillRectangle (disp, pixmap, pmgc, 0, 0, width, height);
- /* Can delete next line if it causes trouble */
- srand((unsigned) time(0)); /* By Craig Smith */
- initasts();
- Newgame:
- deletebooms();
- ships = 3;
- score = 0; oldscore = -1;
- for (level = 0; ;)
- { if (level < 8) level++;
- makeasts (level);
- Newship: botline(disp, window, gc);
- if (!obj[SHIP].alive)
- { obj[SHIP].x = width/2;
- obj[SHIP].y = height/2;
- obj[SHIP].xvel = 0;
- obj[SHIP].yvel = 0;
- obj[SHIP].rot = 3*pi/2;
- obj[SHIP].rotvel = 0;
- energy = 80;
- shield_on = 0;
- }
- obj[SHIP].alive = (ships > 0);
- crashed = 0; flashon = 0; enemycount = 20;
- counter = 0;
- while (numasts)
- { for (i = FBUL; i < LASTBUL+1; i++) /* Bullet timer */
- if (obj[i].alive)
- { obj[i].time--;
- if (!obj[i].time) obj[i].alive = 0; /* Not --! */
- }
- while (XEventsQueued(disp, QueuedAfterReading))
- { XNextEvent(disp, &event);
- switch (event.type)
- { case MappingNotify:
- XRefreshKeyboardMapping (&event);
- break;
- case ConfigureNotify:
- width = event.xconfigure.width;
- height = event.xconfigure.height-letheight-1;
- XFreePixmap (disp, pixmap);
- pixmap = XCreatePixmap (disp, window, width, height, depth);
- XFillRectangle (disp, pixmap, pmgc, 0, 0, width, height);
- botline(disp, window, gc);
- break;
- case KeyPress:
- len = XLookupString (&event, text, 10, &key, 0);
- if (len == 1 && !shield_on) switch (text[0])
- { case 'e':
- obj[SHIP].rotvel = obj[SHIP].rotvel - .1; break;
- case 'r':
- obj[SHIP].rotvel = obj[SHIP].rotvel + .1; break;
- case 'w':
- obj[SHIP].rot -= pi/4; break;
- case 't':
- obj[SHIP].rot += pi/4; break;
- case 'd':
- obj[SHIP].rotvel = obj[SHIP].rotvel - .02; break;
- case 'f':
- obj[SHIP].rotvel = obj[SHIP].rotvel + .02; break;
- case THRUST:
- obj[SHIP].xvel += cos(obj[SHIP].rot);
- obj[SHIP].yvel += sin(obj[SHIP].rot);
- obj[SHIP].shape = SHIPTHRSHAPE;
- break;
- case FIRE:
- if (obj[SHIP].alive) fire(); break;
- case ' ':
- if (obj[SHIP].alive)
- { hyper(); flashon = 1;
- /* NOT XSetForeground (disp, gc, bg);
- If you set the fg black, & print the highscore, it will effectively erase it. */
- XSetForeground (disp, pmgc, fg);
- XFillRectangle (disp, pixmap, pmgc, 0, 0, width, height);
- }
- break;
- case SHIELD:
- if (energy)
- { shield_on = 1;
- obj[SHIP].shape = SHIPSHAPE;}
- break;
- case '.': /* decrease delay */
- if (delay > 1) delay >>=1; break;
- case ',': /* increase delay */
- delay <<=1; break;
- case 'm': /* decrease drawscale - may go negative */
- drawscale -= .1; break;
- case 'n': /* increase drawscale */
- drawscale += .1; break;
- case '2': /* increase speedscale */
- speedscale += .1; break;
- case '1': /* decrease speedscale */
- speedscale -= .1; break;
- case 'b': /* increase moves/update */
- counterstart++; break;
- case 'v': /* decrease moves/update */
- if (counterstart > 1) counterstart--;
- break;
- case PAUSE: /* pause */
- pause = 1 - pause; break;
- case '+': /* cheat */
- ships++; botline(disp, window, gc); break;
- case 'Q': /* quit */
- goto End;
- case 's': /* start new ship */
- if (!obj[SHIP].alive)
- if (ships < 1) goto Newgame;
- else goto Newship;
- break;
- }
- break;
- case KeyRelease:
- len = XLookupString(&event, text, 10, &key, 0);
- if (len == 1) switch (text[0])
- { case 'e':
- obj[SHIP].rotvel = 0; break;
- case 'r':
- obj[SHIP].rotvel = 0; break;
- case THRUST:
- obj[SHIP].shape = SHIPSHAPE;
- break;
- case SHIELD:
- shield_on = 0; break;
- }
- /* break; */
- } }
- if (!pause)
- { moveobjs(&crashed);
- if (ships) score--; /* timer effect */
- if (!counter)
- { counter = counterstart; /* Restart counter */
- if (crashed == 2)
- { crashed--; flashon++;
- boom(SHIP, BMAX-1, 70);
- XSetForeground (disp, pmgc, fg);
- XFillRectangle (disp, pixmap, pmgc, 0, 0, width, height);
- botline(disp, window, gc);
- }
- /* Write copyright notice */
- if (!ships && blist == NULL)
- { sprintf(text, "Xasteroids");
- XDrawImageString (disp, pixmap, gc,
- width/2-50, height/2-2*letheight,
- text, strlen(text));
- sprintf(text, "Copyright 1990 by Phil Goetz");
- XDrawImageString (disp, pixmap, gc,
- width/2-140, height/2,
- text, strlen(text));
- sprintf(text, "goetz@cs.buffalo.edu");
- XDrawImageString (disp, pixmap, gc,
- width/2-100, height/2+2*letheight,
- text, strlen(text));
- }
- /* Draw objects */
- for (i = 0; i <= LASTOBJ; i++)
- if (obj[i].alive)
- vdraw(disp, pixmap, gc, obj[i].shape,
- obj[i].x, obj[i].y, obj[i].rot);
- if (shield_on && obj[SHIP].alive)
- { r = abs((int) (drawscale*SHIPSIZE));
- XDrawArc(disp, pixmap, gc,
- ((int) obj[SHIP].x) - r,
- ((int) obj[SHIP].y) - r,
- 2*r, 2*r, 0, 360*64);
- energy--;
- if (!energy) shield_on = 0;
- }
- drawbooms(disp, pixmap, gc);
- /* update display: */
- XCopyArea(disp, pixmap, window, gc, 0, 0, width, height, 0, 0);
- printss(disp, window, gc);
- /* erase objects */
- XFillRectangle (disp, pixmap, pmgc, 0, 0, width, height);
- if (flashon)
- { flashon--;
- XSetForeground (disp, pmgc, bg);
- XFillRectangle (disp, pixmap, pmgc, 0, 0, width, height);
- }
- XSync(disp, 0);
- }
- counter--;
- c = rand(rndint)>>8;
- if (!obj[ENEMY].alive)
- { if (c < level)
- { c = rand(rndint);
- if (c < level * 10) makeenemy(level);
- } }
- else
- obj[ENEMY].yvel += (c>128+6*obj[ENEMY].yvel) ? .5 : -.5;
- enemycount--; if (!enemycount)
- { enemycount = 100;
- if (obj[ENEMY].alive)
- { obj[ENEMYBUL].alive++;
- obj[ENEMYBUL].x = obj[ENEMY].x;
- obj[ENEMYBUL].y = obj[ENEMY].y;
- dx = obj[SHIP].x - obj[ENEMY].x;
- dy = obj[SHIP].y - obj[ENEMY].y;
- dist = sqrt(dx*dx + dy*dy);
- obj[ENEMYBUL].xvel = 3*dx/dist;
- obj[ENEMYBUL].yvel = 3*dy/dist;
- }
- else obj[ENEMYBUL].alive = 0;
- }
- for (i = 0; i < delay; i++);
- }
- }
- }
- End: printf("\nYour high score was %d\n", highscore);
- XFreeGC (disp, gc);
- XFreeGC (disp, pmgc);
- XFreePixmap (disp, pixmap);
- XDestroyWindow (disp, window);
- XCloseDisplay (disp);
- exit(0);
- }
-