flightsim.c

来自「飞机飞行界面」· C语言 代码 · 共 1,162 行 · 第 1/3 页

C
1,162
字号

    if (Position[2] > (0.45 * TERRAIN_SIZE))
        {
	Position[2]    = 0.45 * TERRAIN_SIZE;
	Orientation[1] += 10.0 * distance;
	}

    i = (Position[0] + 0.5 * TERRAIN_SIZE) / TERRAIN_SPACING + 0.5;
    j = (0.5 * TERRAIN_SIZE - Position[2]) / TERRAIN_SPACING + 0.5;

    if (Position[1] < (5.0 + Terrain[i][j].v[1]))
        {
	Position[1]    = 5.0 + Terrain[i][j].v[1];
	Orientation[0] += 5.0 * distance;
	}

    if (Position[1] > (0.2 * TERRAIN_SIZE))
        {
	Position[1]    = 0.2 * TERRAIN_SIZE;
	Orientation[0] -= 5.0 * distance;
	}

    if (Orientation[0] < -90.0)
        {
        Orientation[0] = -180.0 - Orientation[0];
	Orientation[2] += 180.0;
	}
    else if (Orientation[0] > 90.0)
        {
        Orientation[0] = 180.0 - Orientation[0];
	Orientation[2] -= 180.0;
	}

    if (Orientation[1] < 0.0)
        Orientation[1] += 360.0;
    else if (Orientation[1] > 360.0)
        Orientation[1] -= 360.0;

    if (Orientation[2] < -180.0)
        Orientation[2] += 360.0;
    else if (Orientation[2] > 180.0)
        Orientation[2] -= 360.0;

    /* Update instruments as needed... */
    if (fabs(Orientation[0] - Horizon[0]) > 1.0 ||
        fabs(Orientation[2] - Horizon[1]) > 1.0)
        RedrawHorizon = 1;

    if (fabs(Orientation[1] - Compass) > 1.0 &&
        fabs(Orientation[1] - Compass) < 359.0)
	RedrawCompass = 1;

    if (Position[1] != Altimeter)
        RedrawAltimeter = 1;

    /* Update the frames-per-second value */
    FPSTime += distance;
    FPSCount ++;
    if (FPSCount >= 20)
        {
	FPS       = FPSCount / FPSTime + 0.5;
	FPSTime   = 0.0;
	FPSCount  = 0;
	}

    RedrawAll = -1;
    Redraw();
    }


/*
 * 'Joystick()' - Handle joystick movement.
 */

void
Joystick(unsigned state,       /* I - Button state */
         int      x,           /* I - X position (-1000 to 1000) */
 	 int      y,           /* I - Y position (-1000 to 1000) */
	 int      z)           /* I - Z position (-1000 to 1000) */
    {
    float      new_velocity;   /* New velocity value */
    static int last_state = 0; /* Last button state */

    if (last_state != state)
        {
	/* Button changed state; see what the new state is... */
	if (state && !last_state)
            {
    	    /* Start flying */
            MouseStartX = MouseX = x / 2;
	    MouseStartY = MouseY = y / 2;
	    LastTime    = GetClock();
            glutIdleFunc(Idle);
	    }
            else if (!state && last_state)
            {
	    /* Stop flying */
            glutIdleFunc((void (*)(void))0);
	    }

	last_state = state;
	}

    /* Update the joystick/mouse position */
    if (state)
        {
	MouseX = x / 2;
        MouseY = y / 2;
	}

    if (z > -999)
        Velocity = (999 - z) * 0.045 + 10.0;

    if (fabs(Velocity - Airspeed) >= 1.0)
	RedrawAirspeed = 1;
    }

/*
 * 'Keyboard()' - Handle key presses...
 */

