生活随笔
收集整理的這篇文章主要介紹了
【玩转cocos2d-x之三十七】粒子系统的加载优化
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Cocos2d-x的粒子系統(tǒng)是通過加載plist生成的。plist包含兩部分內(nèi)容:粒子系統(tǒng)屬性和粒子紋理。然而每次調(diào)用create都會(huì)對(duì)plist進(jìn)行讀取解析,如果重復(fù)地使用同一個(gè)粒子效果,這樣的調(diào)用明顯是低效冗余的。所以我們要做的是,將粒子系統(tǒng)屬性和粒子紋理分別抽出。
(1)將粒子系統(tǒng)屬性預(yù)加載并全局保存,避免每次進(jìn)行讀取。
(2)粒子紋理可視且可以進(jìn)行紋理打包,加載粒子紋理就和加載普通的圖片一樣。
本文通過增加ParticleSystemQuad的接口實(shí)現(xiàn)對(duì)粒子系統(tǒng)屬性和紋理幀的直接載入,來提高粒子系統(tǒng)的加載效率和實(shí)現(xiàn)內(nèi)存紋理的優(yōu)化。
1.ParticleSystemQuad
首先先看下ParticleSystemQuad,ParticleSystemQuad繼承于ParticleSystem,擁有后者的所有特性,并且增加了一些新的特性:
(1)粒子大小支持浮點(diǎn)數(shù)
(2)支持縮放
(3)支持選擇
(4)支持subrect
(5)支持批渲染
ParticleSystemQuad同時(shí)也是其他特效的父類,創(chuàng)建一個(gè)粒子系統(tǒng)的函數(shù)調(diào)用順序?yàn)?#xff1a;
[cpp]?view plaincopy
Create→initWithFile→initWithDictionary??
在initWithDictionary中對(duì)粒子數(shù)據(jù)和紋理進(jìn)行了讀取和解析(這部分有興趣的可以直接看源碼)。
2.如何優(yōu)化?
參考initWithDictionary的函參
[cpp]?view plaincopy
static?bool?initWithDictionary(ValueMap&?dictionary,?const?std::string&?dirname);??
設(shè)計(jì)如下接口,當(dāng)然你要傳入文件名也可以:
[cpp]?view plaincopy
static?ParticleSystemQuad?*?create(ValueMap&?valueMap,?SpriteFrame?*frame);?? bool?initWithValueMap(ValueMap?&valueMap,?SpriteFrame*?frame);??
源碼如下:
[cpp]?view plaincopy
ParticleSystemQuad?*?ParticleSystemQuad::create(?ValueMap&?map,?SpriteFrame?*frame)?? ?{?? ?????ParticleSystemQuad?*ret?=?new?ParticleSystemQuad();?? ?????if?(ret?&&?ret->initWithValueMap(map,?frame))?? ?????{?? ?????????ret->autorelease();?? ?????????return?ret;?? ?????}?? ?????CC_SAFE_DELETE(ret);?? ?????return?ret;?? ?}??
[cpp]?view plaincopy
bool?ParticleSystemQuad::initWithValueMap(ValueMap?&valueMap,?SpriteFrame*?frame)?? ?{?? ?????std::string?dirname?=?"";?? ?????bool?ret?=?false;?? ?????unsigned?char?*buffer?=?nullptr;?? ?????unsigned?char?*deflated?=?nullptr;?? ???? ?????do?? ?????{?? ?????????int?maxParticles?=?valueMap["maxParticles"].asInt();?? ??????????? ?????????if(this->initWithTotalParticles(maxParticles))?? ?????????{?? ??????????????? ?????????????_configName?=?valueMap["configName"].asString();?? ???? ??????????????? ?????????????_angle?=?valueMap["angle"].asFloat();?? ?????????????_angleVar?=?valueMap["angleVariance"].asFloat();?? ???? ??????????????? ?????????????_duration?=?valueMap["duration"].asFloat();?? ???? ??????????????? ?????????????if?(_configName.length()>0)?? ?????????????{?? ?????????????????_blendFunc.src?=?valueMap["blendFuncSource"].asFloat();?? ?????????????}?? ?????????????else?? ?????????????{?? ?????????????????_blendFunc.src?=?valueMap["blendFuncSource"].asInt();?? ?????????????}?? ?????????????_blendFunc.dst?=?valueMap["blendFuncDestination"].asInt();?? ???? ??????????????? ?????????????_startColor.r?=?valueMap["startColorRed"].asFloat();?? ?????????????_startColor.g?=?valueMap["startColorGreen"].asFloat();?? ?????????????_startColor.b?=?valueMap["startColorBlue"].asFloat();?? ?????????????_startColor.a?=?valueMap["startColorAlpha"].asFloat();?? ???? ?????????????_startColorVar.r?=?valueMap["startColorVarianceRed"].asFloat();?? ?????????????_startColorVar.g?=?valueMap["startColorVarianceGreen"].asFloat();?? ?????????????_startColorVar.b?=?valueMap["startColorVarianceBlue"].asFloat();?? ?????????????_startColorVar.a?=?valueMap["startColorVarianceAlpha"].asFloat();?? ???? ?????????????_endColor.r?=?valueMap["finishColorRed"].asFloat();?? ?????????????_endColor.g?=?valueMap["finishColorGreen"].asFloat();?? ?????????????_endColor.b?=?valueMap["finishColorBlue"].asFloat();?? ?????????????_endColor.a?=?valueMap["finishColorAlpha"].asFloat();?? ???? ?????????????_endColorVar.r?=?valueMap["finishColorVarianceRed"].asFloat();?? ?????????????_endColorVar.g?=?valueMap["finishColorVarianceGreen"].asFloat();?? ?????????????_endColorVar.b?=?valueMap["finishColorVarianceBlue"].asFloat();?? ?????????????_endColorVar.a?=?valueMap["finishColorVarianceAlpha"].asFloat();?? ???? ??????????????? ?????????????_startSize?=?valueMap["startParticleSize"].asFloat();?? ?????????????_startSizeVar?=?valueMap["startParticleSizeVariance"].asFloat();?? ?????????????_endSize?=?valueMap["finishParticleSize"].asFloat();?? ?????????????_endSizeVar?=?valueMap["finishParticleSizeVariance"].asFloat();?? ???? ??????????????? ?????????????float?x?=?valueMap["sourcePositionx"].asFloat();?? ?????????????float?y?=?valueMap["sourcePositiony"].asFloat();?? ?????????????this->setPosition(?Point(x,y)?);?? ?????????????_posVar.x?=?valueMap["sourcePositionVariancex"].asFloat();?? ?????????????_posVar.y?=?valueMap["sourcePositionVariancey"].asFloat();?? ???? ??????????????? ?????????????_startSpin?=?valueMap["rotationStart"].asFloat();?? ?????????????_startSpinVar?=?valueMap["rotationStartVariance"].asFloat();?? ?????????????_endSpin=?valueMap["rotationEnd"].asFloat();?? ?????????????_endSpinVar=?valueMap["rotationEndVariance"].asFloat();?? ???? ?????????????_emitterMode?=?(Mode)?valueMap["emitterType"].asInt();?? ???? ??????????????? ?????????????if?(_emitterMode?==?Mode::GRAVITY)?? ?????????????{?? ??????????????????? ?????????????????modeA.gravity.x?=?valueMap["gravityx"].asFloat();?? ?????????????????modeA.gravity.y?=?valueMap["gravityy"].asFloat();?? ???? ??????????????????? ?????????????????modeA.speed?=?valueMap["speed"].asFloat();?? ?????????????????modeA.speedVar?=?valueMap["speedVariance"].asFloat();?? ???? ??????????????????? ?????????????????modeA.radialAccel?=?valueMap["radialAcceleration"].asFloat();?? ?????????????????modeA.radialAccelVar?=?valueMap["radialAccelVariance"].asFloat();?? ???? ??????????????????? ?????????????????modeA.tangentialAccel?=?valueMap["tangentialAcceleration"].asFloat();?? ?????????????????modeA.tangentialAccelVar?=?valueMap["tangentialAccelVariance"].asFloat();?? ???? ??????????????????? ?????????????????modeA.rotationIsDir?=?valueMap["rotationIsDir"].asBool();?? ?????????????}?? ???? ??????????????? ?????????????else?if?(_emitterMode?==?Mode::RADIUS)?? ?????????????{?? ?????????????????if?(_configName.length()>0)?? ?????????????????{?? ?????????????????????modeB.startRadius?=?valueMap["maxRadius"].asInt();?? ?????????????????}?? ?????????????????else?? ?????????????????{?? ?????????????????????modeB.startRadius?=?valueMap["maxRadius"].asFloat();?? ?????????????????}?? ?????????????????modeB.startRadiusVar?=?valueMap["maxRadiusVariance"].asFloat();?? ?????????????????if?(_configName.length()>0)?? ?????????????????{?? ?????????????????????modeB.endRadius?=?valueMap["minRadius"].asInt();?? ?????????????????}?? ?????????????????else?? ?????????????????{?? ?????????????????????modeB.endRadius?=?valueMap["minRadius"].asFloat();?? ?????????????????}?? ?????????????????modeB.endRadiusVar?=?0.0f;?? ?????????????????if?(_configName.length()>0)?? ?????????????????{?? ?????????????????????modeB.rotatePerSecond?=?valueMap["rotatePerSecond"].asInt();?? ?????????????????}?? ?????????????????else?? ?????????????????{?? ?????????????????????modeB.rotatePerSecond?=?valueMap["rotatePerSecond"].asFloat();?? ?????????????????}?? ?????????????????modeB.rotatePerSecondVar?=?valueMap["rotatePerSecondVariance"].asFloat();?? ???? ?????????????}?else?{?? ?????????????????CCASSERT(?false,?"Invalid?emitterType?in?config?file");?? ?????????????????CC_BREAK_IF(true);?? ?????????????}?? ???? ??????????????? ?????????????_life?=?valueMap["particleLifespan"].asFloat();?? ?????????????_lifeVar?=?valueMap["particleLifespanVariance"].asFloat();?? ???? ??????????????? ?????????????_emissionRate?=?_totalParticles?/?_life;?? ???? ??????????????? ?????????????if?(!_batchNode)?? ?????????????{?? ??????????????????? ?????????????????_opacityModifyRGB?=?false;?? ???? ???? ?????????????????if?(!_configName.empty())?? ?????????????????{?? ?????????????????????_yCoordFlipped?=?valueMap["yCoordFlipped"].asInt();?? ?????????????????}?? ???? ?????????????}?? ?????????????setDisplayFrame(frame);?? ?????????????ret?=?true;?? ?????????}?? ?????}?while?(0);?? ?????free(buffer);?? ?????free(deflated);?? ?????return?ret;?? ???? ?}??
注意,這里只是提供了通過粒子系統(tǒng)屬性和紋理創(chuàng)建粒子系統(tǒng)的接口,并沒有實(shí)現(xiàn)對(duì)粒子屬性的全局保存(可以參考
Earth Warriors 3D中ParticleManager的實(shí)現(xiàn)
)和圖片幀的預(yù)加載。
粒子屬性的獲取:
[cpp]?view plaincopy
ValueMap?FileUtilsApple::getValueMapFromFile(const?std::string&?filename);??
圖片幀的獲取(這個(gè)獲取方式就比較多了。。。):
[cpp]?view plaincopy
SpriteFrame*?create(const?std::string&?filename,?const?Rect&?rect);??
3.如何使用?
[cpp]?view plaincopy
auto?plistData?=?FileUtils::getInstance()->getValueMapFromFile("Particles/emissionPart.plist");?? auto?emission_frame?=?SpriteFrame::create("Images/engine.jpg",?Rect(0,0,25,32));??? auto?emitter?=?ParticleSystemQuad::create(plistData,?emission_frame);?? _background->addChild(_emitter,?10);??
4.源碼下載
我也不知道3.0release會(huì)不會(huì)集成這個(gè)功能,這里先發(fā)出pull request的鏈接:https://github.com/cocos2d/cocos2d-x/pull/5979/files
總結(jié)
以上是生活随笔為你收集整理的【玩转cocos2d-x之三十七】粒子系统的加载优化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。