精灵的优化

cocos2dx针对游戏设计的不同方面会有不同的优化方案,可以对声音,对内存,对图片格式,对色彩等等进行优化。有关这些方面的方法请大家查找其他的文章。我今天要说的是如何对精灵进行优化,程序中我们用到的最多的就是精灵,大到背景、UI,小到 NPC、道具,只要是用图片展示的,都是精灵或它的子类。精灵是什么,在我看来精灵就是一张纹理图片,是按某种方式显示出来的图片。精灵如此的重要,我们当然要好好的优化优化了。我们可以减小精灵图片的大小,使用缓存Cache的方法将精灵提前加载到内存中,当有很多精灵的时候,使用批次渲染的方法。所以我就从缓存和批次渲染这俩个方面来说一下如何优化我们的精灵图片。
1、通过批次渲染的方法来优化精灵。在游戏中的某一时刻,有时候会用到大量的精灵,比如说发射子弹,粒子效果,这些精灵图片所使用的纹理都是相同的,如果一张一张的图片进行渲染势必会降低效率,大家在开发中看到的窗口的左下角的三行数字中,第一行数字就是渲染批次,这个渲染批次在我看来就是画了多少次,cocos2dx中使用opengl进行绘图,渲染的批次越少当然越好了,所以这个渲染批次才会显示在左下角让我们参考。我们应当尽量的减小这个渲染的批次,提高游戏的效率。方法就是使用CCSpriteBatchNode和CCParticleBatchNode精灵批节点类和粒子批节点类。先来看看在代码中如何使用它们。

?


1

2

3

4

5

6

7

8

CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();

//创建了十个精灵将这十个精灵添加到当前的层中

for(int i=0;i<10;i++)

{

    CCSprite * sprite = CCSprite::create("icon.png");

    sprite->setPosition(ccp(CCRANDOM_0_1()*visibleSize.width,CCRANDOM_0_1()*visibleSize.height));

    this->addChild(sprite);

}

上边的这种情况是采用一般的方式将精灵添加到层中的,这个时候的渲染批次是10。

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

//创建一个CCSpriteBatchNode,传入的参数就是精灵们将要用到的图片

    CCSpriteBatchNode * batchNode = CCSpriteBatchNode::create("icon.png");

    //或者使用texture2d初始化,里边传入一个texture

    //CCSpriteBatchNode * batch = CCSpriteBatchNode::createWithTexture();

    //这一句写不写都可以,因为node的默认坐标就是(0,0)

    batchNode->setPosition(CCPointZero);

    for(int i=0;i<10;i++)

    {

        //创建的这些精灵所使用的纹理必须和CCSpriteBatchNode相同,而且所有这些精灵必须在同一个渲染层

        CCSprite * sprite = CCSprite::createWithTexture(batchNode->getTexture());

        sprite->setPosition(ccp(CCRANDOM_0_1()*visibleSize.width,CCRANDOM_0_1()*visibleSize.height));

        batchNode->addChild(sprite);

    }

    this->addChild(batchNode);

采用上边的方法添加精灵到层中,渲染批次是1,就是因为我们用到了CCSpriteBatchNode这个类,从道理上来说,这个类也是一个node,通常我们使用node的时候就是为了方便的管理精灵,创建一个node节点,然后将精灵放到这个节点中,而node本身是没法显示出来的,显示出来的东西是放到它里边的node子节点,node的长和宽都是0,坐标默认是在父节点的左下角也就是原点处。所以对子节点位置的设置不会产生影响。CCSpriteBatchNode就是这样的一个node,不同的是创建的时候需要一个纹理,要不怎么叫sprite node呢?里边传入的纹理图片是子节点用到的纹理图片,我们可以设置好这些子精灵节点的坐标,然后添加到这个node中,这个node再添加到其他的层中,这样就可以批次渲染了。这个node要求它的字精灵节点和它使用相同的纹理,那如果纹理不一样怎么办,那就把纹理都打包到一张图片上,用的时候从这张图片上截取,工具可以使用texturepacker。

?


1

2

3

4

5

6

7

8

9

CCTexture2D * texture = CCTextureCache::sharedTextureCache()->addImage("fire.png");

    for(int i=0;i<10;i++)

    {

        //CCParticleSun里边没有参数

        CCParticleSystem * particle = CCParticleSun::create();

        particle->setTexture(texture);

        particle->setPosition(ccp(CCRANDOM_0_1()*visibleSize.width,CCRANDOM_0_1()*visibleSize.height));

        this->addChild(particle);

    }

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

