TexturePacker打包图片并使用addImageAsync实现longding界面异步加载图片纹理---cocos2d-x学习之路

TexturePacker 小图打包大图必备。

为什么要把小图打包成大图?

减少内存消耗,提高绘制效率。与openGL的纹理加载特性和绘制特性有关系。具体可以自行百度,网上介绍的很多。

TexturePacker 工具下载链接 http://www.codeandweb.com/texturepacker

注意 TexturePacker 不是免费的 如果你也有自己的技术博客,可以在官网页面申请一个免费的key 

我申请到了一个免费的key,作为回报就有了这篇博客。


欢迎转载  请注明出处 http://blog.csdn.net/yangjie314/article/details/23709243


废话不多,简单介绍一下工具的使用,重点实现异步加载纹理。

具体参数不需要过多设置,如图中所示。直接拖拽多个图片或者装有多个图片的文件夹到图中标记区域


like this: 然后点击Publish


选择路径,然后就生成完毕了。


注意:生成两个文件 一个是合成的大图.png 一个是用来描述大图中小图位置大小的参数配置文件.plist


下面介绍 如何在游戏中加载大图纹理并将大图纹理解析到CCSpriteFrameCache(精灵帧缓存),然后使用小图 --》helloWorld场景

如何在游戏中使用loading界面异步加载多个大图纹理并解析到CCSpriteFrameCache(精灵帧缓存) 同时更新loading进度条 --》AsyncLoadingScene场景

游戏中的资源 如图


demo 环境为cocos2d-x 2.2.2 嗯嗯..3个2

demo代码 共三个场景 HelloWorldScene AsyncLoadingSceneGameScene对应 logo-》loading-》game

HelloWorldScene.h

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #ifndef __HELLOWORLD_SCENE_H__  
  2. #define __HELLOWORLD_SCENE_H__  
  3.   
  4. #include "cocos2d.h"  
  5.   
  6. USING_NS_CC;  
  7. //要加载的大图纹理 png 图片的文件名  
  8. const static char fileName[] = "texturePacker_%d.png";  
  9. //解释要加载的大图纹理 png 图片的 plist文件名  
  10. const static char plistName[] = "texturePacker_%d.plist";  
  11.   
  12. //helloWorld 里使用的大图文件名 index  
  13. const static int testfileNameIndex = 0;  
  14.   
  15. //整个需要加载的大图的数量  
  16. const static int fileNum = 3;  
  17.   
  18.   
  19. class HelloWorld : public cocos2d::CCLayer  
  20. {  
  21. public:  
  22.      
  23.     virtual bool init();    
  24.   
  25.   
  26.     static cocos2d::CCScene* scene();  
  27.       
  28.     // a selector callback  
  29.     void menuCloseCallback(CCObject* pSender);  
  30.   
  31.     CREATE_FUNC(HelloWorld);  
  32.   
  33.     //跳转到loadingScene的回调函数  
  34.     void toLoadingScene(float dt);  
  35.   
  36.     //这里释放纹理  
  37.     virtual void onExit();  
  38.   
  39. };  
  40.   
  41. #endif // __HELLOWORLD_SCENE_H__  
