RPG游戏通用开发工具——图形部分的处理.doc_第1页
RPG游戏通用开发工具——图形部分的处理.doc_第2页
RPG游戏通用开发工具——图形部分的处理.doc_第3页
RPG游戏通用开发工具——图形部分的处理.doc_第4页
RPG游戏通用开发工具——图形部分的处理.doc_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

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

文档简介

RPG游戏通用开发工具图形部分的处理1、图块库的结构图块库由图块索引和图块内容两部分构成。因为图块的字节长度是不固定的。图块索引的结构:每个索引的长度为一个 int (4 bytes);图块内容的结构:(1)8 bytes的图块信息头typedef struct short blkwidth; /图块的宽度(以点阵来计算) short blkhigh; /图块的高度(以点阵来计算) short blkorx; /图块在X方向相对于绝对位置的偏移量 short blkory; /图块在Y方向相对于绝对位置的偏移量BlkInfo;(2)长度不固定的图块内容其结构是以行为单位,进行处理的。它的每一行的结构 1 byte n bytes画这一行需要阅读多少字节 不定长度的线段内容它的每个线段内容的结构1 byte 1 byte n bytes相对于上次位置的偏移量 这个线段共需要画多少个字节 这个线段的具体内容 阅读图块的C语言算法void drawblk(char * dest)/*输入参数:dest - 图块将展开成像素格式到这个目的缓冲区内*/ BlkInfo mInfo; /包含了这个图块的图块信息头 UCHAR readnum ; /画这一行应该阅读多少字节 UCHAR drawnum ; /每个线段所用掉的字节数 UCHAR usednum ; /目前画过的线段已经用掉的字节数 char mx ; /当前的线段应该画在的位置(相对于本图块的绝对位置) int offset ;/因为dest是连续的内存,不分宽度和高度的,需要/一个变量来计算画点到dest的偏移量。 LPSTR lpBlk ; /指向本图块的开始位置的指针 short y=mInfo.blkhigh-1;/实际需要画的行数 int bufWidth; /dest接收的宽度(是为了兼容标准位图的标准格式) /在这里可以认为等于 mInfo.blkwidth int i ; for(i=0;imInfo.blkhigh;i+) readnum=*lpBlk; /取得画这一行应该阅读多少字节lpBlk+; /指针指向了第一个线段的偏移量 usednum=0; mx=0; drawnum=0; /局部变量的初始化 while(usednumreadnum) /进行循环直到该画的字节都画完 mx = * lpBlk + mx + drawnum; /取得即将画出的线段的偏移量 lpBlk +; /指针指向了即将画出的线段的 /实际字节数 drawnum= * lpBlk ; /取得即将画出的线段的实际字节数 lpBlk+; /指针指向了即将画出的线段的 /实际内容 offset=y*bufWidth+mx; /计算应该拷贝到dest的那个位置 memcpy(lpDIBits+offset,lpBlk,drawnum); /到dest的内存拷贝 usednum=usednum+drawnum+2; /计算已经画出的线段用了多少 /字节 lpBlk=lpBlk+drawnum; /指向下一个即将画出的线段 y-; /标准位图是从最后一行开始算起的 注意:只是为了说明图块的解码方法。对于转化成标准内存位图,需要宽度边界的判断。对于直接写入屏幕缓冲区,还需要进行是否超过缓冲区边界的判断。2、阅读图块库的类 - CBlkLibApi 的数据和函数成员class CBlkLibApipublic:CBlkLibApi();virtual CBlkLibApi();protected:CPalette* pPal;/char* blkBuffer;HBLK blkHandle;/UINT * idxBuffer;HBDX idxHandle;CList idxList;int blkNumber;CString palFileName;public:BOOLEAN ExportBlk(int index,CFile&file); /把指定编号的图块输出成标准位图格式BOOLEAN LoadBlkLibFile(LPCTSTR lpszBlkName); /装载图块库到内存void CloseBlkLibFile(); /关闭图块库BOOLEAN SaveBlkLibFile(LPCTSTR lpszBlkName); /图块库文件存盘void SetPalFileName(LPCTSTR lpszPalName); /设置图块所用到的调色板文件CPalette * GetBlkPal(); /取得当前图库所用的调色板int GetBlkNumber(); /取得当前图库中图块的数量BOOLEAN BlkiToIcon(CDC * dcWnd,int wDest,int hDest, CBitmap& mBitmap,int index); /把指定编号的图块输出成指定大小的标准位图(缩放)HANDLE BlkiToBitmap(LPBITMAPINFO& mbInfo,int index); /把指定编号的图块输出成与原来图块大小相同的标准位图LPBITMAPINFO GetBlkiInfo(BlkInfo& mInfo, int index); /取得指定编号的图块的信息BOOLEAN InsertBlk(int position,CBitmap mBitmap,CBitmap mMask, int blkOrx,int blkOry); /把一个标准的位图加入图块库中,成为一个图块BOOLEAN DeleteBlk(int position); /从图块库中删除指定位置的图块protected:LPBITMAPINFO mDibInfo; BOOLEAN ReadBlkLibFile(LPCTSTR lpszBlkName);BOOLEAN ReadBlkIdxFile(LPCTSTR lpszIdxName);BOOLEAN ReadBlkPalFile();void GetBlkIdxFileName(LPCTSTR lpszBlkName,CString& idxName);void InitDibInfo();需要改进的地方:原来是由这个类自己管理一个调色板文件。在使用DirectX后,需要改成兼容的调色板结构。增加两个图块库之间的大量图块的直接拷贝。提供把图块直接画在由指针指定的内存中的功能。就象直接画在屏幕上一样。实际上传递给它的指针,很有可能就是屏幕的背后缓存的指针。3、地图数组文件的结构(内部)地图数组文件由场景索引和场景地图两个部分组成。场景地图的长度可以是固定的,也可以是不固定的。场景索引结构:每个场景索引的长度为一个 int (4 bytes);场景地图结构:地图分成几个层来画,一是为人物的移动提供了判断依据,二是为使某些物体具有透明的属性,同时也造成了三维空间的假象:即下面的层会被 上面的层遮盖。(1)地面:将把这一层的数组全部填满。因为地面是一直铺满整个地图的。包括草 地,土地,水,但是不包括任何阻挡人物行走的石头和草。(2)建筑?包括房屋,花草树木,桌椅板凳任何带有高度的物体。在这一层中,有 物体的地方,将填写相关物体的图块索引号,没有物体的地方将用 0字节来填写。 最终所有的人物,在计算了移动位置以后,也将并入这一层。根据人物将移动的方 向的字节是否为零,来判断人物移动的可能性。如果增加某些有生气的动物,也将并入这一层(同样是计算了位置改变以后)。(3)摆设 包括桌子上摆的东西,墙上挂的装饰品。仅仅是为了画面的华丽程度。加入这一层的原因,是因为摆设物品的位置和所依附的物体的坐标往往是相同的。也许 只是为了减少一些图块?但是增加了两个很大的矩阵!(4)建筑图块的偏移量因为所有的图块,并不是很规则的,为了在画面上使它们紧凑地排列在一起,而加入了这个数组。(5)摆设物品的偏移量作用同建筑图块的偏移(6)动画和事件触发标志定义了在地图上需要进行动画和什么地方将有事件发生的数组。在地图里,它们的标志是相同的。有这种标志的地方,填写了事件的索引号,没有的地方,用-1来填写(因为事件的索引号有可能是0)。因为地图是随着人物 的走动和时钟的进行,不断改变的(范围和某些动画),这些标志将作为动画处理和事 件发生的判断依据。无论如何,事件的发生是和地图想关联的,它们都有自己固定的位置。不断打算盘的客栈老板,和飘扬的旗帜,流动的水,都将来源于这些标志。改进建议数组的大量填零,造成空间的很大浪费。对于物体的显示,可以采用绝对位置加索引号来表示,显示倒不成问题,但是对于人物移动可能性的判断,就变得很 困难。是否可以采用某种链表结来进行判断,总的说来,是要用时间来换取空间,还是用空间来换取时间。如果在链表结构上处理得非常杰出,时间损失很小 ,是最好不过的了!物体的偏移量的信息是否可以包含在图块本身的数据结构里?似乎影响不是很大。 经过仔细观察,带有偏移量的原因有两个:一是对于规则大小的图块,需要 摆在图块的中央,显得好看。二是一些不规则的家具,一件家具往往是由几个图 块拼凑起来的。如果没有适当的偏移,会出现裂缝。但是为什么是拼凑起来的?因为一个家具可能会在不同方位出现不同的人物。比如坐在桌子旁边的令狐冲的形象,是和桌子的那一角画在一起的。反正,认为能够很自由地在桌子前面站起来,坐 下,于是很大的难题。原来游戏采取屏幕变黑来处理,偷懒了!动画和事件的触发?能不能分开来写?这些标志是和判断人物行走无关的,也许优化的可能性是最大的,算法相对简单一点。地图显示和运行的基本算法这部分的程序应该是比较关键的。程序的大部分时间都将在地图的显示,移动,和变 化状态中。原来我的程序结构是把事件的处理加入了地图显示的循环,就是坏惺录赝急旧淼难方岵佟欠裼貌扇拖姆?/FONT式,还值得仔细 探讨。unsigned short * allsinbuf; /指向所有数组的指针-这些数组连续放在一起unsigned short * groundbuf; /指向地面数组的指针unsigned short * buildbuf; /指向建筑数组的指针unsigned short * toolsbuf; /指向摆身数组的指针unsigned short * actorbuf; /指向动画和事件标志的指针unsigned short * buildoff; /指向建筑物体偏移的指针unsigned short * toolsoff; /指向摆设物体偏移的指针sinkey * skeybuf; /指向动画和事件解释文件的指针/提供给外部以下三个函数int SceenInInit(unsigned idx) /指定场景的初始化/*输入参数 idx - 场景的编号*/ 打开并读入需要的图块文件; 打开并读入需要的图块索引文?/FONT 打开并读入指定场景号码的地图数组文件; 打开并读入指定场景号的动画和事件解释文件?/格式随后介绍int SceenInRun(unsigned idx) /指定场景的运行/*输入参数 idx - 场景的编号*/ int mx,my; /以自己扮演的角色为标准的人物位置 int m; /角色需要显示的当前桢(包括了面对的方向) int outFlag=SceenLoop; /程序循环和退出场景的标志 short allDef; i=0; j=0; /场景在屏幕左上角的那个图块在地图数组 /中的位置。 m=需要显示的当前桢; /一般为零。 mx=人物初始位置; my=人物初始位置; /根据场景的不同而不同 SceenInDraw(0,0,mx,my,m); /根据初始人物位置和场景位置画出场景 while(!outFlag) /循环直到接到退出指令 GetEvent(&eventMsg); /获取用户的输入,转化成标准消息结构 outFlag=DispatchEvent(&eventMsg,&i,&j,&mx,&my,&m);/处理消息事件 SceenInDraw(i,j,mx,my,m); /重新刷新屏幕 ClearEvent(&eventMsg); /清除消息队列 return 1;void SceenInClose(void) /关闭指定场景 clearv( ); /清除屏幕 closesinall( ); /关闭所有文件,释放所有内存/以下函数是上面三个函数需要调用的不公开函int SceenInDraw(unsigned int x,unsigned y,unsigned mx, unsigned my,uchar picnum)/根据角色的位置和时钟重新刷新屏幕/*输入参数x,y,- 场景在屏幕左上角的那个图块在地图数组中的位置mx,my - 人物的当前位置picnum - 人物需要显示的当前桢 int i; clearvb( ); /清除屏幕背后缓存区 dispground(x,y); /画地面 dispmainact(mx,my); /把主角合并到建筑那一层 dispactor(x,y,picnum); /把其他角色合并到建筑那一层 dispbuild(x,y); /显示建筑层 disptools(x,y); /显示摆设层 /*calc if outFlag=1*/ /计算是否走到了出口 VideoReflash( ); /把背后缓存传送到屏幕 return 0;int DispatchEvent(&eventMsg,&i,&j,&mx,&my,&m)/处理消息队列,来计算位置的变化if(eventMsg.type&键盘事件) /处理键盘事件 switch(eventMsg.key) case 方向键: /处理人物的移动 if(moveable(mx,my,0)?/如果可以移动(没有障碍) 计算位置; 计算方向 ; 计算当前显示桢; break; case 激活菜单: /处理用户呼叫菜单 MenuInit( ); if(MenuRun( ) outFlag=SceenQuit; break; case 决定: if(allDef=eventhappend(mx,my,MActorDir)!=-1) SceenDefRun(allDef); /如果存在事件,则执行它 break; default: break; if(eventMsg.type&时钟刷新) m+; if(m=12) /计算动画的显示 m=0;存在的问题 对于多个物体时间有差别的动画问题。是不是把时钟的控制单位定小一点?给每物体单独分配一个控制时间的变量?搜索链表? 对于时间是否包含在场景循环内,还是以发送消息的方式,交给其他的函数来处理原来的方式,是对应每个场景,都有一个单独的图块库。如果采取所有场景共用一个图块库,应该如何在初始化的时候,加载当前场景所需要的图块?如果是另外记载需要的图块,装入内存以后,是否要重新建立索引?设想,共有的图块库为 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,.当前场景需要的图块为 1, 5, 13, 18,. 在加载的时候,重新建立一个对应于当前内存中图块库的索引,在一边挑选图块的时候,这个索引就一边建立起来了。在图形部分需要做的工作: 尽快指定合理的解决方案,解决上面的问题。 一个可以重用的 CBlkApi 类。 一个图块编辑器。 一个地图编辑器。 场景运行程序的基本构架。 一个可重用的 CSceenMaps 类。“盗亦有道”-如何从别人的游戏学习经验选定一个游戏,来对他的文件组织结构进行比较深入的分析,无疑是得到这一类型的游戏制作经验的捷径。据说有名的赤壁就是前导公司仔细剖析了魔兽争霸做出来的!以下结合对智冠出品的“金庸群侠传”的剖析,介绍一下我是怎么样从别人的游戏里学习经验的。也许是因为智冠许诺给河洛制作组的工作是时间太短的原因,我从来没有见到过文件格式如此透明的游戏了。能够遇到这样一个游戏,并从中学到很多有关 RPG游戏的编程经验,也为剖析其他游戏积累经验,当属于三生有幸。但是剖析游戏切忌陷入“牛角尖”的误区,时刻牢记我们剖析游戏的目的和初衷:我们仅仅是为了从中学习一些经验,并不是真的要把这个游戏的每一比特的含义都搞懂。而且深入剖析一个游戏以后,等于已经掌握了它记录图象信息存储的文件格式,对于那些暂时找不到美工,又急于制作引擎的业余游戏编程爱好者说,也暂时提供了用来实验的图象素材,而且比用屏幕捕捉程序截取的图片完整得多。剖析“金庸群侠传”的步骤:1、确定每个文件的用途:a、查看游戏文件目录,根据自己的找出自己熟悉的文件。比如,一看到SETSOUN-D.EXE马上就明白了:是声卡的设置程序嘛!凡是在 DOS4GW下做的游戏,大多数有这个文件。同时也就确定了*.MDI,*.DIG是声卡的MIDI和声音的驱动程序,*.XMI是游戏的MIDI音乐,*.WAV是程序的音效。还有一些是根据自己的编程经验一眼就能看出来的:768个字节的那个文件,肯定是记录的系统 256色调色板的!这样就可以排除掉很多文件,剩下的就是游戏开发小组自己定义的文件格式了。b、有一些文件的文件名起得非常好:好到一眼就可以确定他是干什么的程度。比如,ALLSIN.GRP 和 ALLSIN.IDX,就是 ALL SCENERY IN 嘛!所有的内部场景。IDX 嘛,当然就是索引了!HDGRP.GRP和HDGRP.IDX,当然是人物的头像了!至于是否想法正确,可以用下几步的方法来验证。c、利用改变文件名的方法,来确定一些文件的作用:把等待验证用途的文件改成其他名字,而人为地给引擎制造一些错误。对于一个好的游戏引擎,应该有比较好的容错性和稳固性,或者会给出XXXX文件找不到的信息。这种方法对那些在游戏初始化已经完成,后期才加载的文件尤其灵验。但是用这种方法有时可能会死机( 为了祖国的游戏事业,RESET几次有啥子大不了的嘛)。那么我们就坐下来大骂这个游戏的引擎做得太差劲了好了。比如,我们在游戏目录下看到如下的文件:BUILDING.002 BUILDX.002 BUIL-DY.002 EARTH.002 SURFACE.002,我们根据名字猜测它们是和大地图地图有关的文件,那么我们就把EARTH.002 改名成 EARTH.003,然后运行游戏,看看会发生什么错误。谢天谢地!没有死机。但是走出去一看,大地图上所有的地面(不包括道路,植物和建筑都变成单一的蓝色了,这就说明EARTH.002 这个文件,记录的是大地图上地面的图块的排列。d、利用同类文件交换文件名来确定文件的用途:在这个游戏里,有SMP0?和SDX0-? 这样的文件,文件名比较简单,很难确定它到底是保存的图块,还是场景中图块的排列顺序。但是正好这种同类的文件很多,这个时候可以采取这种办法。把SMP001,SD-X001的文件名与SMP000,SDX000 对调一下(具体过程不用说了吧)。然后运行游戏,咦?没有变化?一个不小心,走进了“河洛客栈”,噎?“河洛客栈”什么时候重新装修过了?布局没有改变,只是构成场景的图块改变了,这就说明这几个文件,记录的是图块本身的信

温馨提示

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

评论

0/150

提交评论