CCTexture2D * texture = CCTextureCache::sharedTextureCache()->addImage("fire.png");

    //参数同样需要一张纹理图片

    CCParticleBatchNode * particleBatch = CCParticleBatchNode::createWithTexture(texture);

    //也可以采用如下的方式创建

    //CCParticleBatchNode * particleBatch = CCParticleBatchNode::create("fire.png");

    for(int i=0;i<10;i++)

    {

        //CCParticleSun里边没有参数

        CCParticleSystem * particle = CCParticleSun::create();

        //传入的texture必须和CCParticleBatchNode相同

        particle->setTexture(texture);

        particle->setPosition(ccp(CCRANDOM_0_1()*visibleSize.width,CCRANDOM_0_1()*visibleSize.height));

        particleBatch->addChild(particle);

    }

    this->addChild(particleBatch);

这里的道理是和CCSpriteBatchNode相同的,就不用解释了吧。
2、使用缓存提前加载精灵。当我们使用纹理的时候可以制作一个loading界面,将将要用到的纹理加载到缓存中,同时将它们的引用计数增加一,以便这些纹理不会被释放。用的时候直接从缓存中取就可以了,这样也可以提高效率。我们用到的缓存类有CCTextureCache、CCSpriteFrameCache、CCAnimationCache,下面分别说明其用法。

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

bool HelloWorld::init()

{

    //////////////////////////////

    // 1. super init first

    if ( !CCLayer::init() )

    {

        return false;

    }

    CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();

    //缓存其实就是一个数组,把用到的纹理图片放到这个数组中,纹理的引用计数加1,这样的话就不会释放纹理图片了

    //等下一次使用的时候直接从这个数组中取就可以了,这样的话就不必再次加载到内存中了

    CCTexture2D * texture = CCTextureCache::sharedTextureCache()->addImage("icon.png");

    CCLog("%d",texture->retainCount()); //count=1

    //使用如下俩种方法可以获得缓存中的纹理,第二种方法如果之前已经加载了纹理,这个时候不会重新加载

    //而是直接返回

    texture = CCTextureCache::sharedTextureCache()->addImage("icon.png");

    texture = CCTextureCache::sharedTextureCache()->textureForKey("icon.png");

    CCLog("%d",texture->retainCount()); //count=1

    //异步加载图片,开辟一个新的线程专门用来加载图片,加载完毕以后调用loadingCallBack函数

    //所以在这个init函数中是不应该去调用函数textureForKey的,因为你不知道是否加载好了纹理啊

    CCTextureCache::sharedTextureCache()->addImageAsync("icon1.png",

        this,callfuncO_selector(HelloWorld::loadingCallBack));

    return true;

}

//object就是加载好了的纹理

void HelloWorld::loadingCallBack(CCObject * object)

{

    CCTexture2D * texture = (CCTexture2D *)object;

    CCLog("%d",texture->retainCount()); //count=2

    //通过以下的方法取得的texture和上边的那个texture相同

    //CCTexture2D * texture2 = CCTextureCache::sharedTextureCache()->textureForKey("icon1.png");

    //CCLog("%d",texture2->retainCount());

    //会清除掉所有的纹理,在其他的地方不可以再引用这些纹理了

    CCTextureCache::sharedTextureCache()->removeAllTextures();

    //以下的方法会remove掉count值为1的纹理,icon.png被remove掉了,个人认为实际用的时候就用这个

    //CCTextureCache::sharedTextureCache()->removeUnusedTextures();

    //count=1

    CCLog("%d",texture->retainCount());

    //查看纹理清除的信息

    CCTextureCache::sharedTextureCache()->dumpCachedTextureInfo();

    //切换场景

    CCDirector::sharedDirector()->replaceScene(TestScene::scene());

}

在新的场景中使用加载好的纹理。

?


1

2

3

4

5

6

7

8

bool TestScene::init()

{

    //因为将所有的纹理清除掉了,所以这里引用的时候会出错

    CCTexture2D * texture = CCTextureCache::sharedTextureCache()->textureForKey("icon1.png");

    CCLog("%d",texture->retainCount());

    return true;

}

