fly.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:7k
- /*
- * fly.c $Revision: 1.2 $
- */
- #include "stdio.h"
- #include "math.h"
- #include "skyfly.h"
- #if defined(_WIN32)
- #pragma warning (disable:4244) /* disable bogus conversion warnings */
- #pragma warning (disable:4305) /* VC++ 5.0 version of above warning. */
- #endif
- #define cosf(a) cos((float)a)
- #define sinf(a) sin((float)a)
- #define sqrtf(a) sqrt((float)a)
- #define expf(a) exp((float)a)
- typedef struct paper_plane_struct {
- float Pturn_rate;
- float PX, PY, PZ, PZv;
- float Pazimuth;
- float Proll;
- int Pcount, Pdirection;
- } paper_plane;
- static paper_plane flock[NUM_PLANES];
- static float X, Y, Z, Azimuth, Speed;
- static int Keyboard_mode;
- extern float *A;
- extern int Wxorg, Wyorg;
- static float terrain_height(float x, float y);
- int Xgetbutton(int b);
- int Xgetvaluator(int v);
- void init_positions(void)
- {
- int i;
- X = GRID_RANGE / 2.;
- Y = GRID_RANGE / 2.;
- Z = 1.5;
- /*
- * randomly position the planes near center of world
- * take MAX of height above terrain and 0, so planes
- * don't fall into canyon. Canyon has negative elevation
- */
- for (i = 0; i < NUM_PLANES; i++) {
- flock[i].PX = (float) IRND(20) + GRID_RANGE / 2 - 10;
- flock[i].PY = (float) IRND(20) + GRID_RANGE / 2 - 10;
- flock[i].PZ = MAX(terrain_height(flock[i].PX, flock[i].PY),0.) +
- 2.*(float)i/NUM_PLANES+.3;
- flock[i].Pazimuth = ((float)IRND(256) / 128.) * M_PI;
- }
- Speed = 0.1f;
- Azimuth = M_PI / 2.;
- #if 0
- // if (Init_pos) {
- // X = Init_x;
- // Y = Init_y;
- // Z = Init_z;
- // Azimuth = Init_azimuth;
- // Keyboard_mode = 1;
- // }
- #endif
- }
- int _frame = 0;
- void fly(perfobj_t *viewer_pos)
- {
- float terrain_z, xpos, ypos, xcntr, ycntr;
- float delta_speed = .003;
- /* if (++_frame == 1000) {
- _frame = 0;
- init_positions();
- }*/
- xcntr = Wxsize / 2;
- ycntr = Wysize / 2;
- if (Xgetbutton(RKEY))
- init_positions();
- if (Xgetbutton(SPACEKEY)) {
- Keyboard_mode = !Keyboard_mode;
- }
- if (Keyboard_mode) {
- /*
- * step-at-a-time debugging mode
- */
- if (Keyboard_mode && Xgetbutton(LEFTARROWKEY)) {
- Azimuth -= 0.025;
- }
- if (Keyboard_mode && Xgetbutton(RIGHTARROWKEY)) {
- Azimuth += 0.025;
- }
- if (Keyboard_mode && Xgetbutton(UPARROWKEY)) {
- X += cosf(-Azimuth + M_PI / 2.) * 0.025;
- Y += sinf(-Azimuth + M_PI / 2.) * 0.025;
- }
- if (Keyboard_mode && Xgetbutton(DOWNARROWKEY)) {
- X -= cosf(-Azimuth + M_PI / 2.) * 0.025;
- Y -= sinf(-Azimuth + M_PI / 2.) * 0.025;
- }
- if (Keyboard_mode && Xgetbutton(PAGEUPKEY)) {
- Z += 0.025;
- }
- if (Keyboard_mode && Xgetbutton(PAGEDOWNKEY)) {
- Z -= 0.025;
- }
- } else {
- /*
- * simple, mouse-driven flight model
- */
- if (Xgetbutton(LEFTMOUSE) && Speed < .3)
- Speed += delta_speed;
- if (Xgetbutton(RIGHTMOUSE) && Speed > -.3)
- Speed -= delta_speed;
- if (Xgetbutton(MIDDLEMOUSE))
- Speed = Speed*.8;
- xpos = (Xgetvaluator(MOUSEX)-xcntr) / ((float)Wxsize*14.);
- ypos = (Xgetvaluator(MOUSEY)-ycntr) / ((float)Wysize*.5);
- /*
- * move in direction of view
- */
- Azimuth += xpos;
- X += cosf(-Azimuth + M_PI / 2.) * Speed;
- Y += sinf(-Azimuth + M_PI / 2.) * Speed;
- Z -= ypos * Speed;
- }
- /*
- * keep from getting too close to terrain
- */
- terrain_z = terrain_height(X, Y);
- if (Z < terrain_z +.4)
- Z = terrain_z +.4;
- X = MAX(X, 1.);
- X = MIN(X, GRID_RANGE);
- Y = MAX(Y, 1.);
- Y = MIN(Y, GRID_RANGE);
- Z = MIN(Z, 20.);
- *((float *) viewer_pos->vdata + 0) = X;
- *((float *) viewer_pos->vdata + 1) = Y;
- *((float *) viewer_pos->vdata + 2) = Z;
- *((float *) viewer_pos->vdata + 3) = Azimuth;
- }
- void fly_paper_planes(perfobj_t *paper_plane_pos)
- {
- int i;
- float speed = .08;
- float terrain_z;
- /*
- * slow planes down in cyclops mode since
- * frame rate is doubled
- */
- for (i = 0; i < NUM_PLANES; i++) {
- /*
- * If plane is not turning, one chance in 50 of
- * starting a turn
- */
- if (flock[i].Pcount == 0 && IRND(50) == 1) {
- /* initiate a roll */
- /* roll for a random period */
- flock[i].Pcount = IRND(100);
- /* random turn rate */
- flock[i].Pturn_rate = IRND(100) / 10000.;
- flock[i].Pdirection = IRND(3) - 1;
- }
- if (flock[i].Pcount > 0) {
- /* continue rolling */
- flock[i].Proll += flock[i].Pdirection * flock[i].Pturn_rate;
- flock[i].Pcount--;
- } else
- /* damp amount of roll when turn complete */
- flock[i].Proll *=.95;
- /* turn as a function of roll */
- flock[i].Pazimuth -= flock[i].Proll *.05;
- /* follow terrain elevation */
- terrain_z=terrain_height(flock[i].PX,flock[i].PY);
- /* use a "spring-mass-damp" system of terrain follow */
- flock[i].PZv = flock[i].PZv -
- .01 * (flock[i].PZ - (MAX(terrain_z,0.) +
- 2.*(float)i/NUM_PLANES+.3)) - flock[i].PZv *.04;
- /* U-turn if fly off world!! */
- if (flock[i].PX < 1 || flock[i].PX > GRID_RANGE - 2 || flock[i].PY < 1 || flock[i].PY > GRID_RANGE - 2)
- flock[i].Pazimuth += M_PI;
- /* move planes */
- flock[i].PX += cosf(flock[i].Pazimuth) * speed;
- flock[i].PY += sinf(flock[i].Pazimuth) * speed;
- flock[i].PZ += flock[i].PZv;
- }
- for (i = 0; i < NUM_PLANES; i++) {
- *((float *) paper_plane_pos[i].vdata + 0) = flock[i].PX;
- *((float *) paper_plane_pos[i].vdata + 1) = flock[i].PY;
- *((float *) paper_plane_pos[i].vdata + 2) = flock[i].PZ;
- *((float *) paper_plane_pos[i].vdata + 3) = flock[i].Pazimuth * RAD_TO_DEG;
- *((float *) paper_plane_pos[i].vdata + 4) = flock[i].PZv * (-500.);
- *((float *) paper_plane_pos[i].vdata + 5) = flock[i].Proll *RAD_TO_DEG;
- }
- }
- /* compute height above terrain */
- static float terrain_height(float x, float y)
- {
- float dx, dy;
- float z00, z01, z10, z11;
- float dzx1, dzx2, z1, z2;
- int xi, yi;
- x /= XYScale;
- y /= XYScale;
- xi = MIN((int)x, GridDim-2);
- yi = MIN((int)y, GridDim-2);
- dx = x - xi;
- dy = y - yi;
- /*
- View looking straight down onto terrain
- <--dx-->
- z00----z1-------z10 (terrain elevations)
- | | |
- ^ | Z at(x,y) |
- | | | |
- dy | | |
- | | | |
- | | | |
- V z00----z2-------z10
- (xi,yi)
- Z= height returned
-
- */
- z00 = A[xi * GridDim + yi];
- z10 = A[(xi + 1) * GridDim + yi];
- z01 = A[xi * GridDim + yi + 1];
- z11 = A[(xi + 1) * GridDim + yi + 1];
- dzx1 = z10 - z00;
- dzx2 = z11 - z01;
- z1 = z00 + dzx1 * dx;
- z2 = z01 + dzx2 * dx;
- return (ScaleZ*((1.0 - dy) * z1 + dy * z2));
- }