王朝网络
分享
 
 
 

对2D游戏引擎设计的一些思考

王朝other·作者佚名  2008-05-19
宽屏版  字体: |||超大  

前不久用模拟器玩了SFC上的一个经典SLG――圣龙战记后,突然对它出色的表现有了浓厚的兴趣,尤其是在那种硬件平台下,仅仅3M的游戏竟然能够有如此出色的表现!不仅是画面表现得极致, 而且整个游戏的系统,情节相对当今的大多数游戏来说,实在是有过之而无不及!~实在是佩服万分~!

确实,现在的硬件条件都比以前好多了,做一个游戏也越来越简单了(虽然我没有在DOS下写过程序,但是经过两年多的编程,对各个方面都有些了解,仍能体会到在DOS下写游戏的痛苦), 现在各种各样的游戏开发包也越来越多了不说别的,就直接用DirectX SDK吧,做一个小的游戏比如飞机类也不会花几天时间(以前我花了3天做过一个^_^),开发 简单了,自然有些东西就不那么讲究了比如说现在的商业游戏的容量,无论是什么都先比光盘多少,你的3CD,我来5CD,除去里面\"免费赠送\"的一些\"原声大蝶\" 阿,\"官方资料\"阿之类的东西,一个游戏至少也有1个G,(大概是现在的硬盘在大家的眼中不怎么值钱了吧,可能商家是这么认为的,也可能是大众心理:东西越多越好 嘛),真正有用的数据有多少?估计也只有商家才清楚~先不说某些游戏连压缩都没压缩过就裸用一大堆的24Bit BMP( 没错,就是标准的位图)来做游戏中的资源(仅仅做了一个未压缩的资源包,很轻松就能提取出全部资源),画面看起来 效果好么?确实,不过那没有什么,反正就是美工的表现嘛!还对机器要求至少有PIII 500,128M以上的RAM~真是Faint!