void
Keyboard(unsigned char key, /* I - Key that was pressed */
         int           x,   /* I - Mouse X position */
	 int           y)   /* I - Mouse Y position */
    {
    switch (key)
        {
	case 0x1b :
	    puts("");
	    exit(0);
	    break;
	case ',' :
	    if (Velocity > 5.0)
	        {
		RedrawAirspeed = 1;
	        Velocity       -= 5.0;
		}
	    break;
	case '.' :
	    if (Velocity < 100.0)
	        {
		RedrawAirspeed = 1;
	        Velocity       += 5.0;
		}
	    break;
	case '<' :
	    RedrawAirspeed = 1;
	    Velocity       = 10.0;
	    break;
	case '>' :
	    RedrawAirspeed = 1;
	    Velocity       = 100.0;
	    break;
	case '3' :
	    ShowTerrain = !ShowTerrain;
	    break;
	case 'l' :
	    ShowLighting = !ShowLighting;
	    break;
	case 's' :
	    ShowSky = !ShowSky;
	    break;
	case 't' :
	    UseTexturing = !UseTexturing;
	    break;
	case 'w' :
	    ShowWater = !ShowWater;
	    break;
	case 'W' :
	    if (PolyMode == GL_FILL)
	        PolyMode = GL_LINE;
	    else
	        PolyMode = GL_FILL;
	    break;
	}

    glutPostRedisplay();
    }


/*
 * 'Motion()' - Handle mouse pointer motion.
 */

void
Motion(int x, /* I - Current mouse X position */
       int y) /* I - Current mouse Y position */
    {
    MouseX = x;
    MouseY = y;
    }


/*
 * 'Mouse()' - Handle mouse button events.
 */

void
Mouse(int button, /* I - Button that changed */
      int state,  /* I - Current button states */
      int x,      /* I - Current mouse X position */
      int y)      /* I - Current mouse Y position */
    {
    if (state == GLUT_DOWN)
        {
	/* Start flying */
	MouseStartX = MouseX = x;
	MouseStartY = MouseY = y;
	LastTime    = GetClock();
        glutIdleFunc(Idle);
	}
    else
        {
	/* Stop flying */
        glutIdleFunc((void (*)(void))0);
	}
    }


/*
 * 'draw_instrument()' - Draws an instrument frame.
 */

void
draw_instrument(int ix, int iy, int isize)
    {
    float	theta; /* Angle for circle */

    glColor3f(0.5, 0.5, 0.525);
    glBegin(GL_QUADS);
    glVertex2i(ix, iy);
    glVertex2i(ix + isize - 1, iy);
    glVertex2i(ix + isize - 1, iy + isize - 1);
    glVertex2i(ix, iy + isize - 1);
    glEnd();

    glColor3f(0.75, 0.75, 0.788);
    glBegin(GL_LINE_STRIP);
    glVertex2i(ix, iy);
    glVertex2i(ix, iy + isize - 1);
    glVertex2i(ix + isize - 1, iy + isize - 1);
    glEnd();

    glColor3f(0.25, 0.25, 0.262);
    glBegin(GL_LINE_STRIP);
    glVertex2i(ix, iy);
    glVertex2i(ix + isize - 1, iy);
    glVertex2i(ix + isize - 1, iy + isize - 1);
    glEnd();

    glColor3f(1.0, 1.0, 1.0);
    glBegin(GL_TRIANGLE_FAN);
    glVertex2f(ix + isize * 0.5f, iy + isize * 0.5f);

    for (theta = 0.0f; theta < (2.0f * M_PI + M_PI / 18.0f); theta += M_PI / 18.0f)
	glVertex2f(ix + isize * 0.5f + cos(theta) * isize * 0.4f,
	           iy + isize * 0.5f + sin(theta) * isize * 0.4f);
    glEnd();
    }


/*
 * 'Redraw()' - Redraw the window...
 */

void
Redraw(void)
    {
    int   i, j;
    int   ix, iy, isize;
    TP    *tp;
    float theta, st, ct;
    static GLfloat sunpos[4] = { -0.7071, -0.7071, 0.0, 0.0 };
    static GLfloat suncolor[4] = { 1.0, 1.0, 0.8, 1.0 };
    static GLfloat sunambient[4] = { 0.25, 0.25, 0.2, 1.0 };
    static GLfloat s_vector[4] = { 50.0 / TERRAIN_SIZE, 0.0, 0.0, 0.0 };
    static GLfloat t_vector[4] = { 0.0, 0.0, 50.0 / TERRAIN_SIZE, 0.0 };

    /* Force a full redraw for normal situations; Idle sets it to -1 */
    RedrawAll ++;

    /* Reset the viewport... */
    glViewport(0, 3 * Height / 8, Width, Height - 3 * Height / 8);
    glScissor(0, 3 * Height / 8, Width, Height - 3 * Height / 8);
    glEnable(GL_SCISSOR_TEST);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(22.5, 2.0f * (float)Width / (float)Height, 4.0,
                   TERRAIN_VIEW);
    glMatrixMode(GL_MODELVIEW);

    /* Clear the window to light blue... */
    if (ShowSky && UseTexturing && PolyMode == GL_FILL)
        glClear(GL_DEPTH_BUFFER_BIT);
    else
        {
        glClearColor(0.75, 0.75, 1.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	}

    /* Setup viewing transformations for the current orientation... */
    glPushMatrix();
    glRotatef((float)ViewAngle, 0.0, 1.0, 0.0);
    glRotatef(Orientation[2], 0.0, 0.0, 1.0);
    glRotatef(Orientation[0], -1.0, 0.0, 0.0);
    glRotatef(Orientation[1], 0.0, 1.0, 0.0);
    glTranslatef(0.0, -Position[1], 0.0);

    glPolygonMode(GL_FRONT_AND_BACK, PolyMode);

    /* Draw the sky */
    if (UseTexturing && SkyTexture && ShowSky && PolyMode == GL_FILL)
        {
        glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, SkyTexture);

        glColor3f(1.0, 1.0, 1.0);
        glBegin(GL_TRIANGLE_FAN);
        glTexCoord2f(0.5, 0.5);
        glVertex3f(0.0, TERRAIN_VIEW, 0.0);
        for (theta = 0.0; theta < (2.1 * M_PI); theta += M_PI / 8)
            {
            ct = cos(theta);
            st = sin(theta);
            glTexCoord2f(0.5 + 0.3 * ct, 0.5 + 0.3 * st);
            glVertex3f(ct * TERRAIN_VIEW * 0.7071,
	               TERRAIN_VIEW * 0.7071,
	               st * TERRAIN_VIEW * 0.7071);
            }
        glEnd();

        glBegin(GL_TRIANGLE_STRIP);
        for (theta = 0.0; theta < (2.1 * M_PI); theta += M_PI / 8)
            {
            ct = cos(theta);
            st = sin(theta);
            glTexCoord2f(0.5 + 0.3 * ct, 0.5 + 0.3 * st);
            glVertex3f(ct * TERRAIN_VIEW * 0.7071,
	               TERRAIN_VIEW * 0.7071,
	               st * TERRAIN_VIEW * 0.7071);
            glTexCoord2f(0.5 + 0.5 * ct, 0.5 + 0.5 * st);
            glVertex3f(ct * TERRAIN_VIEW, -100.0,
	               st * TERRAIN_VIEW);
            }
        glEnd();
        }

    /* Setup lighting if needed... */
    glEnable(GL_LIGHTING);
    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, sunambient);
    glEnable(GL_COLOR_MATERIAL);

    if (ShowLighting)
        {
        glEnable(GL_LIGHT0);
        glLightfv(GL_LIGHT0, GL_POSITION, sunpos);
        glLightfv(GL_LIGHT0, GL_DIFFUSE, suncolor);
        glLightfv(GL_LIGHT0, GL_AMBIENT, sunambient);
        }
    else
        glDisable(GL_LIGHT0);

    /* Then draw the terrain... */
    if (UseTexturing && LandTexture && PolyMode == GL_FILL)
        {
        glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, LandTexture);
        }

    glTranslatef(-Position[0], 0.0, -Position[2]);

    glColor3f(0.3, 0.8, 0.2);

    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
    glTexGenfv(GL_S, GL_OBJECT_PLANE, s_vector);

    glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
    glTexGenfv(GL_T, GL_OBJECT_PLANE, t_vector);

    glEnable(GL_TEXTURE_GEN_S);
    glEnable(GL_TEXTURE_GEN_T);

    if (ShowTerrain)
        {
        glEnable(GL_CULL_FACE);

⌨️ 快捷键说明

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