cocos2d-x[3.2]如何實現拖尾漸隱效果MotionStreak,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
【嘮叨】
在游戲的實現過程中,我們有時會需要在某個游戲對象上的運動軌跡上實現拖尾漸隱效果,這種感覺就好像是類似飛機拉線似的拖尾巴,使我們的游戲在視覺上感覺很好。
比如:刀光、子 彈的運動軌跡、流星劃痕等等。
cocos2d-x提供了一種內置的拖尾漸隱效果的實現方法:MotionStreak。
偷了幾張圖,呵呵呵呵呵。。。
當然要做出酷炫的拖尾效果,都是需要與 粒子特效Particle 相結合的。
如下再附一張唯美的拖尾效果(MotionStreak + 粒子特效),增加大家學習的激情。
雖然我不會弄愛心,但是我覺得你學完 MotionStreak,你肯定就會弄下面的愛心了。。。
【致謝】
http://blog.csdn.net/honghaier/article/details/8600896 (源碼原理深入分析)
http://cn.cocos2d-x.org/tutorial/show?id=2225 (《水果忍者》劃動刀光實現)
http://blog.csdn.net/dionysos_lai/article/details/39083031 (流星拖尾效果實現)
【MotionStreak】
1、原理
MotionStreak 的拖尾效果,原理實際上是:在相應距離內動態生成一段段的條帶,然后一段段逐漸的消隱。
可以指定消隱的速度fade(時間秒),一段條帶最小距離minSeg,以及條帶的寬度粗細(stroke),條帶的顏色值(color),以及相應的紋理圖片對象。
原理說明:MotionStreak在移動的過程中(setPosition位置發生改變時),會動態生成一段段條帶段,然后這些條帶段會在生命周期fade秒內,漸漸隱去(慢慢變透明),從而形成了拖尾的效果。
如下如所示:
PS:因為是一段段條帶相連形成拖尾,所以如果條帶太粗(stroke太大),在視覺上可能會出現“脫節”的效果,就像上面的圖一樣。所以在實際使用中,stroke的大小設置應該合理。
2、創建方式
創建MotionStreak有兩種方式:
> 一種是用圖片資源文件作為紋理創建。
> 另一種是通過紋理圖片Texture2D創建。
各個參數的說明,在“原理”中已經給出解釋。
/** * 創建MotionStreak 的兩種方式 **/ // fade : 拖尾漸隱時間(秒) // minSeg : 最小的片段長度(漸隱片段的大?。?。拖尾條帶相連頂點間的最小距離。 // stroke : 漸隱條帶的寬度。 // color : 片段顏色值。 // path : 紋理圖片的文件名。 // texture : 紋理圖片的對象指針。 static MotionStreak* create(float fade, float minSeg, float stroke, const Color3B& color, const std::string& path); static MotionStreak* create(float fade, float minSeg, float stroke, const Color3B& color, Texture2D* texture); // 使用舉例 auto motionstreak = MotionStreak::create(1.0f, 1.0f, 10.0f, Color3B(255, 0, 0), "streak.png"); //
3、相關函數
為了實現拖尾漸隱效果,MotionStreak還對Node類的一些函數進行了重載,如update、draw、setPosition等。
每當MotionStreak改變了位置(setPosition)后,就會形成一條拖尾。而update里則根據位置信息產生一段段新的頂點(條帶段),并讓之前生成的條帶段漸隱或消失。
// /** * 相關函數 * tintWithColor : 設置頂點顏色值。 * reset : 刪除所有條帶段,重置。 * setFastMode : 設置快速模式。 * setStartingPositionInitialized : 不需要了解,也不需要去使用。 **/ // 條帶段使用的顏色值 void tintWithColor(const Color3B& colors); // 重置,刪除所有條帶段 void reset(); // 設置是否是快速模式, 默認為true // 當為快速模式時,新的頂點被更快的加入,但是新的頂點具有更小的精確值 // PS:實踐測試,請寬恕若菜的無知,若菜實在看不出有何區別。。。 inline bool isFastMode() const { return _fastMode; } inline void setFastMode(bool bFastMode) { _fastMode = bFastMode; } // 在剛創建MotionStreak的時候會置為false(表示創建后,還未移動過) // 一旦改變Position(即移動后),會置為true(表示拖尾效果開始了,然后移動就會有拖尾的效果了) // PS:一般不會手動去設置它,所以不需要了解這個函數。 inline bool isStartingPositionInitialized() const { return _startingPositionInitialized; } inline void setStartingPositionInitialized(bool bStartingPositionInitialized) { _startingPositionInitialized = bStartingPositionInitialized; } //
4、支持Action動作
MotionStreak繼承自Node類。而既然它一旦移動(位置Position發生改變)就會拉出一條拖尾,那么執行 MoveTo/MoveBy 或者 JumpTo/JumpBy 等等Action動作,自然也是可以形成拖尾效果的啦。
5、使用步驟
(1)創建MotionStreak。MotionStreak::create()。
(2)將MotionStreak加入到場景中。this->addChild()。
(3)設置位置MotionStreak->setPosition();或執行移動Action動作。
(4)一旦改變了位置之后,就會形成一段拖尾效果了。
【代碼實踐】
1、《水果忍者》劃動刀光效果(MotionStreak + 粒子特效)
代碼實現可參見:http://cn.cocos2d-x.org/tutorial/show?id=2225
手勢劃動產生的刀光效果,是利用觸摸移動事件,改變MotionStreak的位置,來形成拖尾的。
2、《流星劃痕效果》(精靈移動 + MotionStreak + 粒子效果)
代碼實現可參見:http://blog.csdn.net/dionysos_lai/article/details/39083031
流星的尾巴,是在schedule/update中不斷改變MotionStreak的位置,來形成拖尾的。
以下,再讓我介紹一個MotionStreak的簡單實現的“酷炫”例子吧。
3、通過觸摸事件,實現拖尾效果
圖片資源偷自《流星劃痕效果》。
[PIC_XX.png]
[steak.png]
預期實現效果:
> 觸摸開始touchBegan,流星的位置設置為觸摸點位置。
> 觸摸移動touchMoved,流星跟隨觸摸點移動而移動,同時MotionStreak跟隨流星移動,形成拖尾效果。
創建兩種不同規格的MotionStreak,看看效果。
> 設置minSeg = 50、stroke = 30、color = WHITE、紋理為steak.png 。
> 設置minSeg = 1 、stroke = 10、color = RED 、紋理為steak.png 。
3.1、在HelloWorld.h中添加如下變量與函數。
// class HelloWorld : public cocos2d::Layer { public: static cocos2d::Scene* createScene(); virtual bool init(); CREATE_FUNC(HelloWorld); // 觸摸事件 回調函數 bool onTouchBegan(Touch* pTouch, Event* pEvent); void onTouchMoved(Touch* pTouch, Event* pEvent); private: Sprite* star; // 流星精靈 MotionStreak* streak; // 拖尾 }; //
3.2、在HelloWorld.cpp的init()中,創建流星精靈、MotionStreak拖尾,并添加觸摸監聽事件。
// bool HelloWorld::init() { if ( !Layer::init() ) return false; // 流星精靈Sprtie star = Sprite::create("PIC_XX.png"); star->setPosition(100, 100); this->addChild(star); // 流星拖尾MotionStreak streak = MotionStreak::create(0.5f, 50, 30, Color3B::WHITE, "steak.png"); // streak = MotionStreak::create(0.5f, 1, 10, Color3B::RED, "steak.png"); streak->setPosition(star->getPosition()); // 設置拖尾streak的位置 this->addChild(streak); // 注冊單點觸摸 auto dispatcher = this->getEventDispatcher(); auto listener = EventListenerTouchOneByOne::create(); listener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this); // 觸摸開始 listener->onTouchMoved = CC_CALLBACK_2(HelloWorld::onTouchMoved, this); // 觸摸移動 dispatcher->addEventListenerWithSceneGraphPriority(listener, this); return true; } //
3.3、實現觸摸事件
> 觸摸開始touchBegan :流星位置設置為觸摸點。
> 觸摸移動touchMoved :流星移動,streak跟隨流星移動,形成拖尾效果。
// // 觸摸開始 :設置star和streak的位置 bool HelloWorld::onTouchBegan(Touch* pTouch, Event* pEvent) { // 獲取觸摸點位置 Vec2 pos = pTouch->getLocation(); // 設置位置 star->setPosition(pos); streak->setPosition(star->getPosition()); // 刪除所有活動條帶段 streak->reset(); return true; } // 觸摸移動 :移動star和streak的位置 void HelloWorld::onTouchMoved(Touch* pTouch, Event* pEvent) { // 觸摸移動的偏移量 Vec2 delta = pTouch->getDelta(); // 設置位置 star->setPosition(star->getPosition() + delta); streak->setPosition(star->getPosition()); } //
3.4、運行結果
(1)設置minSeg = 50、stroke = 30、color = WHITE、紋理為steak.png 。
(2)設置minSeg = 1 、stroke = 10、color = RED 、紋理為steak.png 。
(3)關于streak->reset() 函數。
細心的小伙伴,肯定發現了我在上面的兩個GIF圖片的一開始,鼠標到處點了好幾下。
為什么我會做這種“無用”操作呢?因為接下來我要講的就是我為什么亂點的原因。
我在 onTouchBegan 中寫了這么一句話:streak->reset() 。
如果去掉這句話。那么每次觸摸開始時,流星直接移動到觸摸點,streak也跟隨改變位置,就會出現如下的現象:沒有觸摸拖動,只是點擊鼠標,也會出現拖尾劃痕。
而 streak->reset() 的作用就是:清除所有活動條帶段。
3.5、分析與總結
> 如果minSeq和stroke設置較大,即每一段條帶都比較長或寬,視覺上就會看到明顯“一節一節”的那種效果。
> 如果拖尾效果不與粒子特效組合使用的話,就會像上面的例子那樣,比較單調。
> MotionStreak只要改變位置,就會形成拖尾效果。無論是setPosition,還是執行動作(MoveTo、JumpTo)。
> reset() 函數可以清除當前所有存在的漸隱條帶,即所謂的重置。
關于cocos2d-x[3.2]如何實現拖尾漸隱效果MotionStreak問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。