HelloWorldScene.cpp

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include "HelloWorldScene.h"  
  2. #include "AsyncLoadingScene.h"  
  3.   
  4.   
  5. CCScene* HelloWorld::scene()  
  6. {  
  7.     // 'scene' is an autorelease object  
  8.     CCScene *scene = CCScene::create();  
  9.       
  10.     // 'layer' is an autorelease object  
  11.     HelloWorld *layer = HelloWorld::create();  
  12.   
  13.     // add layer as a child to scene  
  14.     scene->addChild(layer);  
  15.   
  16.     // return the scene  
  17.     return scene;  
  18. }  
  19.   
  20. // on "init" you need to initialize your instance  
  21. bool HelloWorld::init()  
  22. {  
  23.     //  
  24.     // 1. super init first  
  25.     if ( !CCLayer::init() )  
  26.     {  
  27.         return false;  
  28.     }  
  29.       
  30.     CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();  
  31.     CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();  
  32.   
  33.     CCMenuItemImage *pCloseItem = CCMenuItemImage::create(  
  34.                                         "CloseNormal.png",  
  35.                                         "CloseSelected.png",  
  36.                                         this,  
  37.                                         menu_selector(HelloWorld::menuCloseCallback));  
  38.       
  39.     pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/2 ,  
  40.                                 origin.y + pCloseItem->getContentSize().height/2));  
  41.   
  42.   
  43.     CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);  
  44.     pMenu->setPosition(CCPointZero);  
  45.     this->addChild(pMenu, 1);  
  46.   
  47.       
  48.     CCLabelTTF* pLabel = CCLabelTTF::create("TexturePacker Test""Arial", 30);  
  49.     pLabel->setPosition(ccp(origin.x + visibleSize.width/2,  
  50.                             origin.y + visibleSize.height - pLabel->getContentSize().height));  
  51.     this->addChild(pLabel, 1);  
  52.   
  53.       
  54.     //加载纹理 使用纹理缓存单例 加载  
  55.     CCTexture2D* texture =   
  56.         CCTextureCache::sharedTextureCache()->addImage(  
  57.         CCString::createWithFormat(fileName,testfileNameIndex)->getCString()  
  58.         );  
  59.   
  60.     //将纹理分解为原始小图 缓存到精灵帧缓存  
  61.     CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile(  
  62.         CCString::createWithFormat(plistName,testfileNameIndex)->getCString(),texture  
  63.         );  
  64.   
  65.     //跳转到loading页面  
  66.     scheduleOnce(schedule_selector(HelloWorld::toLoadingScene),2.0f);  
  67.       
  68.       
  69.     //可以使用两种方式来生成精灵  都是通过加载到精灵帧缓存中的纹理获得的  
  70.   
  71.     //直接使用图片文件名  
  72.     CCSprite* girl_6 = CCSprite::createWithSpriteFrameName("girl_6.jpg");  
  73.   
  74.     //使用精灵帧生成精灵  
  75.     //获得精灵帧  
  76.     CCSpriteFrame* frame_3 = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("girl_3.jpg");  
  77.     CCSprite* girl_3 = CCSprite::createWithSpriteFrame(frame_3);  
  78.       
  79.     girl_3->setPosition(ccp(300,visibleSize.height/2));  
  80.     girl_6->setPosition(ccp(600,visibleSize.height/2));  
  81.       
  82.   
  83.     this->addChild(girl_3);  
  84.     this->addChild(girl_6);  
  85.   
  86.       
  87.     return true;  
  88. }  
  89.   
  90. void HelloWorld::toLoadingScene(float dt){  
  91.   
  92.     CCScene* scene = AsyncLoadingScene::scene();  
  93.   
  94.     CCDirector::sharedDirector()->replaceScene(scene);  
  95.   
  96. }  
  97.   
  98. void HelloWorld::onExit(){  
  99.     CCLog("HelloWorld::onExit");  
  100.   
  101.     CCLayer::onExit();  
  102.   
  103.     //释放注意顺序 先释放精灵帧缓存  再释放纹理  
  104.     //释放精灵帧缓存   
  105.     CCSpriteFrameCache::sharedSpriteFrameCache()->removeSpriteFramesFromFile(  
  106.         CCString::createWithFormat(plistName,testfileNameIndex)->getCString()  
  107.         );  
  108.     //释放纹理缓存  
  109.     CCTextureCache::sharedTextureCache()->removeTextureForKey(  
  110.         CCString::createWithFormat(fileName,testfileNameIndex)->getCString()  
  111.         );  
  112.   
  113. }  
  114.   
  115. void HelloWorld::menuCloseCallback(CCObject* pSender)  
  116. {  
  117.       
  118. #if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)  
  119.     CCMessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");  
  120. #else  
  121.     CCDirector::sharedDirector()->end();  
  122. #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)  
  123.     exit(0);  
  124. #endif  
  125. #endif  
  126. }  
AsyncLoadingScene.h

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #ifndef _ASYNC_LOADING_SCENE_H_  
  2. #define _ASYNC_LOADING_SCENE_H_  
  3.   
  4. #include "cocos2d.h"  
  5.   
  6. USING_NS_CC;  
  7. /** 
  8.     加载多张texturePacker生成的大图,可能会造成卡顿,所以使用异步加载纹理 
  9.     cocos2d-x 自己维护一个线程来加载资源 无需过多操作 方便 省事! 
  10.     加载到内存的纹理在不使用的情况下注意释放! 
  11.  
  12. */  
  13.   
  14. //进度条每次移动的时间  
  15. const static float s_progressAddTime = 2.0f;  
  16.   
  17. class AsyncLoadingScene : public CCLayer  
  18. {  
  19. public:  
  20.     virtual bool init();  
  21.     virtual void onEnter();  
  22.     static CCScene* scene();  
  23.     CREATE_FUNC(AsyncLoadingScene);  
  24.   
  25.     //异步加载完一张纹理的回调函数  
  26.     void AsyncLoadingCallback(CCObject* pSender);  
  27.   
  28.     //进度条  
  29.     CCProgressTimer* progress;  
  30.     //当前加载的第几个纹理  
  31.     int loadingIndex;  
  32.     //加载进度  
  33.     int i_progress;  
  34.     //加载一个纹理进度的增加值  
  35.     int i_progressAddValue;  
  36.   
  37.     //加载结束的回调 控制跳转  
  38.     void loadingOverCallback();  
  39.   
  40. };  
  41.   
  42.   
  43.   
  44.   
  45. #endif//_ASYNC_LOADING_SCENE_H_  

