zoukankan      html  css  js  c++  java
  • 我的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, 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)结合使用效果更好!

        

  • 相关阅读:
    css之position
    js之循环语句
    js之条件判断
    js之字典操作
    js之获取html标签的值
    5.15 牛客挑战赛40 C 小V和字符串 数位dp 计数问题
    5.21 省选模拟赛 luogu P4297 [NOI2006]网络收费 树形dp
    luogu P4525 自适应辛普森法1
    luogu P1784 数独 dfs 舞蹈链 DXL
    5.21 省选模拟赛 luogu P4207 [NOI2005]月下柠檬树 解析几何 自适应辛普森积分法
  • 原文地址:https://www.cnblogs.com/gongyan/p/4539405.html
Copyright © 2011-2022 走看看