小球遊戲

代碼實現功能如下:

       繪製一個小球,並且在小球下方添加有材質的地面。w,s,a,d分別實現控制小球上,下,左,右的移動。鍵盤上,下,左,右的箭頭分別控制視角的旋轉變化。

 

#include <GL/glut.h>
#include <cmath>
#include <stdlib.h>
#include <GL/glut.h>
#include <math.h>

static int s = 0;

//色彩全局常量
GLfloat WHITE[] = { 1, 1, 1 };    //白色
GLfloat RED[] = { 1, 0, 0 };    //紅色
GLfloat GREEN[] = { 0, 1, 0 };    //綠色
GLfloat MAGENTA[] = { 1, 0, 1 };  //洋紅

//攝像機類:水平移動半徑爲10,按上下鍵則垂直移動
class Camera {
public:  
    double theta;      //確定x和z的位置
    double y;          //y位置
    double dTheta;     //角度增量
    double dy;         //上下y增量
public:
    //類構造函數—默認初始化用法
    Camera() : theta(0), y(3), dTheta(0.04), dy(0.2) {}
    //類方法
    double getX() { return 10 * cos(theta); }
    double getY() { return y; }
    double getZ() { return 10 * sin(theta); }
    void moveRight() { theta += dTheta; }
    void moveLeft() { theta -= dTheta; }
    void moveUp() { y += dy; }
    void moveDown() { if (y > dy) y -= dy; }
};

//球類定義
//半徑、顏色、最大高度
//x和z固定
//用lame bouncing algorithm
//每幀上下移動0.05單位
class Ball {
    //類的屬性
    double radius;
    GLfloat* color;
    double maximumHeight;
    double x;
    double y;
    double z;
    int direction;   //方向
public:
    //構造函數
    Ball(double r, GLfloat* c, double h, double y, double z) :
        radius(r), color(c), maximumHeight(h), direction(-1),
        y(h), x(x), z(z) {
    }

    //更新和繪製方法
    void update() {
		if(s==0){
			z+=0.05;
		}
		else if(s==1){
			z-=0.05;
		}
		else if(s==2){
			x+=0.05;
		}
		else if(s==3){
			x-=0.05;
		}
        if (x > 7) {
            x = 7;
            direction = -1;
        }
        else if (x < 0) {
            x =0;
            direction = 1;
        }
        glPushMatrix();
        //單獨設置每個球的材質參數
        glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color);
       	glTranslated(x, y, z);	
        //創建球
        glutSolidSphere(radius, 30, 30);
        glPopMatrix();
    }
};

//棋盤格:沿x和z平面分佈
//點光源位置設置爲(4, 3, 7).
class Checkerboard {
    int displayListId;
    int width;
    int depth;
public:
    //構造函數
    Checkerboard(int width, int depth) : width(width), depth(depth) {}

    //中心X
    double centerx() { return width / 2; }

    //中心Y
    double centerz() { return depth / 2; }

    //創建方法
    void create() {
        displayListId = glGenLists(1);     //每個顯示列表對應1個編號——關聯起來
        //新建操作表
        glNewList(displayListId, GL_COMPILE);   //把下述命令裝入顯示列表但不顯示
        //光源位置參數
        GLfloat lightPosition[] = { 4, 3, 7, 1 };
        //設置光源位置
        glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
        //開始繪製四邊形
        glBegin(GL_QUADS);
        //法向量方向
        glNormal3d(0, 1, 0);
        for (int x = 0; x < width - 1; x++) {
            for (int z = 0; z < depth - 1; z++) {
                //設置每個格子的材質屬性
                glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE,
                    (x + z) % 2 == 0 ? RED : WHITE);
                //四邊形的4個點座標
                glVertex3d(x, 0, z);
                glVertex3d(x + 1, 0, z);
                glVertex3d(x + 1, 0, z + 1);
                glVertex3d(x, 0, z + 1);
            }
        }
        glEnd();
        glEndList();
    }
    //按列表編號繪製棋盤格
    void draw() {
    glCallList(displayListId);
    }
};

//全局變量:棋盤格、相機和3個球的數組
Checkerboard checkerboard(8, 8);
Camera camera;
//創建3個小球的數組
Ball balls[] = {
    Ball(0.2, GREEN, 0.2, 2, 3)
};

//自定義初始化方法
void init() {
    //允許深度測試
    glEnable(GL_DEPTH_TEST);
    //設置散射和鏡像反射爲白光
    glLightfv(GL_LIGHT0, GL_DIFFUSE, WHITE);
    glLightfv(GL_LIGHT0, GL_SPECULAR, WHITE);
    //設置前表面的高光鏡像反射爲白光
    glMaterialfv(GL_FRONT, GL_SPECULAR, WHITE);
    //設置前表面散射光反光係數
    glMaterialf(GL_FRONT, GL_SHININESS, 30);
    //允許燈光
    glEnable(GL_LIGHTING);
    //打開0#燈
    glEnable(GL_LIGHT0);
    //創建棋盤格
    checkerboard.create();
}

//自定義繪製函數
//通過類繪製各對象,display函數代碼得以簡化
void display() {
    //清除前一幀繪圖結果
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //裝入單位陣
    glLoadIdentity();
    //設置視角——攝像機參數
    gluLookAt(camera.getX(), camera.getY(), camera.getZ(),    //攝像機位置
        checkerboard.centerx(), 0.0, checkerboard.centerz(),   //焦點座標
        0.0, 1.0, 0.0);   //攝像機機頂方向矢量
    //繪製棋盤
    checkerboard.draw();
    //繪製小球
    //更新位置並繪圖
    balls[0].update();
    //glFlush();
    glutSwapBuffers();
}

//窗口調整大小時調用的函數
void reshape(GLint w, GLint h) {
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(40.0, GLfloat(w) / GLfloat(h), 1.0, 150.0);
    glMatrixMode(GL_MODELVIEW);
}

//自定義計時器函數
void timer(int v) {
    //當計時器喚醒時所調用的函數
    glutPostRedisplay();
    //設置下一次計時器的參數
    glutTimerFunc(1000 / 60, timer/*函數名*/, v);
}

//鍵盤處理函數
void onKey(int key, int, int) {
    //按鍵:上下左右
    switch (key) {
    case GLUT_KEY_LEFT: camera.moveLeft(); break;
    case GLUT_KEY_RIGHT: camera.moveRight(); break;
    case GLUT_KEY_UP: camera.moveUp(); break;
    case GLUT_KEY_DOWN: camera.moveDown(); break;
    }
    glutPostRedisplay();
}

void keyboard (unsigned char key, int x, int y)
{
	switch (key) {
		
		case 'w':
			s=0;
			balls[0].update();
			glutPostRedisplay();
		break;
		
		case 's':
			s=1;
			balls[0].update();
			glutPostRedisplay();
		break;

		case 'a':
			s=2;
			balls[0].update();
			glutPostRedisplay();
		break;

		case 'd':
			s=3;
			balls[0].update();
			glutPostRedisplay();
		break;
		
	}
}

int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowPosition(80, 80);
    glutInitWindowSize(800, 600);
    glutCreateWindow("小球遊戲");
    glutDisplayFunc(display);   //設置顯示函數
    glutReshapeFunc(reshape);   //設置窗口調整大小的函數
    glutSpecialFunc(onKey);   //設置按鍵處理函數
	glutKeyboardFunc(keyboard);

    init();//自定義初始化函數
    glutMainLoop();//進入opengl主循環
	
    
    return 0;
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章