GVKun编程网logo

-SpriteBatchNode与SpriteFrameCache加快渲染

15

在这篇文章中,我们将带领您了解-SpriteBatchNode与SpriteFrameCache加快渲染的全貌,同时,我们还将为您介绍有关CCSpriteBatchNode与"pvr.ccz","pl

在这篇文章中,我们将带领您了解-SpriteBatchNode与SpriteFrameCache加快渲染的全貌,同时,我们还将为您介绍有关CCSpriteBatchNode与"pvr.ccz","plist"精灵优化及注意事项、CCSpriteBatchNode中存放元素的一点理解、Cocos2d-js_____Sprite 和 SpriteBatchNode、cocos2d-x 3.0 精灵帧缓存(SpriteFrameCache)的知识,以帮助您更好地理解这个主题。

本文目录一览:

-SpriteBatchNode与SpriteFrameCache加快渲染

-SpriteBatchNode与SpriteFrameCache加快渲染

源地址

大家都知道一个游戏里面会有大量的图片,每个图片渲染是需要时间的,下面分析两个类来加快渲染速度,加快游戏运行速度

一、SpriteBatchNode
1、先说下渲染批次:这是游戏引擎中一个比较重要的优化指标,指的是一次渲染凋用。也就是说,渲染的次数越少,游戏的运行效率越高。
2、SpriteBatchNode就是cocos2d-x为了降低渲染批次而建立的一个专门管理精灵的类。
有人会问,怎么快速知道到底渲染了多少次了,告诉你吧,游戏左下角有三行数据:
GLverts表示给显卡绘制的顶点数
GLcalls表示代表每一帧中OpenGL指令的调用次数
FPS这个是帧率不多说
主要看第二个“GLcalls”代表每一帧中OpenGL指令的调用次数,这个数字越小,程序的绘制性能就越好。我们有没有法子让他小点了,答案当然是yes
首先我们使用sprite创建100个精灵,看看这个值是多少
code:

