WAP之家:为您提供最全最新的WAP技术,CP.SP.3G等行业资讯。 WAP之家交流论坛全新开放 点击进入>>
WAP资讯 | 3G动态 | SP动态 | 运营商动态 | 内容商动态 | 制造商动态 | 论坛讨论>> 每次自动访问
WAP技术 | WAP源码 | 手机编程 | 手机源码 | 无线技术 | J2ME技术 | 手机软件 添加到收藏夹
IVR技术 | SP资料 | SMS MMS技术 | 商业方案 | IVR下载 | 书籍教程 | 工具软件 语言:繁體中文

WAP之家技术文章J2ME技术进阶教程优化你的手机游戏:使用脏矩形技术

优化你的手机游戏:使用脏矩形技术
作者:佚名  来源:本站整理  发布时间:2008-2-11 11:06:07
ool IsDirty( ) = 0;//是否有脏矩形
virtual bool GetBoundsRect(RECT*pRect) =0;//得到该物体的范围
virtual int GetDirtyRects ( RECT*pRectBuffer ) = 0;//该物体的脏矩形个数,填充到pRectBuffer里面,返回填充了多少个
...其他函数
}; 

    我们还需要一个简单的能管理脏矩形和渲染物体的类
class CRenderObjectManager
{
pulibc:
void RemoveRenderObject( CRenderObject*pObject );//删除一个渲染物体
void AddRenderObject( CRenderObject*pObject );//添加一个渲染物体
void Render( GraphicsDevice*pDevice );//渲染所有的物体
void Update( );//更新所有物体
.....其他函数
protected:
std::list< CRenderObject* > m_RenderObjects;
int m_nCurrentDirtyRectCount;//当前脏矩形数量
struct DirtyRect
{
RECT Range; //脏矩形范围
int AreaSize; //脏矩形大小,用来排序
};
BOOL m_bHoleDirty;//是否全部脏了
DirtyRect m_DirtyRects[128];//屏幕上最多的脏矩形数量,如果大于这个数量则认为屏幕所有范围都脏了
};
void CRenderObjectManager::Update()
{
m_bHoleDirty = false;
m_nCurrentDirtyRectCount = 0;
static RECT DirtyRectBuffer[128];
float TimeStamp = GetElapsedTime();
for(std::list< CRenderObject* >::iterator it = m_RenderObjects.begin();
it != m_RenderObjects.end(); it++)
{
CRenderObject*pObject = *it;
pObject->OnUpdate( TimeStamp );
if(m_bHoleDirty == false && pObject->IsDirty() )
{
int Count = pObject->GetDirtyRects(DirtyRectBuffer);
for( i =0; i<Count;i++)
{
对于该物体的每一个脏矩形DirtyRectBuffer[i]
如果DirtyRectBuffer[i] 没有在任何一个已有的脏矩形范围内
那么把这个脏矩形根据从大到小的顺序添加到脏矩形范围内,否则忽略这个脏矩形
   如果脏矩形数量已经大于设定的最大脏矩形范围,设置所有所有屏幕都脏了的标志,
}
}
}
如果屏幕所有都脏了,填充背景颜色
否则为每一个脏矩形填充背景颜色
}
void CRenderObjectManager::Render( GraphicsDevice* pGraphics)
{
for(std::list< CRenderObject* >::iterator it = m_RenderObjects.begin();
it != m_RenderObjects.end(); it++)
{
CRenderObject*pObject = *it;
if(如果屏幕都脏了的标志已经设定)
{
RECT rcBoundsRect = { 0, 0, 0, 0 };
if( pObject->GetBoundsRect( rcBoundsRect ) )
{
//设置屏幕裁减区域
pGraphics->SetClipper( &rcBoundsRect );
}
pObject->OnRender( pGraphics );
}
else
{

RECT rcBoundsRect = { 0, 0, 0, 0 };
if( pObject->GetBoundsRect( rcBoundsRect ) )
{
//如果该物体的范围与脏矩形缓冲区的任何一个脏矩形有交集的话
for( int i=0; i<m_nCurrentDirtyRectCount; i++ )
{
RECT rcIntersect;
if( ::IntersectRect( &rcIntersect, &m_DirtyRects[i].Range, &rcBoundsRect ) )
{
//只画交集的部分
pGraphics-> SetClipper ( &m_DirtyRects[i].Range );
pObject->OnRender( pGraphics );
}
}
}
}



    好了,核心代码的伪代码就在这里,不知道大家看明白没有,当然我在这里上面实现的这种方法有一个缺陷,最坏情况下一个也许会导致重新画很多次,如图的情况:




    假设A是渲染物体,B,C,D,E是由大到小的脏矩形范围,那么很显然,重叠的部分就被反复画。。。这是在分割脏矩形导致的问题,这样画下来,如果A物体是采用了叠加混合到背景的算法的话,问题就出来了,重画的部分会变得非常亮。所以脏矩形的分割就显得非常重要,也就是说把这些脏矩形还要分割为互相独立的互不相交的矩形,至于分割算法嘛,嘿嘿,各位还是动一下脑筋思考思考吧:)这个也是最值得优化的地方了,哈哈。实在想不出的话,最简单的方法就是把彼此相交的脏矩形都做一个合并,得到更大的脏矩形,虽然没有相交的区域了,但是也许这个脏矩形会变得比较大了哦:)
