OpenGL实现三维迷宫游戏(一)

xiaoxiao2021-02-27  170

《计算机图形学》这门课的第二个实验,觉得还挺有意思的…

实验要求

设计一个OpenGL程序,创建一个三维迷宫,支持替身通过一定交互手段在迷宫中漫游,基本功能包括: - 迷宫应当至少包含10 * 10 个Cell,不能过于简单,下图给出一种示例。 - 读取给定的替身模型,加载到场景中。 - 键盘方向键控制替身转向与漫游。 - 有碰撞检测,替身不应当穿墙。 - 支持切换第一视角和第三视角进行观察。 - 迷宫场景中的墙、地面等应贴上纹理。 附加要求(可选择一个): - 同时加入二维辅助地图,替身在三维迷宫探索的同时,在小地图中显示已经探索的区域;(我选的是这一个,其他的由于最近事情比较多就没有做,以后有机会再补吧…如果有机会的话…=。=) - 在俯视状态下,可以通过鼠标点选替身需要到达的目的地,通过寻径算法,控制替身自动到达目的地; - 迷宫地图交互编辑功能,例如,可以设计一个二维地图编辑器,根据用户的绘制,拉伸得到三维迷宫场景; - 其他相当难度,可以增加迷宫游戏趣味性的功能(需要通过指导老师认可)

实现过程

投影模式采用透视投影,第一、三视角之间的切换只需改变gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);的参数值即可。

main()方法:

int main(int argc,char **argv){ glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH); glutInitWindowPosition(300, 50); glutInitWindowSize(700, 700); glutCreateWindow("迷宫"); init(); glutDisplayFunc(display); glutMainLoop(); return 0; }

init()方法:

void init(){ glClearColor(0.8, 0.8, 0.8, 1);//用灰色清屏 glEnable(GL_DEPTH_TEST);//开启深度测试 glEnable(GL_TEXTURE_2D);//启用二维纹理 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(50, 1, 0.5, 100);/*其实一开始ZNear设的是1~*/ glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(lookX, lookY, lookZ, centerX,centerY,centerZ,upX,upY,upZ); glShadeModel(GL_SMOOTH); //使用平滑明暗处理 glEnable(GL_DEPTH_TEST); //剔除隐藏面 glEnable(GL_CULL_FACE); //不计算多边形背面 glFrontFace(GL_CCW); //多边形逆时针方向为正面 { //三视图光源 GLfloat light0_position[] = {10.0f, 10.0f, 0.0f, 1.0f }; GLfloat light0_ambient[] = { 0.8f, 0.8f, 0.8f, 1.0f }; GLfloat light0_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; glLightfv(GL_LIGHT0, GL_POSITION, light0_position); glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse); //一视图光源 GLfloat light1_position[] = { 10.0f, 10.0f, 0.0f, 1.0f }; GLfloat light1_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f }; GLfloat light1_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; GLfloat light1_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; glLightfv(GL_LIGHT1, GL_POSITION, light1_position); glEnable(GL_LIGHTING);//开启光照明 glEnable(GL_DEPTH_TEST); }

参数的初始值:

double lookX=0, lookY=0, lookZ=15;//相机在世界坐标的位置 double centerX = 0, centerY = 0, centerZ = 0;//相机镜头对准的物体在世界坐标的位置 double upX = 0, upY = 1, upZ = 0;//相机向上的方向在世界坐标中的方向

关于gluPerspective()的理解推荐看OpenGL函数思考-gluPerspective。gluLookAt()挺好理解的就不推荐了。

display()方法:

void display(){ drawMaze();//画迷宫 glutSwapBuffers();/*这句很重要!!!刚开始学OpenGL的时候没注意这个,结果画出来什么都没有是全白的。开了双缓冲就要写。*/ }

迷宫我是用对应位置及数量的小立方体拼起来的,所以先声明了一个方法drawCube(double x, double y, double z)专门用于绘制立方体。

void drawCube(double x, double y, double z){ glPushMatrix();/*!划重点!不写后果很严重(当然这个错误不是我犯得哈哈)*/ glTranslatef(x, y, z); glColor3f(1.0f, 1.0f, 1.0f); glBegin(GL_QUADS); glNormal3f(0.0f, 1.0f, 0.0f);//法向量,光照明要用的 glVertex3f(0.5f, 0.5f, 0.5f); glVertex3f(0.5f, 0.5f, -0.5f); glVertex3f(-0.5f, 0.5f, -0.5f); glVertex3f(-0.5f, 0.5f, 0.5f); glEnd(); glBegin(GL_QUADS); glNormal3f(0.0f, -1.0f, 0.0f); glVertex3f(0.5f, -0.5f, 0.5f); glVertex3f(-0.5f, -0.5f, 0.5f); glVertex3f(-0.5f, -0.5f, -0.5f); glVertex3f(0.5f, -0.5f, -0.5f); glEnd(); glBegin(GL_QUADS); glNormal3f(0.0f, 0.0f, 1.0f); glVertex3f(0.5f, 0.5f, 0.5f); glVertex3f(-0.5f, 0.5f, 0.5f); glVertex3f(-0.5f, -0.5f, 0.5f); glVertex3f(0.5f, -0.5f, 0.5f); glEnd(); glBegin(GL_QUADS); glNormal3f(0.0f, 0.0f, -1.0f); glVertex3f(0.5f, 0.5f, -0.5f); glVertex3f(0.5f, -0.5f, -0.5f); glVertex3f(-0.5f, -0.5f, -0.5f); glVertex3f(-0.5f, 0.5f, -0.5f); glEnd(); glBegin(GL_QUADS); glNormal3f(-1.0f, 0.0f, 0.0f); glVertex3f(-0.5f, 0.5f, 0.5f); glVertex3f(-0.5f, 0.5f, -0.5f); glVertex3f(-0.5f, -0.5f, -0.5f); glVertex3f(-0.5f, -0.5f, 0.5f); glEnd(); glBegin(GL_QUADS); glNormal3f(1.0f, 0.0f, 0.0f); glVertex3f(0.5f, 0.5f, 0.5f); glVertex3f(0.5f, -0.5f, 0.5f); glVertex3f(0.5f, -0.5f, -0.5f); glVertex3f(0.5f, 0.5f, -0.5f); glEnd(); glPopMatrix();/*有Push当然要有Pop*/ }

画迷宫我是用数组存的,因为还要实现同时加入二维辅助地图,替身在三维迷宫探索的同时,在小地图中显示已经探索的区域这个功能。(感觉很弱鸡啊…但是也没想出其他好办法…好在跑起来不卡…哈…哈…) 声明数组int maze[900]用于存储一个30x30的迷宫。用0和1初始化数组。

maze[i]=0: 坐标(i - i / 30 * 30, i / 30,-20)处不绘制立方体。 maze[j]=1: 坐标(j - j / 30 * 30, j / 30,-20)处绘制立方体。

(初始化数组的过程赶时间写的超烂…不放了就…)

void drawMaze(){ glEnable(GL_SCISSOR_TEST); glScissor(0, 0, 700, 700); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_SCISSOR_TEST); glViewport(0, 0,700,700); glEnable(GL_LIGHT0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(50, 1, 0.5, 100); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(lookX, lookY, lookZ, centerX, centerY, centerZ, upX, upY, upZ); //drawGamer(); //画三维地图 glPushMatrix(); glTranslatef(-15, -14, 0); for (int i = 0; i < 900; i++){ if (maze[i] == 1||maze[i]==-1){ drawCube(i - i / 30 * 30, i / 30,-20); } } glPopMatrix(); //画地板 glPushMatrix(); glColor3f(1.0f, 1.0f, 1.0f); glBegin(GL_QUADS); glNormal3f(0.0f, 0.0f, 1.0f); glVertex3f(14, 15, -20.5); glVertex3f(-15, 15, -20.5); glVertex3f(-15, -14.9, -20.5); glVertex3f(14, -14.9, -20.5); glEnd(); glPopMatrix(); }

效果应该就是这样orz有点丑…贴上纹理会好很多的…

有空再接着写实现了全部功能的:) 完整源代码下载

转载请注明原文地址: https://www.6miu.com/read-12152.html

最新回复(0)