
bool HelloWorld::init(){ if(!Layer::init()){ return false; } //创建一堆的精灵 for(int i=0;i<20000;i++){ Sprite* s = Sprite::create("sprite.png"); s->setposition(Point(CCRANDOM_0_1()*480,120+CCRANDOM_0_1()*300)); this->addChild(s); }}查看调试信息 第一行的数字表示顶点数量; 第二行的数字表示渲染批次,意思就是,要执行多少次渲染; 第三行左边的数字是帧率,右边的是每一帧所需的时间; 在cocos2d-x 2.0的时候,像这样创建这么多精灵的话应该已经卡掉了吧;
然后在3.0,cocos2d-x自己做了优化,会自动处理这样的情况,叫做auto-batching;
2.3.0的新功能auto-batching要auto-batching生效,需要满足的条件(好吧,看不懂啊)
需要确保精灵对象拥有相同的TextureID(精灵表单Spritesheet) 确保他们都是用相同的材质和混合功能 不再把精灵添加SpriteBatchNode一般情况下,我们用同一张图片,并没有做特殊处理,就能满足auto-batching的条件,不需要我们去做处理
3.auto-batching的一些问题bool HelloWorld::init(){ if(!Layer::init()){ return false; } //创建一堆的精灵 for(int i=0;i<20000;i++){ Sprite* s = Sprite::create("sprite.png"); s->setposition(Point(CCRANDOM_0_1()*480,120+CCRANDOM_0_1()*300)); this->addChild(s); s = Sprite::create("sprite1.png"); s->setposition(Point(CCRANDOM_0_1()*480,120+CCRANDOM_0_1()*300)); this->addChild(s); }}循环创建了两个不同的精灵,运行的结果和预期的不同,auto-batching没有生效 auto-batching的另外一个限制条件,对于不连续的渲染对象,是无法在一个渲染批次里进行渲染的。
怎样才算是“连续的对象”,最简单的解释就是:
如果节点具有相同的globalZOrder值,则是连续的; 否则,如果节点具有相同的localZOrder值,则是连续的; 否则,如果节点具有相同的orderOfArrival值,则是连续的; 连续的节点还必须使用相同的纹理,就是相同的图片咯。bool HelloWorld::init(){ if(!Layer::init()){ return false; } //创建一堆的精灵 for(int i=0;i<20000;i++){ Sprite* s = Sprite::create("sprite.png"); s->setposition(Point(CCRANDOM_0_1()*480,120+CCRANDOM_0_1()*300)); this->addChild(s); s->setGlobalZOrder(1); s = Sprite::create("sprite1.png"); s->setposition(Point(CCRANDOM_0_1()*480,120+CCRANDOM_0_1()*300)); this->addChild(s); s->setGlobalZOrder(2); }} 给每个精灵设置了globalZOrder属性,globalZOrder对排序有了影响,,使得所有的sprite精灵都是连续的,sprite1也是连续的
这就满足了auto-batching的条件了。
影响精灵排序的优先级:globalZOrder优先于LocalZOrder,localZOrder优先于orderOfArrival
SpriteBatchNode如果包含了子节点,那么所有的子节点在绘制的时候只会调用一次OpenGL的渲染。只有使用同一纹理的精灵才能添加到SpriteBatchNode上,如果精灵没有添加到SpriteBatchNode上,那么每一个精灵的绘制都会调用一次OpenGL的渲染(当然咯,满足auto-batching条件的除外咯)。
bool HelloWorld::init(){ if(!Layer::init()){ return false; } //创建批次渲染对象,并添加到场景中 SpriteBatchNode* batchNode = SpriteBatchNode::create("sprite.png"); this->addChild(batchNode); //创建精灵,加入到批次渲染对象中 for(int i=0;i<999;i++){ Sprite* s = Sprite::cretae("sprite.png"); s->setposition(Point(CCRANDOM_0_1()*480,120+CCRANDOM_0_1()*200)); batchNode->addChild(s); } return true;}这边是先将SpriteBatchNode加入到场景中,再将精灵加到SpriteBatchNode中; 当然,SpriteBatchNode也是有限制的,并需把精灵添加到SpriteBatchNode上,并且只允许添加精灵对象,其他的对象是不允许添加的。 6.Texture简单介绍---纹理
使用相同的图片或者使用相同图片的一部分具有相同的纹理
bool HelloWorld::init(){<span > </span>if(!Layer::init()){<span > </span>return false;<span > </span>}<span > </span>//截取图片的一部分来创建精灵<span > </span>Sprite* s1 = Sprite::createWithSpriteFrame(SpriteFrame::create("sprite.png",Rect(0,60,50)));<span > </span>Spritr* s2 = Sprite::create("sprite.png");<span > </span>s1->setposition(Point(100,200));<span > </span>s2->setposition(Point(300,200));<span > </span>this->addChild(s1);<span > </span>this->addChild(s2);<span > </span>//获取两个精灵的纹理对象,通过控制台观察,发现两个精灵对象的值是一样的<span > </span>Texture2D* t1 = s1->getTexture();<span > </span>Texture2d* t2 = s2->getTexture();<span > </span><span > </span>return true;} 7.TexturePacker工具
当需创建多个精灵的时候,图片不一样,纹理就没有办法相同的,那就不能使用auto-batching或者SpriteBatchNode了。
这个时候,我们就要将多个图片拼接的一个图片中了。
当一张图片中拥有多个精灵时。
bool HelloWorld::init(){ if(!Layer::init()){ return false; } //截取图片的一部分来创建精灵 Sprite* s1 = Sprite::createWithSpriteFrame("Sprites.png",50));//精灵一 Spritr* s2 = Sprite::createWithSpriteFrame("Sprites.png",Rect(30,30,50));//精灵二 s1->setposition(Point(100,200)); s2->setposition(Point(300,200)); this->addChild(s1); this->addChild(s2); return true;}以上是手动计算精灵在图中的位置,不过相对来说是比较麻烦的 接下来,我们就要使用到工具了
TexturePacker图片打包工具:http://www.codeanDWeb.com/texturepacker
不过打开来相对是比较慢的,还有,好像官网是不允许下载旧版本的,要输入什么东西
TexturePacker一些选项的作用
Data Format:生成配置文件的格式类型,不同引擎支持不同的格式 Texture Format:生成的图片的格式 Image Format:图片色彩模式,木头使用的是RGBA4444 Dithering:抖动显示,如果我们选择的图片色彩模式比较低(颜色数较少)导致图片失真严重,可以通过抖动显示来缓解失真程度 Size constraints:图片打包都是按2的次方的 Allow rotation:是否允许图片旋转,旋转在某些时候可以缩小图片 Trim:是否允许把图片透明部分去掉点击“Publish”按钮,导出打包后的文件"*.pList"和"*.png"
8.加载打包后的图片既然用TexturePacker打包好了图片,我们当然就要使用它了
将两个文件复制到resources文件夹下
bool HelloWorld::init(){ if(!Layer::init()){ return false; } //将图片添加到精灵缓存池 SpriteFrameCache* frameCache = SpriteFrameCache::getInstance(); frameCache->addSpriteFramesWithfile("Sprites.pList","Sprites.png"); //用小图片的名字即可创建精灵,即使是旋转了的图片,这样创建出来也是正常的 Sprite* s = Sprite::createWithSpritename("sprite1.png"); s->setposition(Point(100,200)); This->addChild(s); return true;} 创建精灵时使用的是打包前图片的名字,pList文件里记录了各个图片在大图片中的位置和大小
9.动画Animation
Animate* HelloWorld::createAnimate1(){ //将15张动作的图片放到resources文件夹中 int sNum = 15;//动作图片的数量 SpriteFrame* frame = NulL;//每个图片为一个SpriteFrame对象 Vector<SpriteFrame*> frameVec; //用一个列表保存所有SpriteFrame对象 for(int i=1;i<=sNum;i++){ frame = SpriteFrame::create(StringUtils::format("run%d.png",i),130,130)); frameVec.pushBack(frame); } //使用SpriteFrame列表创建动画对象 Animation* animation = Animation::createWithSpriteFrames(frameVec); animation->setLoops(-1);//循环次数,-1表示无限循环 animation->setDelayPerUnit(0.1f);//设置每一帧播放延迟 //将动画包装成一个动作 Animate* action = Animate::create(animation); return action;}bool HelloWorld::init(){ if(!Layer::init()){ return false; } Sprite* sprite = Sprite::create("run1.png"); sprite->setposition(Point(200,200)); sprite->runAction(createAnimate1);//直接执行就可以了}在没有打包图片的时候,需要指定图片的大小,接下来我们就用打包后的图片来创建动画 Animate* HelloWorld::createAnimate1(){ //加载图片帧到缓存池 SpriteFrameCache* frameCache = SpriteFrameCache::getInstance(); frameCache.addSpriteFramesWithfile("boys.pList","boys.png"); //将15张动作的图片放到resources文件夹中 int sNum = 15;//动作图片的数量 SpriteFrame* frame = NulL;//每个图片为一个SpriteFrame对象 Vector<SpriteFrame*> frameVec; //用一个列表保存所有SpriteFrame对象 for(int i=1;i<=sNum;i++){ frame = frameCache->getSpriteFrameByname(StringUtils::format("run%d.png",i)); frameVec.pushBack(frame); } //使用SpriteFrame列表创建动画对象 Animation* animation = Animation::createWithSpriteFrames(frameVec); animation->setLoops(-1);//循环次数,-1表示无限循环 animation->setDelayPerUnit(0.1f);//设置每一帧播放延迟 //将动画包装成一个动作 Animate* action = Animate::create(animation); return action;} 10.创建动画的辅助类
AnimationUtil
头文件
#ifndef _ANIMATION_UTIL_H_#define _ANIMATION_UTIL_H_#include "cocos2d.h"class AnimationUtil{ static cocos2d::Animation* createWithStringFramename(const char* name,float delay,int iLoops); static cocos2d::Animation* createWithStringFramenameAndNum(const char* name,int num,int iLoops);};#endifcpp #include "AnimationUtil.h"USING_NS_CC;//根据名字来创建Animation* AnimationUtil::createWithStringFramename(const char* name,int iLoops){<span > </span>SpriteFrameCache* frameCache = SpriteFrameCache::getInstance();<span > </span>Vector<SpriteFrame*> frameVec;<span > </span>SpriteFrame* frame = NulL;<span > </span>int index = 1;<span > </span>do{<span > </span>frame = frameCache->getSpriteFrameByname(StringUtils::format("%s%d.png",name,index++));<span > </span>if(frame == NulL){<span > </span>break;<span > </span>}<span > </span>frameVec.pushBack(frame);<span > </span>}while(true);<span > </span>Animation* animation = Animation::createWithSpriteFrames(frameVec);<span > </span>animation->setLoops(iLoops);<span > </span>animation->setRestoreOriginalFrame(true);<span > </span>animation->setDelayPerUnit(delay);<span > </span>return animation;}//根据名字和数量来创建Animation* AnimationUtil::createWithStringFramenameAndNum(const char* name,int iLoops){<span > </span>SpriteFrameCache* frameCache = SpriteFrameCache::getInstance();<span > </span>Vector<SpriteFrame*> frameVec;<span > </span>SpriteFrame* frame = NulL;<span > </span>int index = 1;<span > </span>for(int i = 1;i<=num;i++){<span > </span>frame = frameCache->getSpriteFrameByname(StringUtils::format("%s%d.png",index++));<span > </span>if(frame == NulL){<span > </span>break;<span > </span>}<span > </span>frameVec.pushBack(frame);<span > </span>}<span > </span>Animation* animation = Animation::createWithSpriteFrames(frameVec);<span > </span>animation->setLoops(iLoops);<span > </span>animation->setRestoreOriginalFrame(true);<span > </span>animation->setDelayPerUnit(delay);<span > </span>return animation;}使用方法 SpriteFrameCache* frameCache = SpriteFrameCache::getInstance();frameCache->addSpriteFramesWithfile("runs.pList","runs.png");Animation* action = AnimationUtil::createWithStringFramename("run",0.1f,-1);sprite->runAction(Animate::create(action)); 总结 以上是内存溢出为你收集整理的【Cocos2d-x3.0学习笔记 08】精灵来了全部内容,希望文章能够帮你解决【Cocos2d-x3.0学习笔记 08】精灵来了所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)