最后,大家一定关心的是我会不会提供源代码,很抱歉的说,不能。我在我的引擎中实现的不是以简单的链表去做的,用的是一棵比较复杂的渲染树,牵扯到的东西就比较多了,所以不方便提供代码,不过可以给一个演示吧:)再说大家如果真的明白了我所说的,那就可以自己动手写一下嘛,不要怕失败/。

    好啦,关于脏矩形的技术就介绍到这里啦,用好这个技术你会发现你的游戏会在配置极低的机器上也能运行如飞的:)这种技术如果能用在现在市面上的那么多的游戏中的话,就不必为一个小游戏就强占了您100%的CPU资源而烦恼拉:)
如果您有更好的方法或者指出其中的不完善的地方还请您不吝赐教,大家多多交流:)

关于测试的Demo 
    该Demo渲染部分由Kylinx花了近半年的时间,全部采用MMX写成,已经成功实现d3d中对2d纹理的操作,速度非常快

关于Settings.ini
EnableDirtyRect = 1 //是否允许脏矩形技术,0=关闭,1=开启
LockFPS = 1 //是否锁定FPS,0=关闭,1=开启
哈,这个Demo在不锁定FPS,脏技术开启的的情况下,我的Duron1.8G CPU,FPS达到 31500左右!(没错,是三万一千五百)这个数字吓人吧?如果脏技术未打开,只能在150左右,相差200倍阿!!!

如果LockFPS开启,在我机器上(512M DDR)跑30个DEMO,CPU占用还是为0,哈哈! 

    关于该引擎:演示用的这个引擎(代号ShinyFairy:闪灵,基于前期开发的GFX3.0系列,该系列已经成功运行在某商业游戏公司的休闲游戏系列),采用Kylinx历时2年多开发的具有自主知识产权的基于2D游戏的超级引擎,强大的数据加密,打包,图形接口同时提供d3d8版本和mmx版本,该演示使用的是mmx版本,适用于各种休闲游戏平台,或者大型2D RPG/MMORPG均可适用。

    例子下载:http://dev.gameres.com/Program/Visual/2D/DirtyRectDemo.rar

上一页  [1] [2] 

[] [返回上一页] [打 印]
文章评论

用户名: 查看更多评论

分 值:100分 85分 70分 55分 40分 25分 10分 0分

内 容:

         (注“”为必填内容。) 验证码: 验证码,看不清楚?请点击刷新验证码