也许大多数人不在乎上面提到的东西~可是作为一个游戏开发者,一个游戏程序设计者,就要在能力范围内对游戏 程序做尽可能的优化(先不提商业制作的一些\"无奈\"的原因的阻碍),就比如说星际,大概是我所见到的PC上的商业游戏中做的最好的一个了好了,废话了一大堆,下面来谈谈点正式的.如今2D PC游戏上,最流行的就是16位色的显示方式(主要是从速度和内存消耗以及显示质量这些方面上来综合),16位色 上基本上是565的显示方式(我到现在还从来没有见到一台555显示的机器或一块555的显卡),所以我只讨论16bit下565 模式

下面的方法是由于\'调色板\'而来的灵感~(先申明,这种方法绝对不适合主流技术,基于上面我所说的游戏----圣龙战记,可以做类似的游戏~不适合基于象素的游戏,对TILE类游戏比较实用)

由于TILE类游戏用到的TILE颜色相对都比较固定,颜色种类比较少,所以我们可以选取一个固定的调色板,里面能容纳大 部分的TILE颜色,这样所有TILE的数据都可以用这个调色板的索引来表示,当然为了方便,256种颜色最好不过,这样每个 点只占8位(也许有人会说,这样不就干脆创建一个8位色的游戏不就行了?嘿嘿,稍安勿躁,马上解释),在内存消耗上就有 了很大的优势~如果再压缩一下

从速度上来说,由于游戏里面需要大量的特效,比如最常用的半透明效果,色彩饱和效果,阴影效果,灰度化等等效果.所 以从这方面来考虑

由于只用到了256色,混合后的颜色也在256种颜色内,所以考虑用查表方式.这256种颜色从16Bit 565模式共65536种颜色的色彩空间中提取出来这样就算是32级的Alpha混合也就只占用256*256*32*8bit=2M的内存但是用16级或者12级我就觉得够了,这样就有256*256*16*8Bit=1M或者256*256*12*8Bit=768K色彩饱和表就只需要256*256*8Bit=64K

阴影表也就只要256*256*8Bit=64K灰度表只要256*8Bit=0.256K一共加起来也就1M左右,呵呵够少吧!

如下:

static unsigned char BDI_AlphaBlendTable[16][256][256];//16级Alpha混和表

static unsigned char BDI_AdditiveTable[256][256];//Additive表

static unsigned char BDI_SubTable[256][256];//阴影表

static unsigned char BDI_GrayTable[256];//灰度表

那么,哪256种颜色可以很好的描述大部分图片的颜色呢?尝试过几个不同的调色板后,最后发现下面这个调色板效果最好(并且还有附加的优势!稍后看到)

如下,unsigned short wPal[256];

for(int i=0;i

{

wPal[i]=i|(i

}

也就是说这个调色板的高8位和低8位是相同的,嘿嘿,想到什么了?(赶快用10秒钟猜猜,下面回答)

当然这样一来也就不能直接用DirectDraw里面的Blt之类的东西啦~,另外,由于我们的数据保留的是调色板的索引所以,不能直接Blt到BackSurface上,自己分配一个缓冲区,大小和BackSurface一样大,不过用byte类型就够啦~自己写几个Blt吧:

比如一个Alpha混合的操作:(代码取自我给出的Demo)

void GBDI:rawToScreenAdditiveSrcColorKey(unsigned char*pBufDest,int nDestWidth,unsigned char*pBufSour,int nLine,int nRow)

{

unsigned char*pDestAddr=pBufDest;

unsigned char*pSourAddr=pBufSour;

for(register int i=0;i

{

for(register int j=0;j

{

if(*pSourAddr != m_byColorKeyIndex)

{

*pDestAddr=GBDI::BDI_AdditiveTable[*pSourAddr][*pDestAddr];//这个地方极大的节省了大量的数学运算

}

pDestAddr++;

pSourAddr++;

}

pBufDest+=nDestWidth;

pBufSour+=m_nWidth;

pDestAddr=pBufDest;

pSourAddr=pBufSour;

}

}

上面的操作是经过裁减过后的显示,裁减代码如下

RECT rtDest={m_position.x,m_position.y,m_position.x+pScreen-GetWidth(),m_position.y+pScreen-GetHeight()};

RECT rtSour=m_rtShowArea;

if(rtDest.top

{

rtSour.top-=rtDest.top;

rtDest.top=0;

}

if(rtDest.left

{

rtSour.left-=rtDest.left;

rtDest.left=0;

}

if(rtDest.left+rtSour.right-rtSour.leftpScreen-GetWidth())

{

rtSour.right=rtSour.left+pScreen-GetWidth()-rtDest.left;

}

if(rtDest.top+rtSour.bottom-rtSour.toppScreen-GetHeight())

{

rtSour.bottom=rtSour.top+pScreen-GetHeight()-rtDest.top;

}

unsigned char*pBufDest=pScreen-GetBuffer()+pScreen-GetWidth()*rtDest.top+rtDest.left;//目标地址

unsigned char*pBufSour=m_pData+m_nWidth*rtSour.top+rtSour.left;//源地址

int nLine=rtSour.right-rtSour.left;

int nRow=rtSour.bottom-rtSour.top;

各种参数的含义都比较明显,了解E文的并且写过代码的应该都能看懂,看不懂的如果有兴趣的话,自己去看完整源代码好了,如何才能在屏幕上正确的显示呢?这个问题就很简单了,当然最最直接的方法就是

for(缓冲区上的每一个点)

BackSurface上的每一个点=缓冲区上的每一个点所代表的调色板的值

嘿嘿,别忘记了,上面说过用到的调色板是什么来的?低8位和高8位相同!如果了解mmx的话,就应该知道这一条指令unpcklbw哈哈!如何?知道优化的方法了吧?下面是我的Demo中的代码

DDSURFACEDESC2 ddsd;

ZeroMemory(&ddsd,sizeof(ddsd));

ddsd.dwSize=sizeof(ddsd);

hr=m_pDSBack-Lock(NULL,&ddsd,DDLOCK_WAIT,NULL);

while(DD_OK!=hr)

{

if(DDERR_SURFACELOST==hr)

RestoreSurface();

else

return;

hr=m_pDSBack-Lock(NULL,&ddsd,DDLOCK_WAIT,NULL);

}

unsigned char*pSourBuf=(unsigned char*)m_pBuffer;

if(m_bDefaultPal)//如果是采用了默认的调色板(高8位==低8位)

{

//由于初学mmx,还不会作mmx指令的优化~代码见笑了~

unsigned long dwResPitch=ddsd.lPitch-(m_nWidth

unsigned char*pBuf=(unsigned char*)ddsd.lpSurface;

unsigned long dwHeight=m_nHeight;

unsigned long loopTime=m_nWidth5; //一次处理32个索引点

{

_asm

{

mov esi,pSourBuf;

mov edi,pBuf;

mov edx,dwHeight;

rowLoop:

cmp edx,0;

je end;

mov ecx,loopTime;

mmxdraw:

movq mm0,[esi]; //8个索引点

movq mm2,[esi+8]; //后8个索引点

movq mm4,[esi+16];

movq mm6,[esi+24];

movq mm1,mm0;

movq mm3,mm2;

movq mm5,mm4;

movq mm7,mm6;

punpcklbw mm0,mm0; //0-3个索引的值

punpckhbw mm1,mm1; //4-7

punpcklbw mm2,mm2; //8-11

punpckhbw mm3,mm3; //12-15

punpcklbw mm4,mm4;

punpckhbw mm5,mm5;

punpcklbw mm6,mm6;

punpckhbw mm7,mm7;

movq [edi],mm0;

movq [edi+8],mm1;

movq [edi+16],mm2;

movq [edi+24],mm3;

movq [edi+32],mm4;

movq [edi+40],mm5;

movq [edi+48],mm6;

movq [edi+56],mm7;

add esi,32;

add edi,64;

loop mmxdraw;

dec edx;

add edi,dwResPitch;

jmp rowLoop;

end:

emms;

}

}

}

else

{

unsigned long dwResPitch=(ddsd.lPitch1)-m_nWidth;

unsigned short*pBuf=(unsigned short*)ddsd.lpSurface;

for(register int i=0;i

{

for(register int j=0;j

{

*pBuf=m_pPal[*pSourBuf];

pBuf++;

pSourBuf++;

}

pBuf+=dwResPitch;

}

}

m_pDSBack-Unlock(NULL);

嘿嘿

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有