我的Cocos2d-x学习笔记八利用CCSpriteBatchNode进行优化

OpenGL是一个基于C语言的三维图形API,是一个开放的、跨平台的图形接口。

OpenGL ES是OpenGL在移动设备上的版本。

Cocos2d-x是一个基于OpenGL的游戏引擎,渲染功能由OpenGL实现。

游戏中会用到许多图片资源,对图片资源渲染进行优化能明显提高效率。

OpenGL中纹理的长和宽像素是2的幂,大小不足的纹理补充到2的幂大小;可以通过把多张小图片合成一张大图加载到游戏中,减少纹理加载次数,减少补齐2的幂大小的空白。

之前学习的纹理缓存、精灵帧缓冲可以把纹理等预先加载到内存中,访问时候节省访问时间;除此之外还可以通过CCSpriteBatchNode节省渲染次数来达到优化的目的。

CCSpriteBatchNode(精灵批处理类):

原理借鉴一下权威指南内容:

当你需要显示两个或两个以上相同的精灵时,如果逐个渲染精灵,每一次渲染都会调用OpenGL的函数;

因为当系统在屏幕上渲染一张贴图的时候,图形处理硬件必须首先准备渲染,然后渲染图形,最后完成渲染以后的清理工作。

以上是每次渲染固定的开销,这样帧率就会下降15%左右或者更多。
如果将所有需要渲染的同一张贴图只进行一次准备,一次渲染,一次清理就可以解决这个问题了。

这时可以使用CCSpriteBatchNode类来批处理这些精灵。

CCSpriteBatchNode:

先来看看它的创建相关代码:

class CC_DLL CCSpriteBatchNode : public CCNode,public CCTextureProtocol
{
public:
	static CCSpriteBatchNode* create(const char* fileImage,unsigned int capacity);
	static CCSpriteBatchNode* create(const char* fileImage)
	{
		return CCSpriteBatchNode::create(fileImage,kDefaultSpriteBatchCapacity);
	}
	static CCSpriteBatchNode* createWithTexture(CCTexture2D* tex,unsigned int capacity);
	static CCSpriteBatchNode* createWithTexture(CCTexture2D* tex) 
	{
		return CCSpriteBatchNode::createWithTexture(tex,kDefaultSpriteBatchCapacity);
	}
}
由上述代码可以看到CCSpriteBatchNode可以通过图片文件直接创建,也可以通过纹理来创建。

CCSpriteBatchNode

(一)、通过图片文件创建CCSpriteBatchNode并且使用它

	static CCSpriteBatchNode* create(const char* fileImage,kDefaultSpriteBatchCapacity);
	}
通过纹理图片直接创建精灵批处理我们可以使用两个创建函数,不过由上述代码可以看出其实只有一个创建函数;

只指定纹理图片路径名称时候,其第二个参数capacity(表示纹理图像容量)为一个系统默认值,并且此函数调用的为两个参数的create函数。

实例:

	CCSpriteBatchNode* batchNode = CCSpriteBatchNode::create("HelloWorld.png");
	for (int i = 0; i < 50; i++)
	{
		CCSprite* sprite = CCSprite::create("HelloWorld.png");
		batchNode->addChild(sprite);
	}
	addChild(batchNode);
首先,通过纹理图片创建一个精灵批处理;

之后,通过循环创建50个精灵,把这50个精灵添加到批处理当中;

最后把批处理加入到父节点。

(二)通过CCTexture2D创建CCSpriteBatchNode并且使用它

实例一:通过纹理缓存中取得纹理创建精灵批处理,此后创建精灵时候可以使用纹理图片名字创建。

	CCTexture2D * texture = CCTextureCache::sharedTextureCache()->addImage("HelloWorld.png");
	CCSpriteBatchNode* batchNode = CCSpriteBatchNode::createWithTexture(texture);
	for (int i = 0; i < 29; i++)
	{
		CCSprite* sprite = CCSprite::create("HelloWorld.png");
		batchNode->addChild(sprite);
	}
	addChild(batchNode);
	CCTexture2D * texture = CCTextureCache::sharedTextureCache()->addImage("HelloWorld.png");
	CCSpriteBatchNode* batchNode = CCSpriteBatchNode::createWithTexture(texture);
	for (int i = 0; i < 50; i++)
	{
		CCSprite* sprite = CCSprite::createWithTexture(texture);
		batchNode->addChild(sprite);
	}
	addChild(batchNode);

上诉两种方式实际上使用起来同样效果,解释如下:

首先,通过纹理缓存获取一个纹理;

之后,通过循环创建50个精灵,把这50个精灵添加到批处理当中,此时创建精灵的时候可以使用纹理图片名称,也可以使用之前从纹理缓冲中获取的纹理;

最后把批处理加入到父节点。

实例二:通过直接创建一个纹理(CCTexture2D)来创建精灵批处理,此后精灵创建时候必须使用之前创建的纹理来创建精灵。

	CCImage* image = new CCImage();
	image->initWithImageFile("HelloWorld.png");
	image->autorelease();
	CCTexture2D* texture = new CCTexture2D();
	texture->initWithImage(image);
	texture->autorelease();

	CCSpriteBatchNode* batchNode = CCSpriteBatchNode::createWithTexture(texture);
	for (int i = 0; i < 50; i++)
	{
		CCSprite* sprite = CCSprite::createWithTexture(texture);
		batchNode->addChild(sprite);
	}
	addChild(batchNode);

首先,通过new的方式获取一个纹理;

之后,通过循环创建50个精灵,把这50个精灵添加到批处理当中,此时的精灵需要用到之前创建的纹理来创建;

最后把批处理加入到父节点。

实例三:加载多张图片使用

	CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("batch.plist");
	CCSpriteBatchNode* batchNode = CCSpriteBatchNode::create("bach.png");
	addChild(batchNode);

上诉代码在精灵帧缓冲中加入一个plist文件;

利用plist对应的图片创建CCSpriteBatchNode;

之后

	static bool flag = true;
	CCSprite * sprite;
	for (int i = 0; i < 1000; i++)
	{
		if (flag)
		{
			sprite = CCSprite::createWithSpriteFrameName("one.png");
		}
		else{
			sprite = CCSprite::createWithSpriteFrameName("two.png");
		}
		flag = !flag;
		sprite->setPosition(ccp(CCRANDOM_0_1() * 480,CCRANDOM_0_1() * 320));
		batchNode->addChild(sprite);
	}
之前把纹理图片添加到精灵帧缓冲中后使用CCSpriteBatchNode创建同一张图片;

此后通过精灵帧缓冲中的精灵帧创建精灵同样为优化后的。


总结:

当我们需要多次使用同一张纹理创建的精灵时候使用它。

因为所有CCSprite节点都添加到同一个CCSpriteBatchNode中,所以所有CCSprite的zOrder相同。

添加到同一个CCSpriteBatchNode中的CCSprite必须使用同一个纹理图片。

精灵帧缓冲(CCSpriteFrameCache)与精灵批处理(CCSpriteBatchNode)结合使用效果更好!

相关文章

    本文实践自 RayWenderlich、Ali Hafizji 的文章《...
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@1...
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从C...
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发...
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《...
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试...