CCTextureCache在我看来就是一个数组,将加载的纹理都放到这个数组中,然后将它们的引用计数加1以防释放掉,我们要使用加载好的纹理直接从这个数组中取就可以了,返回一个CCTexture2D的对象,然后我们使用CCSprite:createWithTexture这个方法来创建出精灵。我觉的这里最主要的问题就是纹理的释放,个人认为使用removeUnusedTexture这个函数比较好,它会释放掉引用计数为1的纹理,也就说明程序中没有再为它增加引用计数,肯定是没用了。那些大于1的纹理不会释放掉,即使我们在不知道的情况下再次加载,也只是返回已经加载好了的。接下来是另外俩个缓存了,和这个意思差不多,直接看代码吧。

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

bool HelloWorld::init()

{

    //////////////////////////////

    // 1. super init first

    if ( !CCLayer::init() )

    {

        return false;

    }

    CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();

    //可以使用texturepacker生成.plist文件,将plist文件和png文件放到资源目录下,通过add方法将ghosts.plist纹理

    //加载到了缓存中

    CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("ghosts.plist");

    //spriteFrameByName中传入的参数可以到.plist文件中查看,通过这个方法可以从缓存中获得一个精灵帧

    CCSpriteFrame * spriteFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("child1.gif");

    CCLog("%d",spriteFrame->retainCount()); //count=1

    //之所以创建精灵帧就是为了播放动画做准备的,这里可以是一个循环不到的创建精灵帧然后添加到animation中

    //关于这部分的内容可以查看我前边的文章,这里是为了说明缓存的使用

    CCAnimation * animation = CCAnimation::create();

    animation->addSpriteFrame(spriteFrame);

    CCLog("%d",spriteFrame->retainCount()); //count=2

    CCLog("%d",animation->retainCount()); //count=1,这个1是创建时候的引用计数

    //动画缓存,将animation放到缓存中,里边存入一个key,方便以后取出,如果不把动画放到这个缓存中,下一帧的时候

    //动画就会被释放掉的,再播放动画就会出错了

    CCAnimationCache::sharedAnimationCache()->addAnimation(animation,"a"); //count=2

    CCLog("%d",animation->retainCount());

    CCAnimate * animate = CCAnimate::create(CCAnimationCache::sharedAnimationCache()->animationByName("a"));

    //当不再需要播放动画的时候从动画缓存中清除,应该先清除动画再清除精灵帧

    CCAnimationCache::sharedAnimationCache()->removeAnimationByName("a");

    //将引用计数为1的精灵帧从缓存中清除

    CCSpriteFrameCache::sharedSpriteFrameCache()->removeUnusedSpriteFrames();

    //释放掉所有的精灵帧

    //CCSpriteFrameCache::sharedSpriteFrameCache()->removeSpriteFrames();

    return true;

}

原文转载:http://www.zaojiahua.com/optimization.html皂荚花

精灵的优化

时间: 2024-10-03 18:59:10

精灵的优化的相关文章

0428数字口袋精灵app优化

"数字口袋精灵app"优化 目录: 一.项目github总仓库推送 二.开发成员 三.分工与合作 四.各模块成果 五.团队成员贡献分 内容: 一.项目github总仓库: https://github.com/LiangZhilin/We-have-bing 二.开发人员: 223孙海林(商软2班) 225江志彬(商软2班) 256林集团(商软2班) 224颜文生(商软2班) 404曹嘉琪(商软1班) 142梁植淋(商软1班) 三.分工与合作: 林集团.颜文生:从开发者的角度出发,进一

精灵的优化-使用纹理图集

游戏是一种很耗费资源的应用,特别是在移动设备中的游戏,性能优化是非常重要的 纹理图集(Texture Atlas)也称为精灵表(Sprite Sheet),它是把许多小的精灵图片组合到一张大图里面.使用纹理图集(或精灵表)有如下主要优点: 减少文件读取次数,读取一张图片比读取一堆小文件要快. 减少OpenGL ES绘制调用并且加速渲染. 减少内存消耗.OpenGL ES 1.1仅仅能够使用2的n次幂大小的图片(即宽度或者高度是2.4.8.64...).如果采用小图片OpenGL ES1.1会分配

Cocos2dx对精灵的优化