for(inti=0;i<100;++i)
{
charname[15];
memset(name,sizeof(name));
sprintf(name,"%d.png",i%10);
autosp=Sprite::create(name);
sp->setPosition(Point(i*5,i*5));
node->addChild(sp);
}
this->addChild(node);
这个循环创建了100个精灵,显示出来,看效果
看左下角红色圈圈,有101次绘制,其中100个元素每个元素绘制一次,多出来的一次是绘制这个左下角信息自己。
在来看看使用SpriteBatchNode
autospBatchNode=SpriteBatchNode::create("0.png");
spBatchNode->setPosition(Point::ZERO);
this->addChild(spBatchNode);
for(inti=0;i<100;++i)
{
count++;
//floatx=CCRANDOM_0_1()*visibleSize.width;
//floaty=CCRANDOM_0_1()*visibleSize.height;
//log("x=%lf,y=%lf",x,y);
autosp=Sprite::createWithTexture(spBatchNode->getTexture());
spBatchNode->addChild(sp);
}看效果图
看到没,立马减到2了,这快了太多了。这是一个提速,在来看看SpriteFrameCache
二、SpriteFrameCache
首先我们使用合图软件,将这10张图合成一张大图和一个plist文件。在使用CocoStudio导出时,选择“使用大图”即可将小图合成一张大图。当然我们也可以选择TexturePacker这种专业的合图软件,合成的图片分为“test.png”和“test.plist”两部分,然后使用SpriteFrameCache。
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("test.plist","test.png");
Node*node=Node::create();
charname[32];
charname[15];
memset(name,Simsun; font-size:14px; line-height:30px">//autosprite=Sprite::create(name);
autosprite=Sprite::createWithSpriteFrameName(name);
sprite->setPosition(Point(i*5,Simsun; font-size:14px; line-height:30px">node->addChild(sprite,0);
这段代码中,我们调用addSpriteFramesWithFile函数,将大图载入到内存中,创建对象时,调用createWithSpriteFrameName从缓存纹理中载入图片。如此做我们所有的绘制调用都可以合并到一次OpenGL指令中,这些绘制指令的计算与合并都由Cocos2d-x引擎完成。编译运行如下图所示:
我们可以非常明显的看到,优化后的程序“GLcalls”依然变成了2次。
还有一种优化,就是当精灵超出屏幕后就剔除掉,这样也能减少OpenGL指令。
三、绘制剔除
相对于上一种优化,这个要更容易理解。它是指当一个元素移动到屏幕之外,就不进行绘制。
code:
autosprite=Sprite::create(name);
//autosprite=Sprite::createWithSpriteFrameName(name);
sprite->setPosition(Point(i*5,Simsun; font-size:14px; line-height:30px"> node->addChild(sprite,Simsun; font-size:14px; line-height:30px">autolistener=EventListenerTouchOneByOne::create();
listener->onTouchBegan=[=](Touch*pTouch,Event*pEvent)
returntrue;
};
listener->onTouchMoved=[=](Touch*pTouch,Simsun; font-size:14px; line-height:30px"> node->setPosition(node->getPosition()+pTouch->getDelta());
Director::getInstance()->getEventdispatcher()->
addEventListenerWithSceneGraPHPriority(listener,this);
returntrue;}
效果图如下:
我们发现GLcalls也变小了,这也是一种不错的方法
四、小结总的来说,这两点优化可以说是对程序性能有了极大提升。同时在开发的过程中,也使程序员不必过多的纠结于渲染效率的优化。

CCSpriteBatchNode与

CCSpriteBatchNode与"pvr.ccz","plist"精灵优化及注意事项

本站文章均为 李华明Himi 原创,转载务必在明显处注明:

转载自【黑米GameDev街区】 原文链接: http://www.himigame.com/iphone-cocos2d/465.html 

前几节由于时间紧张,只是将一些遇到的问题拿出来进行分享经验,那么今天抽空写一篇常用的精灵以及精灵常用和注意的一些知识;那么由于cocos2d教程基本很完善,那么今天Himi介绍一些注意点和细节点分享大家;

            首先对于使用过精灵的童鞋很熟悉CCSpriteBatchNode,至少大家都会知道它能优化精灵,但是至于优化原理这里简单说下:

            一般使用精灵CCSprite的时候,都是直接使用[cclayer* addChild:CCSprite *];,假设我们创建一百个精灵,那么当前的cclayer会为100个精灵单独绘制;

           如果使用精灵集合-CCSpriteBatchNode的话,直接将集合CCSpriteBatchNode添加cclayer中即可,即使创建一百个精灵,我们也都是将100个精灵添加到集合中,[CCSpriteBatchNode* addChild:CCSprite];而已;

           两者的区别:

         1.  直接使用cclayer进行添加精灵,cclayer上有几个精灵,那么底层就会绘制几次精灵;

                      简单可以理解成底层绘制方式如下:

                      for(int i= 0;i<100;i++){open-draw-close;}

          但是使用集合的话,cclayer只需要对精灵集合进行一次渲染,

                     简单可以理解成底层绘制方式如下:

                    open-draw(100次绘制)-close

         从以上两种方式可以看出两者的区别了,第二种使用精灵集合省去了99次open和close的过程,从而达到优化作用;

          上次参加iOS第四次开发者大会,cocos2d-x的张哲在演讲中重点拿出了这一点进行讲解,他在ipad上使用两种方式给出的数据如下:

                  在屏幕中绘制3000个精灵,直接使用cclayer添加精灵的方式,帧数从60下降到不到20帧;

                  同样在屏幕中绘制3000个精灵,使用CCSpriteBatchNode的渲染方式,帧数保持在50帧左右;

          当然Himi也亲自测试过,但是由于真机调试的还没申请下来,所以只能在模拟器上测试,发现同时绘制300个精灵,两种方式帧数一致,无区别;不是因为没差别,而是因为在iOS模拟器中,帧数与屏幕中的精灵数量有关,真机则会很明显的体现两者的区别;

       2.使用CCSpriteBathNode虽然能达到优化,但是要注意一点:

          初始化精灵集合CCSpriteBatchNode的时候会加载一张图片资源(或者pvr文件等),那么限制其精灵集合的子精灵都必须使用集合加载的这张图才行,否则会给出警告;       

       3.使用CCSpriteBatchNode还要注意一点,因为精灵都存放在集合中,那么这个集合CCSpriteBatchNode中的节点(精灵)都将在同一个z轴上,同一深度上; 

       在上一章中介绍过TexturePacker工具的作用,那么这里不介绍如何使用,而是说下主要的两点,一般使用TexturePacker工具都会将很多精灵图片或者动作帧放在一起打包成“.pvr.ccz”、".plist"、“-hd.pvr.ccz”和"-hd.plist"的四个文件,其中两个-hd的是使用工具生成的打包资源的高清版本(940*480)使用的,这个不再强调了;

      至于".pvr.ccz"格式的则是最压缩、最适合iOS的资源文件格式了,那么与".plist"两个文件的使用方式其实也很简单,代码如下:

view plain
  1. [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"XX.plist"];  

    以上代码是将".pvr.ccz"资源包的图进行加载到精灵帧缓存中,一旦加载过后,你就可以任意使用了,比如你将icon.png和himi.png两张图片一起利用工具打包成“.pvr.ccz”、".plist"两个文件后,将两个文件放在项目下(两张图片不需要了),然后使用刚才的代码将资源包加载缓存中,只需要加载plist文件即可,pvr.ccz的不需要加载,但是也需要放在项目下,然后你在创建精灵的时候可以使用以下形式进行创建精灵:

CCSprite *sprite = [CCSprite spriteWithSpriteFrameName:@"himi.png"];  


      通过上面这行代码可以看出,此种创建精灵的方式是利用帧缓存创建的,那么也就是说一旦加载的许多个一样的精灵的时候利用此方式相当优化运行内存,最容易想到的就是创建子弹;

       那么肯定会有童鞋说,那么如果把这资源文件与CCSpriteBathNode结合使用岂不是更嗨皮,没错,可以的,加载的时候只需要将如下创建集合即可: 

CCSpriteBatchNode spritesBgNode = [CCSpriteBatchNode batchNodeWithFile:@"xx.pvr.ccz"];  
  • [cclayer* addChild:spritesBgNode];      
  • [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"xx.plist"];  

  •      最后顺便跟大家强调需要重点注意的三点:

         1.使用TexturePacker工具虽然可以对应生成@2x与-hd文件,但是工具会将你导入的所有精灵图的会做作为-hd的资源包生成,而对应的非高清的则是当前图片尺寸缩放一半的资源而已;

         2.如果你项目中需要加载使用一张"himi.png"的图的话,那么在cocos2d引擎开发的项目中,首先会去资源中寻找"himi-hd.png"的图片,如果找不到则会去寻找"himi@2x.png"的图,所以这里一定要注意资源的命名和使用;

        3.在cocos2d 1.0.0的版本中千万不要在使用pvr.ccz与plist文件的时候加上以下代码: 

    [CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_Default];  


    一些教程都会加,但是加上之后发现图片透明像素都被白色填充!

        而且在使用TexturePacker工具选取打包成pvr.ccz格式的时候会提示让你加上这么一句代码: 

    [CCTexture2D PVRImagesHavePremultipliedAlpha:YES];  

       工具原文提示如下: 

      Himi在代码中测试过,有木有这句都无所谓,不会有什么影响,至少在cocos2d 1.0.0的版本中加不加无所谓;

             好了,这篇就到这里,继续忙了。。。。。。

     

    本文出自 “李华明Himi” 博客,请务必保留此出处http://www.voidcn.com/article/p-nruopnkg-bc.html

    CCSpriteBatchNode中存放元素的一点理解

    CCSpriteBatchNode中存放元素的一点理解

    该对象只能包含基于CCSprite的对象,并且该要求适用于一切子孙对象.即加入CCSpriteBatchNode的任何对象都必须是CCSprite或其子类.

    比如CCSpriteBatchNode包含Fire对象,而Fire对象继承于CCSprite类;如果Fire有子对象,则要求他们也必须继承于CCSprite,依次类推.

    不过貌似最新的Cocos2D中该类用的地方越来越少了,而且在SpriteKit中,所有这些都是由系统帮你搞定的,你不需要在操心在视图上显示大量精灵时需要考虑类似的情况了.

    具体的使用情况,大家可以在我Cocos2D游戏系列编程博客中了解更多.

    Cocos2d-js_____Sprite 和 SpriteBatchNode

    Cocos2d-js_____Sprite 和 SpriteBatchNode

    Sprite 和 SpriteBatchNode点击打开链接

    v2.2 2.2版本中推荐的优化游戏方式是将SpriteBatchNode对象设置为Sprite对象的父节点。 虽然使用SpriteBatchNode对象仍然是一个非常好的优化游戏的方式,但是它仍然有一定的限制:

    • Sprite对象的孩子只能是Sprite(否则,Cocos2d-x 会触发断言)
      • Sprite的父节点是SpriteBactchNode时,不能添加ParticleSystem作为Sprite的子节点。
      • 这将导致当SpriteBatchNode时,不能使用ParallaxNode
    • 所有的Sprite对象必须共享相同的纹理ID (否则,Cocos2d-x 会触发断言)
    • Sprite对象使用SpriteBatchNode的混合函数和着色器。

    虽然 v3.0 仍然支持SpriteBatchNode(与之前的版本拥有相同的特效和限制),但是我们不鼓励使用它。相反,我们推荐直接使用Sprite,不需要再它作为子节点添加到SpriteBatchNode中。

    但是,为了能让 v3.0 有更好的表现,你必须要确保你的Sprite对象满足以下条件:

    • 贡献相同的纹理ID(把它们放在一个spritesheet中,就像使用SpriteBatchNode一样)
    • 确保它们使用相同的着色器和混合函数(就像使用SpriteBatchNode一样)

    如果这么做,Sprites将会像使用SpriteBatchNode一样的快...(在旧设备上大概慢了10%,在新设备上基本上察觉不出)

    v2.2 和 v3.0 最大的区别在于:

      Sprite对象可以有不同的纹理ID。
    • Sprite对象可以有不同种类的Node作为子节点,包括ParticleSystem
    • Sprite对象可以有不同的混合函数和不同的着色器。

    但是如果你这么做,渲染器可能无法对它所有的子节点进行批处理(性能较低)。但是游戏仍然可以正常运行,不会触发任何断言。

    总结:

    • 保持将所有的精灵放在一张大的 spritesheet 中。
    • 使用相同的混合函数(使用默认)
    • 使用相同的着色器(使用默认)
    • 不要将精灵添加到SpriteBatchNode

    只有当你需要一些额外的性能上提升(虽然很小),SpriteBatchNode才会是你最后的选择(你需要对它的限制条件很熟悉)。

    cocos2d-x 3.0 精灵帧缓存(SpriteFrameCache)

    cocos2d-x 3.0 精灵帧缓存(SpriteFrameCache)

    SpriteFrameCache 主要服务于多张碎图合并出来的纹理图片。这种纹理在一张大图中包含了多张小图,直接通过TextureCache引用会有诸多不便,因而衍生出来精灵框帧的处理方式,即把截取好的纹理信息保存在一个精灵框帧内,精灵通过切换不同的框帧来显示出不同的图案。

    SpriteFrameCache
    SpriteFrameCache的内部封装了一个Map<std::string,SpriteFrame*> _spriteFrames对象。key为帧的名称。SpriteFrameCache一般用来处理plist文件(这个文件指定了每个独立的精灵在这张“大图”里面的位置和大小),该文件对应一张包含多个精灵的大图,plist文件可以使用TexturePacker制作。
    SpriteFrameCache的常用接口和TextureCache类似,不再赘述了,唯一需要注意的是添加精灵帧的配套文件一个plist文件和一张大的纹理图。下面列举了SpriteFrameCache常用的方法:(详细API请看SpriteFrameCache API)
    获取单例的SpriteFrameCache对象。sharedSpriteFrameCache方法在3.0中已经弃用
    复制代码
    1. SpriteFrameCache* cache = SpriteFrameCache::getInstance();

    销毁SpriteFrameCache对象。
    复制代码 SpriteFrameCache::destroyInstance();

    使用SpriteFrameCache获取指定的精灵帧,创建精灵对象
    复制代码 SpriteFrameCache *frameCache = SpriteFrameCache::getInstance();
  • frameCache->addSpriteFramesWithFile("boy.plist","boy.png");//boy.png里集合了boy1.png,boy2.png这些小图
  • auto frame_sp = Sprite::createWithSpriteFrameName("boy1.png");//从SpriteFrameCache缓存中找到boy1.png这张图片.
  • this->addChild(frame_sp,2);

  • SpriteFrameCache vs. TextureCache
    SpriteFrameCache精灵框帧缓存。顾名思义,这里缓存的是精灵帧SpriteFrame,它主要服务于多张碎图合并出来的纹理图片。这种纹理在一张大图中包含了多张小图,直接通过TextureCache引用会有诸多不便,因而衍生出来精灵框帧的处理方式,即把截取好的纹理信息保存在一个精灵框帧内,精灵通过切换不同的框帧来显示出不同的图案。
    跟TextureCache功能一样,将SpriteFrame缓存起来,在下次使用的时候直接去取。不过跟TextureCache不同的是,如果内存池中不存在要查找的图片,它会提示找不到,而不会去本地加载图片。
    * TextureCache时最底层也是最有效的纹理缓存,缓存的是加载到内存中的纹理资源,也就是图片资源。
    * SpriteFrameCache精灵框帧缓存,缓存的时精灵帧。
    * SpriteFrameCache是基于TextureCache上的封装。缓存的是精灵帧,是纹理指定区域的矩形块。各精灵帧都在同一纹理中,通过切换不同的框帧来显示出不同的图案。

    关于-SpriteBatchNode与SpriteFrameCache加快渲染的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于CCSpriteBatchNode与"pvr.ccz","plist"精灵优化及注意事项、CCSpriteBatchNode中存放元素的一点理解、Cocos2d-js_____Sprite 和 SpriteBatchNode、cocos2d-x 3.0 精灵帧缓存(SpriteFrameCache)等相关知识的信息别忘了在本站进行查找喔。

    本文标签:

    上一篇cocos-js web开发泡泡龙游戏【一 加载游戏场景】(经典的泡泡龙游戏源码)

    下一篇SpriteBuilder Demo学习笔记(spriter教程)