软件工程课程设计-游戏程序设计课程设计.doc_第1页
软件工程课程设计-游戏程序设计课程设计.doc_第2页
软件工程课程设计-游戏程序设计课程设计.doc_第3页
软件工程课程设计-游戏程序设计课程设计.doc_第4页
软件工程课程设计-游戏程序设计课程设计.doc_第5页
已阅读5页,还剩24页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

游戏程序设计课程设计学院:信息科学与技术学院专业:软件工程班级:09级软件(二)班姓名:学号:200905070201摘要 娱乐一直是计算机的一大应用。在中国,随着网络的发展,休闲化游戏拥有了大量的玩家,且逐渐发展出棋牌类、音乐类、竞速类、体育类、格斗类和益智类等多种游戏类型。 最常见的竞速类游戏就是赛车游戏,玩家可从疾驰的速度中获得刺激感,而从高超技巧带来的流畅性操作中还可获取一定的满足感。3d赛车游戏是整个赛车游戏的重要组成部分,随着游戏行业的快速发展,2d游戏市场份额已经大幅降低 本文实现了一款赛车游戏,该游戏分为场景渲染,天空渲染,赛车的地形跟踪和碰撞检测等几个部分。场景渲染,和天空渲染等构成游戏的渲染画面,基于opengl技术实现。赛车在场景中的漫游和赛车的地形跟踪系统和碰撞检测构成了游戏的主要逻辑。关键词: 3d, opengl, 游戏程序设计, 赛车游戏引言课题背景及意义当前随着计算机的深入普及,越来越多的人有了个人电脑,人们运用计算机完成许多重要的工作,计算机在人们的生活中变得越来越重要。随着计算机的应用和发展计算机已经不单纯是一个工作工具,人们越来越重视计算机的娱乐性。今年来游戏产业规模持续成长,全球每年游戏业总产值已经突破200亿美金,远远超越好莱坞电影产业以及音乐娱乐事业,而成为目前娱乐事业的最大主流。不过游戏产业光鲜亮丽的背后却隐含着高风险、高成本的危机,显示游戏产业慢慢步入微利时代。在这种趋势下各种小型的低成本的游戏软件应运而生。这些小游戏都以益智和娱乐为目的,不仅给紧张工作的人们以轻松,还可以让人们的大脑得到开发。关于本课题使用游戏软件自然是为了满足人们对娱乐性的要求,本次课程设计是采用3d设计,对系统配置有一定的要求。作为本系统的开发工具,microsoft visual c+成为首选。它具有可视化的编程界面、详细的提示、以及完善的帮助文档,使得软件开发人员感到无比的亲切感。另外,还需要配置opengl。一、游戏的总体分析与设计1.1游戏的功能简介 通过仿真游戏地图和游戏场景,完成本系统后,能通过w、a、d、s键控制赛车行驶方向。1.2系统设计1.2.1模块与流程规划 1.2.2系统流程图初始化:这部分执行与其他任何程序类似的标准操作,如内存分配,资源获取,从磁盘加载数据等;进入游戏循环:这部分进入游戏循环,用户将在这里不断地执行动作,知道退出主循环为止;接收玩家输入:这部分处理玩家输入,或将其存储到缓冲区,供游戏逻辑使用;执行游戏逻辑:这部分包含游戏代码的主体部分,将执行人工智能,物理系统和通用游戏逻辑,并根据结果在屏幕上绘制下一帧;图形渲染:在这一部分中,讲根据玩家输入以及逻辑的执行结果,生成下一个游戏动画帧。关闭:退出游戏;1.2.3各类的设计1)ggamemap方法:(1)载入位图高程static bool loadhightmap(const char *filename, int *&ymap, int &w, int &h); (2)构造地图单例对象static ggamemap * create(); (3)释放地图单例对象static void destroy(); (4)得到地图单例对象指针static ggamemap * getcurrent() (5)检测指定点与赛道是否发生碰撞bool iscollision(double x, double z); (6)清空数据结构, 释放资源void clear(); (7)载入地图bool load(const char *filename, gtreebillboard *ptreebillboard);2) gpool方法:(1)池塘构造函数, 传入池塘地面纹理和水波纹理gpool(gtexture2d *plandtex, gtexture2d *pwatertex); (2)绘制池塘virtual void draw();3) gskydome方法:(1)初始化gskydome(gtexture2d *ptex, double r=1000); (2)绘制virtual void draw();4) gtree方法:(1)从文件流中载入树木bool load(file *fp); (2)根据视点坐标更新旋转角度和距离void update(double cx, double cz); (3)绘制树木virtual void draw(); (4)根据视点到树木的距离反比较树木对象指针int gcomparetreeptr(const void *ptr1, const void *ptr2);5) gcurvedroad方法:(1)得到旋转角double getrotangle() (2)设置旋转角void setrotangle(double rot) (3)绘制直赛道(调用前, 请先设置正确的旋转角度和顺时针标志)virtual void draw(); 6) gcar方法:(1)判断是否刹车bool isbreak() (2)设置状态为刹车void setbreak(bool isbreak) (3)判断是否转向角double getsteerangle() (4)设置转向角void setsteerangle(double af) (5)绘制汽车virtual void draw();7) gdashboard方法:(1)速度变化, 更新指针角度void changepointer(double v); (2)绘制仪表盘virtual void draw();8) gminimap方法:(1)绘制道路瓦片void drawroadtile(char typ); (2)汽车的位置void setcarpos(const gvector3d &pos); (3)绘制迷你地图virtual void draw();2、 详细设计2.1 赛车地图资源的加载 赛车地图资源共分为平原高程,山地高程,池塘高程的加载。在功能的实现主要是在ggamemap类中实现的。该类中使用load()方法用于对资源的加载。2.2 天空渲染 天空的渲染主要是使用天空穹技术来实现的。天空穹是一个笼罩在整个赛场之上的半球,它会随着赛道的改变而发生变化,从而使人感觉一直都在场景之中。在三维赛车游戏中我们的视线一直是小于45度的,所以在绘制天空时不必将半圆形全部画上,只画在我们视线内的部分就足够。在绘制是主要使用三角网格技术,将没有顶盖的半球分解成若干个三角形,分别计算出每个三角形各定点的坐标和纹理坐标,再在显示列表中绘制这些三角形。 在程序当中,天空穹主要是用 gskydome类来实现的。该类继承于gshape类。在gskydome类有gtexture2d*mpskytex/ 天空纹理 double mradius/ 天空穹半径 double*mtexbuf/ 纹理缓冲double*mvertexbuf/ 顶点缓冲 int mtricount/ 三角形数目 glintmdisplaylist;/ 显示列表一些数据成员 这样一些数据成员。同时还有一个draw()方法用来实现对天空穹的绘制。2.3 赛车道路的绘制 赛道共分为2种分别为直道和弯道。直道的绘制相对比较简单只需要绘制一个矩形即可,而弯道要用三角网格技术来将赛道分解成许多三角形,弯赛道有四种类型,但是我们只需绘制其中一种,其他三种可以通过旋转绘制出来的那种类型来得到。由于在游戏当中并不能看到整个赛道,所以在绘制时只需要绘制部分可见的赛道即可。 直赛道的绘制是在gstraightroad类当中完成的,该类同样继承于gshape类,在gstraightroad的构造函数中实现了各个定点的坐标和纹理坐标的计算,最后在通过调用该类的draw()方法实现直赛道的绘制。 弯赛道的绘制是在groadcirque类中完成的,同样它也是继承于gshape类,它的构造函数实现了各个定点的坐标和纹理坐标的计算。最后再调用draw()方法绘制。2.4 赛车模型的加载和绘制 汽车模型需要从文件读取,为了显示汽车轮胎的转动和是否刹车(尾灯的亮与不亮),车身与四个轮胎和尾灯要分别绘制。用load()读取汽车模型的文件,汽车也是用三角网格方法绘制。 在程序当中,使用gtrimesh类来实现赛车赛车模型的加载首先通过loadfromobj()方法对赛车模型的加载,同时使用gcar类对赛车模型进行绘画。2.5 树木的绘制 树木的绘制是采用广告牌的方式进行绘制的。广告牌技术及无论赛车怎样旋转始终是图片与我们的视线锤子,即赛车旋转多少度,图片亦随之旋转相应的角度。树木图片加载后还要对其进行消影,对树木按与视点的远近进行排序,远处的树排在前面,绘制的时候最后绘制。 树木的绘制主要是在gtreebillboard类中实现的,该类首先通过load()方法实现对树木图片的加载,其次使用 update()方法获得树木需要旋转的角度以及树木的距离,最后在调用draw()进行树木的绘画。2.6 速度仪的绘制 汽车速度表盘的设计与实现:先绘制一个正方形表盘,再贴上红色纹理表示指针。指针要先平移后旋转,从而达到指针跟随汽车速度的增加与减少而在不同的位置绘制的效果。 速度仪的绘制是在gdashboard中完成的,首先该类使用changepointer()方法获得在速度改变是指针需要旋转的角度,在使用draw()方法对速度表盘进行绘制。2.7 迷你地图的绘制 迷你地图绘制先是绘制一个地图模型,然后在贴上纹理指针。最后根据汽车的移动计算出指针的移动速度。 迷你地图的绘制是在gminimap 类中实现的,该类首先通过drawroadtile()方法绘制道路瓦片,然后在通过setcarpos()方法计算出指针一定速度和方向,最后使用draw()绘制迷你地图。2.8 碰撞检测 碰撞检测主要是检测赛车与赛道之间的碰撞,即赛车与直赛道和玩赛道之间的碰撞检测。 直赛道检测时只需要查看汽车两边是否超出赛道的两边即可,而玩赛道检测则必须检测弯道的四种方式。三、运行效果四、心得体会 在完成本次课程设计的过程中遇到了很多的问题,其中的很多知识还没有了解和掌握。在本次课程设计中,同学给予了很多的帮助,使我对整个课程设计的思路有了总体的把握,并耐心的帮助我解决了许多问题,使我有了很大的收获。5、 附录(部分主要源代码)1地图类的实现 ggamemap * ggamemap:create()if(mpgamemap) destroy();/ 载入平原高程if(!loadhightmap(plain_map_fname, plain_y_map, cell_cols, cell_rows)return null;/ 载入山地高程if(!loadhightmap(hill_map_fname, hill_y_map, cell_cols, cell_rows)return null;/ 载入池塘高程if(!loadhightmap(pool_map_fname, pool_y_map, cell_cols, cell_rows)return null;/ 将池塘地面高度向下减去255int i, j;for(i=0; icell_rows; i+)for(j=0; jcell_cols; j+)pool_y_mapij -= 255;/ 有用单元行列须减1cell_rows-;cell_cols-;x_span = unit_size * cell_cols;z_span = unit_size * cell_rows;cell_x_offset = -0.5 * x_span;cell_z_offset = -0.5 * z_span;road_w = 0.5 * x_span;/ 构造单例对象mpgamemap = new ggamemap();return mpgamemap;bool ggamemap:loadhightmap(const char *filename, int *&ymap, int &w, int &h)iluint image; ilgenimages(1, &image);ilbindimage(image);char imgfilename256;strcpy(imgfilename, filename);ilboolean ok = illoadimage(imgfilename);if(!ok) return false;int i, j, idx;w = ilgetinteger(il_image_width);h = ilgetinteger(il_image_height);unsigned char *data = new unsigned charw*h*3;ilcopypixels(0, 0, 0, w, h, 1, il_rgb, il_unsigned_byte, data);galloc2(ymap, h, w);for(i=0; ih; i+)for(j=0; jw; j+)idx = (i*w + j)*3;ymapij = (dataidx+dataidx+1+dataidx+2) / 3;delete data;ildeleteimages(1, &image);return true;bool ggamemap:load(const char *filename, gtreebillboard *ptreebillboard)clear();int i, j, di32;char key256, buf256;file *fp = fopen(filename, r);if(!fp) return false;while(!feof(fp)/ 获取关键字fgets(buf, 255, fp);strtrim(key, buf);/ 跳过空白行if(strlen(key) = 0) continue ;/ 转换为大写字符串strtoupper(key, key);if(strcmp(key, map_size) = 0)/ 读取地图行列数fscanf(fp, %d %d, &mrowcount, &mcolcount);/ 分配地图数组galloc2(mlandmap, mrowcount, mcolcount);galloc2(mroadmap, mrowcount, mcolcount);else if(strcmp(key, begin) = 0)fscanf(fp, %lf %lf, &mracebeginx, &mracebeginz);mracebeginx *= x_span;mracebeginz *= z_span;else if(strcmp(key, land) = 0)/ 读取地形地图for(i=0; imrowcount; i+)for(j=0; jmcolcount; j+)fscanf(fp, %d, &di32);mlandmapij = di32;else if(strcmp(key, road) = 0)/ 读取赛道地图for(i=0; imrowcount; i+)for(j=0; jmcolcount; j+)fscanf(fp, %d, &di32);mroadmapij = di32;else if(strcmp(key, tree) = 0)/ 读取树木列表fscanf(fp, %d, &mtreecount);mtreelist = new gtree *mtreecount;for(i=0; iload(fp);mtreelisti = ptree;fclose(fp);return true;2.池塘类的实现gpool:gpool(gtexture2d *plandtex, gtexture2d *pwatertex)mpland = new gland(plandtex, pool_y_map);mpwatertex = pwatertex;mframeidx = 0;int i,j,k, it,nrow, ncol;double s,x,z,y0,y1,ymax,deltaf,af,unitsize,offsetx,offsetz;nrow = 8; ncol = 8;s =(double) cell_rows /nrow;ymax = 2.0;deltaf = pi * 4/ nrow;unitsize = s* unit_size;offsetx = -0.5*unitsize * ncol;offsetz = -0.5*unitsize * nrow;mtricount = nrow * ncol *2;/分配缓存for( i = 0; i8; i+)mvertexbufsi = new doublemtricount * 9;mtexbuf = new doublemtricount * 6;gltgeneratetexcoord(ncol,nrow,1.0/nrow,1.0/ncol,mtexbuf);for(k = 0; k8; k+)af = k * pi * 0.25;it = 0;for(i = 0; i nrow; i+)z = offsetz + i* unitsize;for(j=0; jncol; j+)x = offsetx + j*unitsize;y0 = sin(af + j*deltaf) *ymax;y1 = sin(af + (j+1)*deltaf) *ymax;mvertexbufskit+ = x;mvertexbufskit+ = y0;mvertexbufskit+ = z;mvertexbufskit+ = x;mvertexbufskit+ = y0;mvertexbufskit+ = z+unitsize;mvertexbufskit+ = x+unitsize;mvertexbufskit+ = y1;mvertexbufskit+ = z;mvertexbufskit+ = x+unitsize;mvertexbufskit+ = y1;mvertexbufskit+ = z;mvertexbufskit+ = x;mvertexbufskit+ = y0;mvertexbufskit+ = z+unitsize;mvertexbufskit+ = x+unitsize;mvertexbufskit+ = y1;mvertexbufskit+ = z+unitsize;for(k = 0; kuse();glpushmatrix();gltranslated(0, -4.0, 0);glbegin(gl_triangles);for(i=0; idraw();glcalllist(mdisplaylistsmframeidx);3.天空穹类的实现gskydome:gskydome(gtexture2d *ptex, double r)mpskytex = ptex;mradius = r;int ic,it,nw,nh;double step, v, h, vr,hr, sr;step = 15; /角度间隔sr = 15 * angle_to_radian;nw = (int) (360 / step);nh = (int) (45 / step);mtricount = nw * nh * 2;mvertexbuf = new doublemtricount * 9;mtexbuf = new doublemtricount * 6;gltgeneratetexcoord(nw, nh, 1.0/nw, 1.0/nh, mtexbuf);int i,j,k = 0;for(i=0, v=0; inh; i+, v+=step) vr = v * angle_to_radian;for(j=0, h=0; juse();glbegin(gl_triangles);for(i=0; imvdistance2 p2-mvdistance2) return -1;else if(p1-mvdistance2 mvdistance2) return 1;else return 0;5.直赛道的实现groadcylinder:groadcylinder(gtexture2d *ptex, double length, double r, double start, double over, int slices)int j, k;double x, span, angle;mptex = ptex;mtricount = slices * 1 * 2;mvertexbuf = new doublemtricount * 9;mtexbuf = new doublemtricount * 6;gltgeneratetexcoord(1, slices, 1, 1.0/slices, mtexbuf);x = length * 0.5;start *= angle_to_radian;over *= angle_to_radian;span = (over-start) / slices;k = 0;for(j=0, angle=start; juse();glbegin(gl_triangles);for(i=0; imtricount; i+)gltexcoord2dv(&mtexbufi*6);glvertex3dv(&mvertexbufi*9);gltexcoord2dv(&mtexbufi*6+2);glvertex3dv(&mvertexbufi*9+3);gltexcoord2dv(&mtexbufi*6+4);glvertex3dv(&mvertexbufi*9+6);glend();6.弯赛道的实现groadcirque:groadcirque(gtexture2d *ptex, double ringr, double rstart, double rover, int rslices, double cirr, double cstart, double cover, int cslices, double repeat)int i, j, k;double cspan, rspan, cangle, rangle;mptex = ptex;rstart *= angle_to_radian;rover *= angle_to_radian;cstart *= angle_to_radian;cover *= angle_to_radian;mtricount = rslices * cslices * 2;mvertexbuf = new doublemtricount * 9;mtexbuf = new doublemtricount * 6;gltgeneratetexcoord(rslices, cslices, repeat/rslices, 1.0/cslices, mtexbuf);rspan = (rover - rstart) / rslices;cspan = 1*(cover - cstart) / cslices;k = 0;for(j=0, cangle=cstart; jcslices; j+, cangle+=cspan)for(i=0, rangle=rstart; iuse();glbegin(gl_triangles);for(i=0; iuse();for(i=0; imrowcount; i+)for(j=0; jmcolcount; j+)if(pmap-mroadmapij = 0)glpushmatrix();gltranslated(j+0.5, i+0.5, 0);drawroadtile(pmap-m

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论