AsyncLoadingScene.cpp

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include "AsyncLoadingScene.h"  
  2. #include "HelloWorldScene.h"  
  3. #include "GameScene.h"  
  4.   
  5.   
  6.   
  7. CCScene* AsyncLoadingScene::scene(){  
  8.     CCScene* scene = CCScene::create();  
  9.     AsyncLoadingScene* layer = AsyncLoadingScene::create();  
  10.     scene->addChild(layer);  
  11.   
  12.     return scene;  
  13. }  
  14. bool AsyncLoadingScene::init(){  
  15.     if (!CCLayer::init())  
  16.     {  
  17.         return false;  
  18.     }  
  19.     CCLog("AsyncLoadingScene::init");  
  20.     CCSize size = CCDirector::sharedDirector()->getWinSize();  
  21.   
  22.     //进度条背景图片  
  23.     CCSprite* progressBgd = CCSprite::create("progress.png");  
  24.     //设置成灰色  
  25.     progressBgd->setColor(ccGRAY);  
  26.     //设置统一的坐标  
  27.     CCPoint progressPosition = ccp(size.width/2,size.height/4);  
  28.   
  29.     progressBgd->setPosition(progressPosition);  
  30.   
  31.     this->addChild(progressBgd);   
  32.   
  33.     //进度条  
  34.     //通过精灵生成  
  35.     progress = CCProgressTimer::create(CCSprite::createWithTexture(progressBgd->getTexture()));  
  36.     //设置纵向  
  37.     progress->setType(kCCProgressTimerTypeBar);  
  38.     //设置从左边开始还是从右边开始  
  39.     progress->setMidpoint(ccp(0,0));  
  40.     //不懂是干嘛的  
  41.     progress->setBarChangeRate(ccp(1,0));//  
  42.   
  43.     progress->setPosition(progressPosition);  
  44.   
  45.     //progress->setPercentage(0);//设置初始进度  
  46.   
  47.     this->addChild(progress,1);   
  48.   
  49.     //进度条的更新 放到异步加载资源回调中  
  50.   
  51.     //加载回调中 控制解析plist  
  52.     i_progress= 0;  
  53.     loadingIndex = 0;  
  54.     i_progressAddValue = 100/fileNum;  
  55.   
  56.   
  57.   
  58.     //为了验证异步加载不会对游戏主线程造成卡顿 弄30个精灵让他们执行无限循环上下抽搐动作   
  59.     for (int i = 0; i < 30; i++)  
  60.     {  
  61.         CCSprite* sp = CCSprite::create("sp9.png");  
  62.         CCPoint spPos = ccp(30*i+30,size.height/2+i*5);  
  63.         sp->setPosition(spPos);  
  64.         this->addChild(sp);  
  65.   
  66.       
  67.         CCMoveBy* moveBy1 = CCMoveBy::create(0.1f,ccp(0,100));  
  68.   
  69.         //CCReverseTime  反动作,谨慎使用 多适用于 XXXBy 而不是 XXXTo  
  70.         //CCReverseTime* reverse = CCReverseTime::create(moveBy1);  
  71.         CCMoveBy* moveBy2 = CCMoveBy::create(0.1f,ccp(0,-100));  
  72.           
  73.         CCSequence* seq = CCSequence::create(moveBy1,moveBy2,NULL);  
  74.   
  75.         CCRepeatForever* forever = CCRepeatForever::create(seq);  
  76.   
  77.         sp->runAction(forever);  
  78.   
  79.     }  
  80.   
  81.   
  82.     return true;  
  83. }  
  84. void AsyncLoadingScene::onEnter(){  
  85.     CCLog("AsyncLoadingScene::onEnter");  
  86.     CCLayer::onEnter();  
  87.       
  88.     for (int i = 0; i < fileNum; i++)  
  89.     {  
  90.         //异步加载    最后参数为 异步加载完成后回调的函数 传递的CCObjcet 为加载完成后的纹理  
  91.         CCTextureCache::sharedTextureCache()->addImageAsync(  
  92.             CCString::createWithFormat(fileName,i)->getCString(),  
  93.             this,  
  94.             callfuncO_selector(AsyncLoadingScene::AsyncLoadingCallback)  
  95.             );  
  96.     }  
  97.       
  98. }  
  99.   
  100.   
  101. //异步加载回调函数  
  102. void AsyncLoadingScene::AsyncLoadingCallback(CCObject* pSender){  
  103.   
  104.     //传递的CCObjcet 为加载完成后的纹理  
  105.     CCTexture2D* texture = dynamic_cast<CCTexture2D*>(pSender);  
  106.   
  107.     //解析加载的纹理到 精灵帧缓存  
  108.     CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile(  
  109.         CCString::createWithFormat(plistName,loadingIndex)->getCString(),  
  110.         texture  
  111.         );  
  112.       
  113.     //加载完最后一个 loading 结束 进度条绘制完毕后 跳转到切屏  
  114.     if (loadingIndex == fileNum-1)  
  115.     {  
  116.         //停止动作  
  117.         progress->stopAllActions();  
  118.         //进度直接设置为100  
  119.         i_progress = 100;  
  120.         //进度条增加动作  
  121.         CCProgressTo* to = CCProgressTo::create(s_progressAddTime, i_progress);  
  122.   
  123.         CCSequence* seq = CCSequence::create(  
  124.             to,  
  125.             //纹理加载完毕->纹理解析完毕->进度条动作执行完毕->跳转到游戏页面  
  126.             CCCallFunc::create(this,callfunc_selector(AsyncLoadingScene::loadingOverCallback)),  
  127.             NULL);  
  128.   
  129.         progress->runAction(seq);  
  130.           
  131.         //progress->setPercentage(i_progress);  
  132.         //loadingOverCallback();  
  133.     }else  
  134.     {  
  135.         //停止动作  
  136.         progress->stopAllActions();  
  137.         //增加进度条进度  
  138.         i_progress += i_progressAddValue;  
  139.           
  140.         //进度条增加动作  
  141.         CCProgressTo* to = CCProgressTo::create(s_progressAddTime, i_progress);  
  142.         progress->runAction(to);  
  143.           
  144.         //progress->setPercentage(i_progress);  
  145.         //尼玛写注释好累啊.. 这是干嘛来着..  
  146.         loadingIndex++;  
  147.     }  
  148.       
  149. }  
  150. void AsyncLoadingScene::loadingOverCallback(){  
  151.     CCLog("AsyncLoadingScene::loadingOverCallback");  
  152.   
  153.     CCScene* scene = GameScene::scene();  
  154.     CCDirector::sharedDirector()->replaceScene(scene);  
  155.   
  156. }  

