【Cocos2d-x3.0学习笔记 08】精灵来了

【Cocos2d-x3.0学习笔记 08】精灵来了,第1张

概述1.大量绘制精灵 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,12 1.大量绘制精灵
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


4.深入了解auto-batching,嗯,我还看不懂,之后再回过来看


5.一次渲染,SpriteBatchNode的特别之处

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);};#endif
cpp
#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】精灵来了所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/web/1007208.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-22
下一篇2022-05-22

发表评论

登录后才能评论

评论列表(0条)

    保存