计算机科学与技术毕业设计(论文)-DirectX在游戏开发中的应用.doc_第1页
计算机科学与技术毕业设计(论文)-DirectX在游戏开发中的应用.doc_第2页
计算机科学与技术毕业设计(论文)-DirectX在游戏开发中的应用.doc_第3页
计算机科学与技术毕业设计(论文)-DirectX在游戏开发中的应用.doc_第4页
计算机科学与技术毕业设计(论文)-DirectX在游戏开发中的应用.doc_第5页
已阅读5页,还剩25页未读 继续免费阅读

下载本文档

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

文档简介

专 业 计 算 机 科 学 与 技 术指导教师 学 生 论文题目 DirectX在游戏开发中的应用 2011年5月6日HUBEI NORMAL UNIVERSITY 学号 01151404 编号 20050404 研究类型 应用研究 分 类 号 TP317.4(图像处理软件)学士学位论文Bachelors ThesisDirectX在游戏开发中的应用XXX(湖北师范学院 计算机科学系 湖北 黄石 435002)摘要:当游戏作为一种很重要的娱乐手段被大众接受时,游戏产业就已经注定会带巨大的经济效益。文章针对目前市场上流行的Windows平台下的主导开发工具DirectX对游戏开发进行初步的探讨,以两个不同类型的游戏的实现过程来研究DirectDraw、Direct3D 在二维和三维图形处理方面的应用,同时也对DirectSound、DirectInput也进行了初步的研究。关键词:游戏开发 游戏开发包 DirectDraw Direct3D DirectMusic DirectInput 游戏引擎中图分类号:TP317.4Application of DirectX In Game DevelopmentHao xuefang(Department of Computer Science Hubei Normal University Huangshi 435002)Abstract: When Game was accepted by many people as a very important enterainment means,Game-industry will bring to us enormous economic benefit indisputably. This dissertation aim to the most popular Operating System Windows and using the leading game development tools kits DirectX base it, discussing elementary how to develop a game.The emphases is the use of DirectDraw and Direct3D in graphics processing in two dimension and three dimension.and the simply introduce of DirectSound and DirectInput.Keywords: Game-Development DirectXSDK DirectDraw Direct3D DirectMusic DirectInput GameEngine目 录一、引言.1二、游戏开发所需技术及DirectX简介.11DirectX概述.12开发平面游戏所需要的技术分析.23开发3D游戏所需要的技术分析3三、平面游戏LeapMan的实现.41 DirectDraw在二维图形处理方面的功能分析42LeapMan游戏中图片素材预置.73概要设计与算法分析. .74LeapMan的详细设计. .10四、三维游戏Pools Up实现.121三维模型的建立.122碰撞算法分析.133Direct3D在Pools Up中的应用15五、DirectInput与DirectSound在游戏开发中的应用19六、结束语.21致 谢.22参考文献.23一、引言从2001年开始,游戏作为一种产业已经渐渐的为中国大众接受,它所带来的经济效益和社会效益更是人们之前没有估计到的。目前电子竞技已经成为一个本科专业,游戏开发也是“863计划”中一个重要攻关方向。从事游戏行业对软件开发的人员来说有着很广阔的前景。游戏开发相对其他软件开发来说特别复杂,它需要解决图形显示、网络传输、声音处理、I/O控制等问题,这些一般都必须借助游戏开发包(游戏引擎)来实现。图形技术的解决方案有OpenGL和DirectX,OpenGL是三维图形的API标准,但DirectX除了能解决三维图形问题,而且支持2D图形、音效管理、网络互连、外设控制等,它作为一套完整的游戏开发包而成为事实上的行业标准。本文分别以一个二维游戏和一个三维游戏的开发过程来论述DirectX在游戏开发中的应用,向人们展示了各种商业游戏开发的基本方法和一般过程。二、游戏开发所需技术及DirectX简介1DirectX概述在Windows环境中,程序一般不能直接访问硬件,对硬件功能的利用一般都只能通过能用GDI和MCI等设备接口来实现。游戏对实时性要求特别高,这使得稍大规模的游戏都无法在Windows GDI环境下运行。为了解决这个问题,微软公司开发出了DirectX SDK。这是一些基于COM技术的组件。在调用DirectX函数或是Method的时候,其实是调用一些DirectX DLL,然后这些DLL再调用显卡厂商所写的驱动程序,也就是说真正驱动硬件的是厂商所写的驱动程序1,这就使得程序执行效率非常高,并且能极大可能的把硬件的全部功能都发挥起来。同时,DirectX也具有各种硬件仿真功能,如果调用的功能硬件加速器不支持,DirectX就利用自己的仿真加速器来实现同样的效果。这样用DirectX编出的游戏不再担心硬件功能不支持的问题了。DirectX的功能非常强大,它包括以下几个组件: DirectDraw直接操纵显卡,支持图像的移动、拉伸等各种功能 DirectSound提供低延时的声音混合系统,支持硬件加速 DirectPlay简化游戏使用通讯设备的入口,提供通讯功能的集成和多种通讯协议统一接口功能 Direct3D提供三维图形显示的支持 DirectInput兼容所有的输入外设,简化游戏控制方法 DirectSetup简化游戏安装过程,提供多用户登陆的方法以运行程序 DirectMusic支持MIDI音频,支持运行时动态作曲。DirectX到9.0版时,新的组件DirectGraphics已经代替了DirectDraw与Direct3D。其他组件的功能也进行了进一步的扩展。DirectX在开发游戏方面的强大功能将会在本文的论述中看到。目前它的应用范围已经远远的超过了游戏开发领域,Windows平台下音频与视频的处理大部分也是利用DirectX来实现的。相信今后DirectX的领域会更加广泛。2开发平面游戏所需要的技术DirectDraw技术主要是为了解决二维平面游戏的问题而引入的。在DirectDraw的诞生之前,每个游戏厂商都不得不写自己的游戏引擎,而这种游戏引擎过多的依赖机器硬件所提供的图形功能,而且往往会局限在某一种硬件平台,所以当时的游戏开发具有相当大的困难。但纵观各种2D游戏引擎的功能,基本上都有如下几点5: 直接移动内存中的数据(一般来说是移动图片)。即可以把一张已经有的图片从一个内存块移动到另外一个地方,在游戏中看到的效果就是图片由一个位置移动到了另外的一个位置 指定一张图片中的某一部分显示出来。很多时候游戏中都会出现一些图形相同的地方,例如两位游戏角色的衣服,如果能指定图片的某一部分显示在指定的位置,不仅可以提高开发的灵活性,还可以使游戏所使用的图片大大减少,这对提高游戏的执行效率是非常关键的。 支持ColorKey效果。多张图片构成一个比较大的场景时,可以指定透明色,图片中不想要的颜色不显示出来,给人的感觉就是不同的角色之间的无缝接触。 控制显存中的主显示区域(也叫可见区域)。在游戏中需要高频率的切换场景时,如果通过不断的调入内存、显示、调出内存这样一个反复的过程来切换图片,效率将会变得很低。如果能够控制显卡中显示出来的数据区域,切换时只更换主显存基址即实现了动画。有了这种功能后游戏中即使再高频的切换角色也不会对画面的流畅性造成任何影响。 支持多缓冲技术。充分发挥计算机的并行处理能力,在显示器输出图像的同时,把下一帧将要显示的图形拷贝到在另个显存区域处理好,显示的时候只要改变显卡的显示区域基址即可。 支持字体显示、调色板技术和绘图功能。如果要更好的实现游戏的效果,游戏开发包最好能够支持下列图形功能: 支持半透明效果。 支持页面覆盖,即控制某一图形始终显示在最前方。 支持多种图形格式。1、 开发3D游戏所需要的技术要开发一个三维游戏,首先要解决的问题就是构造一个虚拟的三维世界,给玩家的感觉如置身在现实世界一样。当然,用户能看到的就只有一个显示平面,三维效果就是能够观察到三维世界中的不同的侧面。在三维场景显示出来之前需将三维世界中某一个观察点看到的内容投影到显存当中。能够开发一个三维游戏的游戏开发包都具有以下功能9: 构造虚拟的三维世界。这是3D的前提,实际上就是在计算机中建立一个三维坐标系。三维世界中有每一个角色都有方向与位置的概念,这些都可以通过一个坐标系就可以确定。 支持平移、旋转、缩放功能。这些功能都是基于坐标变换14的。 支持光照与投影。用算法来模拟现实生活中明暗效果,支持点光源,平行光和聚光灯,支持光线跟踪与阴影 支持材质和贴图。现实中一个物体有其自身的表现状态,包括颜色,反光强度和表面的图案,在计算机的三维世界中颜色与反光强度的需要有材质的支持,而物理表面的图案则需要贴图功能来支持。 支持观察点与观察角度。ViewPort决定程序显示出三维场景的哪一部分,即看到计算机中的哪些场景。 支持渲染功能。把观察点视线范围内的场景投影到计算机屏幕。 支持外部模型。每一个三维游戏都需要很多物体,这里所述的物体不一定是玩家,它还包括场景中的房屋,树木等三维物体,当物体太多的时候,每个角色不可能都靠软件设计师计算得到,如果那样的话工作量太大了。目前有很多的三维图形软件像3DSMAX、Maya等都可以直接建立三维模型,只有游戏开发包支持把外部的模型直接导入到程序中,在适当的时候把角色调出来显示,这样才可能开发大型的游戏。三、平面游戏LeapMan的实现1DirectDraw在二维图形处理方面的功能分析4DirectDraw的图形处理功能非常强大,它可以评估视频硬件的能力, 只要可能,它就会对其某一特性加以利用。例如,如果你的显卡支持硬件 Blit, DirectDraw 就会将位图映射这一操作分派给显卡来完成,极大的提升运行速度。如果软件中调用的功能硬件功能不支持时, DirectDraw 便利用硬件仿真层(HEL)来完成请求的这项操作。DirectDraw的功能还包括:支持多后台缓存(back buffers)的换页(page flipping)操作;支持窗口和全屏模式应用程序的裁剪;支持 3-D Z 缓存;支持带 Z 轴方向的硬件辅助覆盖;支持可访问图象缩放(stretching)操作;支持同时访问标准的和增强的显示设备内存区,包括动态改变调色板,独占访问硬件,和分辨率切换等等。这里以一个很简单的动画时钟来说明这种技术。图1 背景图图1和图2是将要使用的两张图片,图1是背景图,图2为前景图,利用图片局部显示功能,在程序中分别取出2、0、3、7、4、6、:、等数据块 (如图3)图2 前景图图3 程序定位图图4 程序拼图效果当然,这里所谓的“取”并不是把图片给分割出来,而是指程序在图片中定位,显示的时候只显示其中的一部分。程序最终显示出的程序拼图效果如图4。需要强调的是,游戏中所用到的素材图片只有图1和图2,所有的游戏都是利用这种原理,把基本的图片在一起组合而构成大规模的场景。在一个游戏程序中,一般来讲将会有很多要显示的图片,只有合理的使用有限的内存资源才能使游戏的画面更加流畅。所以,一张图片在调入内存后,尽可能的不要再次调入。倘若现在程序要求:原来显示的地方显示为,如果能把已经显示了后者的内存区域的拷贝到前者现有的内存块内,就可以达到了这种变化的效果。这个功能就是显示内数据块移动功能。在DirectX开发包中,一个函数就可以实现局部显示与图形数据块的移动功能。这个函数的原型就是:BOOL BitBlt(HDC hdcDest,int nXDest,int nYDest,int nWidth,int nHeight,HDC hdcSrc,int nXSrc,int nYSrc,DWORD dwRop);根据系统时间,再结合BitBlt函数,得到的效果图如图5和图6: 图5 动画效果图B图6 动画效果图C很明显,现在已经能够实现动画效果了,但是整个的画面却始终有一个黑的背景,如果能去掉背景色使之不显示的话,才具备游戏开发的基本要求。图7 透明效果图A图8 透明效果图B在游戏开发技术当中,这种指定色不显示的效果叫做ColorKey(关键色)技术,每张图片都可以指定若干种ColorKey。平面游戏(如星际争霸)中每一个场景,每一个玩家角色,都有许许多的方形图片组成的,也有将众多的角色和场景都包括在一张图片中的情况。但是每个图片都有一个背景色,为了方便程序控制,根据制作者的要求,将这种颜色设为统一的颜色。显示时图片中像素值与ColorKey相同的就不会显示在图层上。在DirectDraw中,这种功能对应的函数是:HRESULT SetColorKey(DWORD dwFlags,LPDCOLORKEY lpDDColorKey);其中dwFlags就是一个参数,lpDDColorKey就是要在程序隐藏的颜色。最终实现效果如图7和图8(透明的背景)2.LeapMan游戏中图片素材预置图9 Player1图10 弹板链图11 Player2在LeapMan游戏当中,因为有很多的场景,也有很多的角色,所以,在编程之前一定要把这些图片全部都按照一定的规则排列,手工的计算各个子图形的位置,这些有序的图片叫作Sprite(精灵)。LeapMan中这么多的Sprite都在一张图形当中(见附件)。通过PhotoShop把这些图片有规律的排列,同时记录下这些信息:角色Player(如图9)的在图片MainSprite8pp.bmp的左上角顶点位置信息分别为:(0,0),(32,0),(64,0),(96,0),(0,32),(32,32),(64,32),(96,32),(0,64),(32,64),(64,64),(96,64),这些值都是以像素为单位。图10为其中一种弹板图,它也有自身的规律性,左上角顶点坐标为(384,208),长和宽分别为95和25,图11为Player的Sprite图,每个角色大小和Player1一样,它的左上角顶点为(160,0)。这些数据都将在程序控制时用到。3.概要设计与算法分析在这个软件当中,总共有六种Sprite,一种为Player,其它的就是程序中将要出来的五种档板(普通板、弹板、滚板、软板和钉板)。软件中玩家的动作都是通过不断地切换人物角色图片来实现的,当切换频率达到一定值的时候就成了流畅的动画。如果要显示一张图片,在程序中确定它的左上角和它的长宽值就能够把这部分图形显示出来。这些值都存放在一个链表当中。也就是说需要六个精灵链表。实际上是一个位置信息表。位置信息结构如下:struct SpriteInfoINTnLeft;/标识Sprite在位图中左临界边的象素值INT nTop;/标识Sprite在位图中上临界边的象素值INT nRight;/标识Sprite在位图中右临界边的象素值INT nBottom;/ 标识Sprite在位图中下临界边的象素值INT nWidth;/标识Sprite在位图中宽度信息INT nHeight;/标识Sprite在位图中高度信息;同时,程序执行时挡板是不断的由底向上逐一出现的,当上升到一定高度的时候就从屏幕上消失,这刚好可以用一个队列来实现。队列中有不同的挡板,所以在此定义精灵类型为:enum BoardTypePLANE,SPRING,SLIDE,SINK,STING;由于每种精灵的个数都是不同的。程序中利用宏定义一些标识个数的常量:#define NUM_STING1#define NUM_SLIDE8#define NUM_SINK6#define NUM_SPRING7#define NUM_PLANE1#define NUM_MEN 80精灵链表如下:SpriteInfog_menSpriteNUM_MEN+2;SpriteInfog_springSpriteNUM_SPRING;SpriteInfog_sinkSpriteNUM_SINK;SpriteInfog_slideSpriteNUM_SLIDE;SpriteInfog_planeSpriteNUM_PLANE;SpriteInfog_stingSpriteNUM_STING;程序中变换图片时需要的位置信息都在这些链表当中。在函数BOOL InitSprite()中,把通过计算得到值都赋给队列中的每一个变量。有了精灵的位置信息后,还需要考虑第二个问题:这些精灵最终要显示在屏幕上的什么位置呢?同时,每个精灵是动态的,有速度的和次态的,这些信息又该如何表示呢?解决的方案如下:30struct PlayerINT nmenIndex;/Player的角色索引INT nleft;INT nTop;/Player在屏幕上的位置INT Tending;/Player的运动方向Player1;struct BoardBoardType enumType;/挡板类型INT nSpriteIndex;/挡板的索引INTnLeft;/INT nTop;/挡板位置INT Tending;/挡板动向;其中Player变量只定义了一个表示一个玩家,但是挡板不同的是它有很多个,构成一个角色队列,程序中用一个类封装的。Sprite_Queue在满足条件时更新角色队列,从而实现这个动态变化的效果。游戏中需要一个函数动态而随机的生成挡板队列,功能的实现在CQueue:CreateQueue()当中。对它的要求是随机性和可控性,可控性即某一种板出现的比例大而另一种板出现的比例小。这里,随机函数的生成是使用Rand(),它可以随机的生成0- RAND_MAX之间的任意一个数,其中RAND_MAX 的宏定义如下:#define RAND_MAX 0x7fff,如果希望得到一个1-100之间的整数,把Rand()函数返回值对100求余就可以了。程序中相应代码是: LONG lRand = rand()%max; return lRand;若需要控制某一种板出现的机率大些,将需要将随机结果再进行一个区域判断,如:如果生成的数在1-20之间的就是弹板,1-10之间的数就表示生成一个滑板。这种定界方法可以解决任何一种随机数生成的问题。LeapMan游戏中,游戏循环的主体是ProcessNextFrame()函数,如果程序没有收到WM_QUIT消息时就反复的执行。函数中分别进行下列操作:InitSprite();/当程序第一次执行或者重新开始游戏时,进行角色初始化和变量重置。使用Sprite_Queue.CreateSpriteQueue()更新精灵队列。它的判断条件是:如果最下面的一个板上升到一定的高度的时候,就随机的生成一个新板并加入到精灵队列中。函数UpdateSprites()更新游戏中精灵的状态,包括人物角色状态的变化和板状态位置的变化。关于物体位置与状态的变化是由现在的状态和KeyDown键值来实现的。角色的变化控制函数UpdateSprites()包括1. MoveAllUP()把所有的Sprite上移2. MovePlayerUpDown()来确定玩家是否悬空下落或者是碰弹板上移3. MoveLeftOrRight()来根据外部按键状态左右移动玩家角色,如果按左键,MoveLeft状态为1,那么Player1就向左移动若干单位;如果右就为-1,右移若干单位;同样如果没有按键就为0,表示不移动4. CheckIfInAire()函数来检测是否悬空,它通过索引来逐一检索精灵串,取得现在的位置信息,看看它们的区域是否重合,如果有的话就表明Player站在板上,否则就在使Player下落,并显示下一个角色图。5. ChangeSprites()决定场景中所有精灵的变化,这种改变是按照预定义的规则进行的。最后一步操作是DisplayFrame(),把所有的角色与场景显示到屏幕上,在显示的时候,不同角色优先级不同,先用冒泡排序法将它们的位置排序后,使最后面的Sprite图就先显示出来,而最前面的图就后显示出来。最后就可以得到流畅的游戏画面了。图12 windows程序结构4.LeapMan的详细设计程序结构如图12:任何一个Windows程序都有这种结构。但是作为一个游戏,必须要有一个游戏循环,使游戏能够不停的执行下去,从PeekMessage()到DispathcMessage()都在While(TRUE)循环当中,如果没有外部消息时,就进行GameLoop处理下一帧信息。具体的DirectDraw使用方式如下2 3: DirectDrawCreate(NULL,&pDD,NULL)得到一个全局的DirectDraw对象指针; pDD-QueryInterface(IID_IdirectDraw7,(LPVOID*)&pDD2);得到一个将要使用的DirectDraw7对象指针; 用SetCooperativeLevel(GetSafeHwnd(),DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN| DDSCL_ALLOWMODEX)函数设置程序的协作级别。般的来说,最常用的有WINDOWS和FULLSCREEN两种,FULLSCREEN模式是一种独占模式,即不与其他的应用程序共享内存。为了提高游戏的性能,一般的游戏当规模达到一定的程序的时候,都倾向于使用FULLSCREEN模式使游戏的画面更加流畅; pDD2-SetDisplayMode(DWORD dwWidth,DWORD dwHeight,DWORD dwBPP, DWORD dwRefreshRate,DWORD dwFlags)来设置显示模式; 建立Surface。先填充DDSURFACEDESC2结构,然后调用pDD2 -CreateSurface(&Desc,&pPri,NULL); 利用LoadImage()函数载入将要使用的位图; CreateCompatibleDC()来创建与系统兼容的设备DC.; BitBlt(HDC hdcDest,int nXDest,int nYDest,int nWidth,int nHeight,HDC hdcSrc,int nXSrc,int nYSrc,DWORD dwRop)来进行位块传输; pDD2-SetColorKey(DDCKEY_SRCBLT,&ColorKey)来设置ColorKey;在Leapman当中,的主要技术就在于ColorKey和Blt,其他功能的的实现都是通过Csurface类和Cdisplay类来封装。使用的时候使用函数g_pDisplay-CreateSurfaceFromBitmap( &g_pBackSurface, MAKEINTRESOURCE( IDB_BMP_BACK ),SCREEN_WIDTH, SCREEN_HEIGHT ) ) )来建立一个有目标位图的Surface对象。当所有的Sprites都在内存Surface上绘制完毕,调用g_pDisplay()将这些画面输出到显示屏上。 四、Direct3D技术及应用1.三维模型的建立在Pools Up游戏中,所用到的模型有房屋、球桌、球杆与台球。由于球杆与台球的Mesh比较简单,程序中用填充自定义顶点方式建立。先定义了一个LPDIRECT3DVERTEXBUFFER8类型变量m_pVertexBuffer,然后通过向顶点缓冲区内填充点信息(包括材质信息与顶点位置),这样建立的模型不会有冗余信息,执行效率非常高。房屋与球桌相对来说比较复杂,所以先在3DSMax中建立好模型,导出为.3DS文件,利用DirectX8.0开发包中的conv3ds.exe把模型转换为.X格式,这种格式DirectX可以直接支持。2.碰撞算法分析图14 台球模型图13 碰撞示意图在这个三维游戏pools Up当中,关键问题就是在于球的碰撞控制。碰撞包括球与球的碰撞、球与球台的碰撞。总的来说碰撞就是预测未来帧N物体是否发生接触,如果物体发生了接触则在第N-1帧做出反射动作。否则运动物体间会发生明显嵌入或粘连现象。图8.1判断球与球之间是否发生碰撞非常简单,只要检测空间两点的距离是否小与球的直径便可。而球之间的碰撞反应如图13:假设两球是完全弹性碰撞,向量t为两球心间的连线,n是垂直于MO的向量。则v1在t上的分量v1t与v2在t上的分量v2t 动量守恒,由于两球质量相同联立动能守恒公式可得:碰撞后两球的速度在t上的分量被交换。而在n方向上v1n,v2n 将保持不变。最后把v1t、v1n、 ,v2t、v2n 分别沿x轴y轴投影对应合成后即可得到两球碰撞后的速度。球与球台的碰撞实作起来相对复杂,因为球台是一个网格模型,顶点数目较多而且形状不规则,所以只有另想办法。如图14,假想o是桌面上的一个球,沿圆心作4个向量把圆平均分为4份。每当球移动后就判断这些个向量是否有和桌面相交。如果有则进行碰撞反应处理,否则速度方向不变。考虑到球台几何形状的特殊性,在图15情况下球与球台的碰撞会发生异常。图16 碰撞异常状态a图15 碰撞异常状态a若干时间后球o运动到如图16的位置。图18 检测碰撞回退a图19 检测碰撞回退b图17 增加检测矢量方法显然,球o与球台发生了碰撞,但是由于向量a,b,c,d的方向问题,此时无法判断球与球台的碰撞。球将进入球台内部,造成失真。很显然增加方向向量的数量可以很好地解决这个问题,如图17。当方向向量增加到36时,不会出现碰撞检测失误。但却有一个非常明显的缺点增加了系统负担,在每一帧都必须对球体的36个方向进行检测,大大降低运行速度。如果一个网格模型的顶点数目在300左右,那么每增加8个方向检测fps就会减少1。也就是说如果方向向量的数目从36减少至8,那么至少将fps提升4。如果台面上共有10个球,那么将fps在原有基础上提高40。效果惊人!下面介绍另一个方法如图18:这时虽然球已经与桌面相交,但方向向量并没有检测出碰撞若此时球继续沿v方向移动那么会出现下列状况(图19),此时向量a检测出了球体与球台发生碰撞,设球与桌面的交点为p,并设m_fDis是球心到p的距离, R为球半径。如果此时将球沿-a方向移动R-m_fDis,与此同时调用碰撞反应函数,则可避免球与球台的粘连。球与球台的碰撞反应涉及到向量的反射问题,基本方法如图20:图20 碰撞后方向求解图AB为反射平面,N为平面AB的法线,向量o为平行四边形的对角线。已知a为入射线,且法线方向已知则一定可以求出a在N上的投影an 。根据图示可知:a+ an =1/2 * o = o=2*( a+ an ),因为 a, = o-a 所以 a, =a+2* an(考虑到复杂性问题,目前这个台球使用的还是后滞碰撞算法,只是在第N帧时才作出判断,因此,球球碰撞时还会有嵌入的现象。)3.Direct3D在Pools Up中的应用在开发三维游戏的过程中,一般来说有这几个要解决的问题:创建设备使用Mesh模型初始化顶点定义矩阵并利用矩阵进行变换加入光源使用纹理加入摄像机(进入游戏控制)。 只有创建D3D设备的步骤是不可以倒置的,其他的步骤都要在设备建立好后才可以进行。当然,进入游戏控制(游戏循环GameLoop)后,可能还经常要反复进行上面的操作,如改变摄像机等。不同的程序有不同的结构,但是上面的技术都会用到。这个程序的结构与Windows平台其他程序差不多,只是多了一个Gameloop()循环图12。收到退出消息之前,它会一直在While(TRUE)这个语句中loop下去。主函数即WinMain()函数中的执行顺序如下: 创建一个窗口 初始化 Direct3D 处理系统消息 绘制与显示场景 关闭与清除D3D设备的初始化代码如下:BOOL CGame:InitializeD3D(HWND hwnd,UINT nWidth,UINT nHeight) m_pD3D=Direct3DCreate8(D3D_SDK_VERSION);/创建全局设备m_pD3D-GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm )/设置显示适配器d3ddm.Format=CheckDisplayMode(nWidth,nHeight,32);/设置显示模式并调用InitializeLights()创建灯光:通过给D3DLIGHT8赋值,并执行m_pD3DDevice-SetLight(0,&d3dLight)就设置各种光线效果。最后两句m_pD3DDevice-LightEnable(0,TRUE) m_pD3DDevice-SetRenderState(D3DRS_LIGHTING,TRUE)/ 并改变D3D的状态,使灯光生效在函数GameLoop中,每次渲染之前先根据变量的值来确定物体的显示状态。Pools Up的核心就在GameLoop中间:while(msg.message!=WM_QUIT & !m_bQuit)循环能保证只要没有退出请求,就一直执行TranslateMessage(&msg);DispatchMessage(&msg); 响应消息。如果检测消息队列为空时,就对改变后的场景进行渲染。渲染时,先确定是否有Mouse和Keyboard的外部输入,更改标识后执行Render()函数来渲染。在Render()函数当中,先判断球是否全部静止,如果还有运动着的,就控制玩家不能再次击球,这是通过变量beSend控制的。利用DirectInput处理完Mouse和Keyboard后,在m_pD3DDevice-BeginScene();m_pD3DDevice-EndScene();两个函数之间的代码:Setup3DCamera();/设置摄像机Render3D();/3D场景RenderText();/文字输出输出游戏中的每一帧信息。渲染函数Render3D()中,第一步确定输出视角,第二步将Mesh输出逐一输出,第三步加入光效,第四步确定输出视角,经过四步后即完成每帧渲染。 确定输出视角,即设置在三维空间里物体的显示画面。实际上就是我们前面已经介绍过的坐标变换函数的应用。原理如下:D3DXMATRIX matWorld;D3DXMatrixTranslation(&matWorld,0,0,0);m_pD3DDevice-SetTransform(D3DTS_WORLD,&matWorld);坐标变换的函数如下:D3DXMatrixRotationX(&matWorldRotationX,D3DX_PI/-2.0);/把House绕X转-90度D3DXMatrixRotationY(&matWorldRotationY,D3DX_PI/-2.0);/再绕Y转-90度D3DXMatrixTranslation(&matWorld,30.0f,0.0f,-40.0f);/进行X30,Y-40单位的平移D3DXMatrixMultiply(&matWorld,&matWorld,&matWorldRotationX);D3DXMatrixMultiply(&matWorld,&matWorld,&matWorldRotationY);/最后两条语句将上述变换相乘,最终得到视角变换的效果。即按照游戏的要求把想观察到的物理显示到计算机屏幕上。 程序中使用到的Mesh标识了很多点在三维空间信息的Vector序列信息,它们构成一个个基本的三角形,渲染时是对每个三角形逐一渲染的,程序执行到这里仅仅先把顶点序列准备好。对于外部调入的模型,像程序中拿到到的房屋模型housewithmesh.x和table.x文件,需要调入到顶点缓冲当中。在渲染Mesh的时候需要定义一个结构变量,(它们都是D3D有函数支持的)LPD3DXMESH pMeshTable;下面的函数即把一个mesh装载到LPD3DXMESHBUFFER变量当中。D3DXLoadMeshFromX(pFilename,D3DXMESH_MANAGED,m_pD3DDevice,NULL,&pMaterialsBuffer,&m_dwNumMaterials,&pMeshTable)同时返回的还有这个Mesh中triangle的数量多少,m_dwNumMaterials将会在上面的pTable-Render()函数中用到。pMeshTable-CloneMeshFVF(D3DXMESH_MANAGED,MESH_D3DFVF_CUSTOMVERTEX,m_pD3DDevice,&m_pMeshTable);这个函数将Mesh Buffer中的点信息拷贝到成员变量pMeshTable当中。 加入灯光。Direct3D提供了三种光源:点光源POINT(例如灯泡)、平行光源DIRECTIONAL(例如太阳光)和聚光灯SPOT。一个光源可以由一个D3DLIGHT9结构表示,这个结构的参数有:Type:表明光源种类。可以是D3DLIGHT_POINT、D3DLIGHT_SPOT或 D3DLIGHT_DIRECTIONAL。Diffuse / Specular / Ambient:光源射出的三种光的颜色,每一个都是一个D3DCOLORVALUE结构,有a/r/g/b四个成员,取值范围都是0.0f到1.0f。Position:光源的位置,对于平行光源此值无意义。Direction:光源照射的方向,对于点光源此值无意义。Range:光源能照射多远,最大允许值为sqrt(FLT_MAX),对于平行光源此值无意义,Attenuation0 / Attenuation1 / Attenuation2:指定光线的衰减方式。一般来说Attenuation0与Attenuation2都设为0,Attenuation1设为一个常数。如果你将Attenuation0设为1并将其余两个值设为0,光线将不随距离而衰减。对于平行光源此值无意义。接下来的三个参数是聚光灯所特有的。其中聚光灯的内圈的亮度不随距离而衰减,内圈与外圈之间则不然。下面三个参数就与这些有关:Theta:内圈的角度(单位为弧度)。Phi:外圈的角度(单位为弧度)。Falloff:内圈与外圈之间的亮度的衰减率,一般设为1.0f。填充完D3DLIGHT9结构后,执行:pDev-SetLight(0, &d3dLight); /设置为0号灯pDev-LightEnable(0, TRUE); /打开0号灯后就在渲染状态里打开了灯光的设置。 物体的具体位置确定后,根据计算(使用Dx函数)数目逐个进行渲染。for(DWORD i=0;iSetMaterial(&m_pMeshTableMaterialsi); /材质的设置m_pD3DDevice-SetTexture(0,m_pMeshTableTexturesi); /纹理的设置m_pMeshTable-DrawSubset(i); /渲染是第i种材质的三角形 渲染完成后,还要设定观察点ViewPort,即摄像机的位置。它相当于现实世界中我们的眼睛。程序中,如果我们要实现三维效果,则根据已经有的球杆位置确定的观察点来改变摄像机就可以了。代码如下:D3DXMatrixLookAtLH(&matView,&D3DXVECTOR3(),/像机位置 &D3DXVECTOR3(0.0f,0.0f,0.0f), /观察的方向 &D3DXVECTOR3(0.0f,0.0f,1.0f); /像机的正上方最后,所有的场景都准备好后,m_pD3DDevice-Present()就把渲染后的物体就可以显示到屏幕上了。五、DirectInput与DirectSound技术分析1、 DirectInput在Pools Up中的应用DirectInput的绝对优势在于它为鼠标、键盘、操纵杆等各式各样的输入设备提供统一的操纵方式。DirectInput提供一个外设输入状态队列,外设的输入信息会自动保存在其中。当程序在需要响应时把这个状态读出来即可2。在使用时,首先必须创建一个DirectInput8对象,代码如下:LPDIRECTINPUT8 pInput; DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION,IID_IDirectInput8,(void*)&pInput,NULL); 然后,需要创建一个DirectInput设备:LPDIRECTINPUTDEVICE8 pDev;pInput-CreateDevice(GUID_SysKeyboard, &pDev, NULL); 设置好它的数据格式:pDev-SetDataFormat(&c_dfDIKeyboard); 设置它的协作级后获取设备:pDev-Acquire();这样完成初始化后,DirectInput就已经把Windows对键盘的控制权剥夺了,以后的键盘消息将不会被送入消息循环。然后在需要的地方,比如说在刷新游戏时,加入对键盘数据进行读取和处理的语句,语句如下:#define KEYDOWN(key) (bufferkey & 0x80) /定义一个宏,方便处理键盘数据char buffer256; /键盘数据pDev-GetDeviceState(sizeof(buffer),(LPVOID)&buffer); /得到键盘数据if (KEYDOWN(DIK_XXX) /如果XXX键被按下可以看出,用DirectInput在Pools Up中控制视角变化时是相当方便的。2、 DirectAudio在Pools Up中的应用6程序中有需要声音的地方,使用的是DirectAudio接口。首先声明变量如下:IDirectMusicSegment8* m_pSegment;IDirectMusicPerformance8* m_pDirectAudioPerformance;IDirectMusicLoader8* m_pDirectAudioLoader;IGraphBuilder* m_pGraph;IMediaControl* m_pMediaControl;IMediaPosition* m_pMediaPosition;对于Mp3音乐,播放时执行m_pMediaPosition-put_CurrentPosition(0);m_pMediaControl-Run();对于MIDI或WAV音频,需要播放时执行m_pSegment-SetRepeats(dwNumOfRepeats);m_pDirectAudioPerformance-PlaySegmentEx

温馨提示

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

评论

0/150

提交评论