2012-4-12 读书笔记

前2天都忘记写日记了,主要是在看cocos2d 理了下来龙去脉什么的。不知道我的理解是否正确,暂时拿不出手,呵呵。

接下来做点摘抄 以下内容来自

Learn iPhone and iPad cocos2d Game Development

第六章 深入了解精灵

纹理贴图集是一张包含很多图片的纹理贴图(图片),通常用于存放单个角色 动画的所有动画帧。不过它的作用不止于此。实际上你可以把任何图片放进同 一张纹理贴图中。我们的目的是把尽可能多的图片放进同一张纹理贴图中,以 达到节省空间的目的。很多cocos2d开发者使用Zwoptex这个软件来创建纹理贴 图集。我会在本章介绍Zwoptex这个工具。

精灵批处理”(Sprite Batching)是用于提高精灵渲染速度的技术。它可以提高渲染大量相同精灵的速度,不过它同纹理贴图集配合使用的效率最高。如 果你将纹理贴图集与精灵批处理配合使用的话,你只要调用一次渲染方法就可 以完成纹理贴图集里所有图片的渲染。

“渲染方法调用”(draw call)是把必要的信息传递给图形处理硬件以完成整个或者部份图片渲染的过程。当你使用CCSprite的时候,每生成一个CCSprite 节点都会调用一次渲染方法。每一次渲染方法调用导致的系统开销叠加起来会 使游戏的帧率大约降低15%或者更多(除非你使用CCSpriteBatchNode,它的 作用是作为一个额外的层用于添加多个精灵节点。前提是这些精灵节点使用的 是同一个纹理贴图)。

CCSpriteBatchNode

每次系统在屏幕上渲染一张贴图时,图形处理硬件必须首先准备渲染,然后渲
染图形,最后在完成渲染以后进行清理。上述过程是每一次在启动渲染和结束
渲染之间存在的固定系统开销。如果图形处理硬件知道你需要使用同一张纹理
贴图渲染一组精灵的话,图形处理硬件将只需要为这一组精灵执行一次准备,
渲染,最后清理的过程了。

图6-1展示了这种批量渲染。你可以看到屏幕上有几百个相同的子弹。如果你逐 个渲染它们的话,你的游戏帧率将会下降至少15%。如果你使用CCSpriteBatchNode,你就可以避免帧率的下降。

图6-1.把使用同一张纹理贴图的一组CCSprite节点添加到同一个CCSpriteBatchNode里,比逐 个渲染CCSprite要高效很多。

以下是生成CCSprite的常用代码:

CCSprite* sprite = [CCSprite spriteWithFile:@”bullet.png”]; [self addChild:sprite];

当然,向CCSpriteBatchNode添加一个CCSprite节点不会有任何效率上的提高, 所以如列表6-1代码所示,我把许多使用同一张纹理贴图的精灵节点添加到了同 一个CCSpriteBatchNode里:

列表6-1.创建多个CCSprite节点,将它们添加到同一个CCSpriteBatchNode中以提高渲染速度

CCSpriteBatchNode* batch = [CCSpriteBatchNode batchNodeWithFile:@"bullet.png"]; [self addChild:batch];

for (int i = 0; i < 100; i++)

{ }

CCSprite* sprite = [CCSprite spriteWithFile:@”bullet.png”]; [batch addChild:bullet];

CCSpriteBatchNode的作用很像CCLayer,因为它本身并不显示在屏幕上。不过 你只能把CCSprite加入CCSpriteBatchNode。在列表6-1中,CCSpriteBatchNode 将一个图片文件名作为参数,使用这个参数的原因是所有被添加进 CCSpriteBatchNode的CCSprite节点都必须使用同一个图片文件。如果你没有在

CCSprite中使用相同的图片,你将会在调试窗口中得到以下报错信息:

SpriteBatches[13879:207] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'CCSprite is not using the same texture id'

(注: CCSprite is not using the same texture id 的意思是:CCSprite没 有使用相同的纹理贴图id)

什么时候应该使用CCSpriteBatchNode当你需要显示两个或者更多个相同的CCSprite节点时,你可以使用 CCSpriteBatchNode。组合在一起的CCSprite节点越多,使用 CCSpriteBatchNode得到的效果提升就越大。

不过也有一些限制。因为所有的CCSprite节点都添加到同一个 CCSpriteBatchNode中,所以所有CCSprite节点都会使用相同的z-order(深度)

来渲染。如果你的游戏要求子弹在敌人的前面和后面同时飞过的话,你就必须 使用两个CCSpriteBatchNode节点,因为只有这样你才能使用具有不同z-order 的子弹精灵。

另一个缺点是所有添加到同一个CCSpriteBatchNode中的CCSprite节点必须使用 同一个纹理贴图。不过那也意味着CCSpriteBatchNode非常适合使用纹理贴图集。 使用纹理贴图集的时候,你不仅仅局限于渲染一张图片;你可以把不同的图片 放到同一个纹理贴图集中,然后利用CCSpriteBatchNode将所有图片渲染出来, 以提高渲染速度。

如果把纹理贴图集和CCSpriteBatchNode配合使用的话,之前讨论的z-order渲 染问题就变得不那么明显了,因为你可以在单个CCSprite节点里指定不同的z- order值。如果你可以把所有在游戏中用到的图片都放到同一张纹理贴图集里的 话,你在游戏中使用一个CCSpriteBatchNode就够了(虽然这种情况极少发生)。

你可以把CCSpriteBatchNode看成CCLayer,唯一的区别是:CCSpriteBatchNode 只接受使用同一张纹理贴图的CCSprite节点。有了这样的认识以后,我相信你 会发现很多可以用到CCSpriteBatchNode的地方。


一个通常会犯的致命错误

Sprite01项目展示了一个新的Objective-C开发者通常会犯的错误。你很容易犯 这个错误,但是又很难找到它。请查看一下列表6-2中的代码,你能看到哪里出 错了吗? 

列表6-2.一个通常在继承CCSprite(或者其它类)时会犯的致命错误

‐(id) init {

if ((self = [super initWithFile:@"ship.png"]))

{
}
return self;

[self scheduleUpdate];

}

上述代码的问题是:-(id)init这个方法是默认的初始化方法,它最终会被任何 特殊的初始化方法(比如initWithFile)所调用。因为上述代码又调用了

[super initWithFile:..]这个特殊的初始化方法,最终产生了一个死循环。 解决的方法很简单。你只要像列表6-3所示那样把初始化方法换一个名字(只要

不是-(id)init)就可以了。

列表6-3. 解决列表6-2中的死循环

‐(id) initWithShipImage

{
{

}

return self; }


你可能感兴趣的:(2012-4-12 读书笔记)