1. cocos2d-x播放帧动画需要图片帧集合的描述,以及动画的描述,前者可以直接通过flash自带的插件导出,如图所示
后者可以自己写一个脚本cocos2dxAni.jsfl,放置于形如C:\Program Files (x86)\Adobe\Adobe Flash CS6\Common\Configuration\Sprite Sheet Plugins 的目录下
// cocos2dxAni.jsfl // export Cocos2d ani plist // Ruoqian, Chen<[email protected]> 2013.9.22. function getPluginInfo(lang) { // fl.trace("==== getPluginInfo"); // fl.trace(lang); // fl.trace("---- getPluginInfo"); pluginInfo = new Object(); pluginInfo.id = "cocos2dxAni"; pluginInfo.name = "cocos2dx Ani"; pluginInfo.ext = "plist"; pluginInfo.encoding = "UTF8"; pluginInfo.capabilities = new Object(); pluginInfo.capabilities.canRotate = true; pluginInfo.capabilities.canTrim = true; pluginInfo.capabilities.premultipliedAlpha = true; pluginInfo.capabilities.canShapePad = true; pluginInfo.capabilities.canBorderPad = true; pluginInfo.capabilities.canStackDuplicateFrames = true; return pluginInfo; } function beginExport(meta) { // fl.trace("==== endExport"); // fl.trace(meta.app); // fl.trace(meta.version); // fl.trace(meta.image); // fl.trace(meta.format); // fl.trace(meta.size.w); // fl.trace(meta.size.h); // fl.trace(meta.scale); // fl.trace("---- endExport"); var s = '<?xml version="1.0" encoding="UTF-8"?>\n'; s += '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'; s += '<plist version="1.0">\n'; s += '<dict>\n'; s += '\t<key>animations</key>\n'; s += '\t<dict>\n'; var fname = meta.image; var ndx = meta.image.lastIndexOf('.'); if (ndx > 0) { fname = meta.image.substr(0, ndx); } s += '\t\t<key>' + fname + '</key>\n'; s += '\t\t<dict>\n'; s += '\t\t\t<key>delay</key>\n'; s += '\t\t\t<real>0.04</real>\n'; s += '\t\t\t<key>frames</key>\n'; s += '\t\t\t<array>\n'; return s; } function frameExport(frame) { // fl.trace("==== frameExport"); // fl.trace(frame.id); // fl.trace(frame.frame.x); // fl.trace(frame.frame.y); // fl.trace(frame.frame.w); // fl.trace(frame.frame.h); // fl.trace(frame.offsetInSource.x); // fl.trace(frame.offsetInSource.y); // fl.trace(frame.sourceSize.w); // fl.trace(frame.sourceSize.h); // fl.trace(frame.rotated); // fl.trace(frame.trimmed); // fl.trace(frame.frameNumber); // fl.trace(frame.symbolName); // fl.trace(frame.frameLabel); // fl.trace(frame.lastFrameLabel); // fl.trace("---- frameExport"); var s ='\t\t\t\t<string>' + frame.id + '</string>\n'; return s; } function endExport(meta) { // fl.trace("==== endExport"); // fl.trace(meta.app); // fl.trace(meta.version); // fl.trace(meta.image); // fl.trace(meta.format); // fl.trace(meta.size.w); // fl.trace(meta.size.h); // fl.trace(meta.scale); // fl.trace("---- endExport"); var s = '\t\t\t</array>\n'; s += '\t\t</dict>\n'; s += '\t</dict>\n'; s += '</dict>\n'; s += '</plist>\n'; return s; }
2. 得到两个plist文件以后,很方便的就可以得到动画Node
// MyFlashNode.h // Ruoqian, Chen<[email protected]> // demo version 2013.10.16 #pragma once #include "cocos2d.h" USING_NS_CC; class CMyFlashNode : public CCSprite { public: static CMyFlashNode* create(const char *pszName, int nRepeat = 1, int nDelay_ms = 0); virtual ~CMyFlashNode(void); };
// MyFlashNode.cpp // Ruoqian, Chen<[email protected]> // demo version 2013.10.16 #include "MyFlashNode.h" CMyFlashNode::~CMyFlashNode(void) { } CMyFlashNode* CMyFlashNode::create( const char *pszName, int nRepeat /*= 1*/, int nDelay_ms /*= 0*/ ) { CMyFlashNode* pSpriteAni = new CMyFlashNode; pSpriteAni->autorelease(); pSpriteAni->init(); std::string strName = pszName; std::string strPlist = strName + ".plist"; CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile(strPlist.c_str()); std::string strPlistAni = strName + "_ani.plist"; CCAnimationCache::sharedAnimationCache()->addAnimationsWithFile(strPlistAni.c_str()); std::string strAni = strName + "_ani"; CCAnimation* pAni = CCAnimationCache::sharedAnimationCache()->animationByName(strAni.c_str()); std::string strFrame = strName + "0000"; CCSpriteFrame *pFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(strFrame.c_str()); pSpriteAni->setDisplayFrame(pFrame); CCFiniteTimeAction* pActionWithRepeat = NULL; switch (nRepeat) { case 1: pActionWithRepeat = CCAnimate::create(pAni); break; case -1: //pActionWithRepeat = CCRepeatForever::create(CCAnimate::create(pAni)); pActionWithRepeat = CCRepeat::create(CCAnimate::create(pAni), UINT32_MAX); break; default: pActionWithRepeat = CCRepeat::create(CCAnimate::create(pAni), nRepeat); break; } CCSequence* pActionSeq = NULL; float fDelay = nDelay_ms / 1000.0f; CCCallFunc* pFuncAutoRemove = CCCallFunc::create(pSpriteAni, callfunc_selector(CCNode::removeFromParent)); if (fDelay > 0) { pSpriteAni->setVisible(false); pActionSeq = CCSequence::create(CCDelayTime::create(fDelay), CCShow::create(), pActionWithRepeat, pFuncAutoRemove, NULL); } else { pActionSeq = CCSequence::create(pActionWithRepeat, pFuncAutoRemove, NULL); } pSpriteAni->runAction(pActionSeq); return pSpriteAni; }
3. 实际调用也很简单,直接add即可
CMyFlashNode* pFlashNode = CMyFlashNode::create("star", 5, 3000);
this->setPosition(ptCenter);
this->addChild(pFlashNode);
由于支持配置循环播放次数和延时,且播放完成时候会自动释放,基本满足大部分情况的需要了。需要无限循环的话,repeat参数填写-1即可
因为是做示例,所以简单写了下,实际在项目中,我写成了一整套可配置形式的ui_element管理,会更灵活,以后有机会整理下再发上来。