cocos2dx针对游戏设计的不同方面会有不同的优化方案,可以对声音,对内存,对图片格式,对色彩等等进行优化.有关这些方面的方法请大家查找其他的文章.我今天要说的是如何对精灵进行优化,程序中我们用到的最多的就是精灵,大到背景.UI,小到 NPC.道具,只要是用图片展示的,都是精灵或它的子类.精灵是什么,在我看来精灵就是一张纹理图片,是按某种方式显示出来的图片.精灵如此的重要,我们当然要好好的优化优化了.我们可以减小精灵图片的大小,使用缓存Cache的方法将精灵提前加载到内存中,当有很多精灵的时候

2015-03-18

今天继续看了一些数据结构,还是二叉树,不过看的不深,因为这个东西要想搞深了一定要自己搞,切忌心浮气躁,自己只能慢慢的研究.已经也算是入门了,关于递归,树,图,8大排序,自己慢慢的实现吧. 今天主要看了cocos2dx,包括锚点,精灵,zorder的概念,坐标体系的概念,关于精灵的优化. 首先说锚点,锚点不是中心点,锚点默认是中心点,但是这个点我们可以设,就相当于当前的对象以哪个点为基准的点,我们还可以忽略锚点. 1.锚点影响放置位置 2.影响缩放 3.影响旋转 方法:sprite->setAnc

Cocos2d-x v3.9发布

近日, Cocos引擎完成重大更新:发布了Cocos 2d-x v3.9版本.据悉,Cocos 2d-x v3.9版本补全了3D功能,大大提升了画面表现力:同时在更稳定的2D功能基础上,强化了2D功能的易用性,让代码更为优雅.该版本进一步完善并整合了历史零碎功能,为开发者创造更为简单.快捷的开发环境. Cocos 3D功能日益完善 (Cocos引擎打造的拖尾效果) 此次Cocos 2d-x v3.9新增3D MotionStreak功能,支持拖尾效果. 在游戏的实现过程中,开发者有时会需要在某个

cocos2dx SpriteBatchNode 精灵的渲染优化类

用处是减少对精灵的渲染次数,用法如下 1 SpriteFrameCache::getInstance()->addSpriteFramesWithFile("person.plist"); 2 SpriteBatchNode *node = SpriteBatchNode::create("person.png"); 3 bg->addChild(node); 4 5 SpriteFrame *frame = SpriteFrameCache::getI

前端优化

代码层面:避免使用css表达式,避免使用高级选择器,通配选择器. 缓存利用:缓存Ajax,使用CDN,使用外部js和css文件以便缓存,添加Expires头,服务端配置Etag,减少DNS查找等 请求数量:合并样式和脚本,使用css图片精灵(sprite),初始首屏之外的图片资源按需加载,静态资源延迟加载(懒加载). 请求带宽:压缩文件,开启GZIP, 代码层面的优化 用 hash-table 来优化查找 少用全局变量 用 innerHTML 代替 DOM 操作,减少 DOM 操作次数,优化 j

web前端性能优化

前言:  在同样的网络环境下,两个同样能满足你的需求的网站,一个“Duang”的一下就加载出来了,一个纠结了半天才出来,你会选择哪个?研究表明:用户最满意的打开网页时间是2-5秒,如果等待超过10秒,99%的用户会关闭这个网页.也许这样讲,各位还不会有太多感触,接下来我列举一组数据:Google网站访问速度每慢400ms就导致用户搜索请 求下降0.59%;Amazon每增加100ms网站延迟将导致收入下降1%;雅虎如果有400ms延迟会导致流量下降5-9%.网站的加载速度严重影响了用户体验,也决

Cocos2d-x优化中图片优化

在2D游戏中图片无疑是最为重要的资源文件,它会被加载到内存中转换为纹理,由GPU贴在精灵之上渲染出来.它能够优化的方面很多,包括:图片格式.拼图和纹理格式等,下面我们从这几个方面介绍一下图片和纹理的优化.1.选择图片格式要回答这个问题,我们需要先了解一下目前在移动平台所使用的图片文件格式,以及这些图片格式Cocos2d-x是否支持.图片格式有很多,但是在移动平台主要推荐使用的PNG,JPG也可以考虑,而其它的文件格式最好转化成为PNG格式.我们先了解一下它们的特点.1.PNG文件PNG文件格式设