GameScene.h

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #ifndef _GAME_SCENE_H_  
  2. #define _GAME_SCENE_H_  
  3.   
  4. #include "cocos2d.h"  
  5. USING_NS_CC;  
  6. class GameScene:public CCLayer  
  7. {  
  8. public:  
  9.     virtual bool init();  
  10.     static CCScene* scene();  
  11.     CREATE_FUNC(GameScene);  
  12.   
  13.   
  14.   
  15. };  
  16.   
  17. #endif  //_GAME_SCENE_H_  

GameScene.cpp

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include "GameScene.h"  
  2.   
  3.   
  4. CCScene* GameScene::scene(){  
  5.     CCScene* scene = CCScene::create();  
  6.   
  7.     GameScene* layer  = GameScene::create();  
  8.   
  9.     scene->addChild(layer);  
  10.     return scene;  
  11. }  
  12. bool GameScene::init(){  
  13.     if (!CCLayer::init())  
  14.     {  
  15.         return  false;  
  16.     }  
  17.       
  18.   
  19.   
  20.     const static char imageName[] = "neck_%d.jpg";  
  21.   
  22.     int index = 1;  
  23.     for (int i = 1; i <= 2; i++)  
  24.     {  
  25.         for (int j = 1; j <= 5; j++)  
  26.         {  
  27.             CCSprite* temp = CCSprite::createWithSpriteFrameName(CCString::createWithFormat(imageName,index)->getCString());  
  28.             temp->setPosition(ccp(200*j-50,200*i+150));  
  29.             this->addChild(temp);  
  30.             index++;  
  31.         }  
  32.     }  
  33.   
  34.   
  35.   
  36.     return true;  
  37. }  

大概就是这个样子..嗯

最后在GameScene读取纹理 绘制出来 下面这个样子



大家发现有什么不对的地方 欢迎留言 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值