您的位置:首页 > 移动开发 > Cocos引擎

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

2015-05-29 00:21 501 查看
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, unsigned int capacity);
static CCSpriteBatchNode* create(const char* fileImage)
{
return CCSpriteBatchNode::create(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)结合使用效果更好!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: