註:本人在部落格園編寫博文的同時,也挑選一些譯為英文發表於英文網站上,常用網名elecpiano或本人英文名Jason Lee。以下網址所發表的文章,均由本人自行撰寫並發布,歡迎請各位朋友閱讀。
http://xnaelectriceffect.codeplex.com/
http://www.windowsphonegeek.com/articles/Electric-Effect-on-Windows-Phone-7-using-XNA
http://www.symbio.com/techblog/?p=461
最近在做一款消除類遊戲,需要實現強電流橫穿螢幕的效果。首先我想到了用粒子系統(Particle System)來實現,但嘗試過無數次的參數調整之後,發現粒子系統並不適合做電流、閃電等效果。
剖析原因:
無論是複雜還是簡單的粒子系統,核心思路都是通過不斷地釋放(Emit)離散的、輻射狀蔓延的小亮點,來營造諸如火焰、煙霧、爆炸等效果。電流和閃電效果與前者最大的區別在於:前者的粒子移動軌跡是輻射狀的,而後者的分布和移動卻是線性(所謂線性,後文具體闡述)。
如果要直觀地感受一下電流的運動軌跡,可以在網上搜一搜“電漿求”或“Plasma Ball”等關鍵字,甚至可以下載相關的手機應用來體驗一下。
是本人在Windows Phone 7上利用XNA實現的電流效果:
歡迎下載範例程式碼。
設計思路:
我認為電流的運動模型可以抽象為:
每一股電流,都是由一系列小亮點組成。而在任意時刻,這些小亮點都沿著某一特定曲線分布。在該曲線中選擇若干個特徵點,然後通過不斷移動這些特徵點的位置,就能類比一股電流的蠕動效果。
請看下面的圖示:
中,藍色直線串連著一股電流的起點和終點。5個紅色小點,就是我們選取的特徵點。
試著想象一下,在某一時刻,這5個點分別位於各自活動範圍內的任意位置。那麼,其效果就會是如所示:
中,紅色的連線代表著實際的小亮點分布曲線。當然,利用直線來串連兩個特徵點是最簡單的做法,卻顯得有些不夠逼真。我們可以採用不同的曲線計算方法來對此進行改善。就是利用Catmull Rom演算法來改善後的效果:
註:Catmull Rom方法是XNA的Vector2 類中內建的方法。有關Catmull Rom演算法的詳細介紹,請參考網上的相關文章。
進一步改善:
實際上,上述這些特徵點並漫無邊際地運動,而是應該在某一特定範圍內移動。請看:
藍色半透明圓形地區,是每個特徵點所對應的移動範圍。每個小亮點都從原點出發,沿著某一隨機的方向,按照某一隨機速度,努力向外遊動,當達到半徑所示範圍邊界時,就會回到原點,再次沿著另一個方向移動。這樣一來就能夠營造出更加逼真的電流效果(請參考網上的一些Plasma Ball的動畫,電流在彎曲到一定程度後,就會重新開始蠕動)。
閃爍效果:
電流的蠕動已經實現了,但還不夠。再次仔細觀察Plasma Ball的效果,你會發現電流在蠕動過程中,還有閃爍的效果。閃爍的效果可以不斷修改每個小亮點的透明度來實現。
但是!人類的眼睛實在是太過尖銳了,任何機械的變化都會令我們感到很做作。因此,還需要不斷隨機變更小亮點本身的材質。材質的變更要遵循“大同小異”的原則,在顏色和尺寸上稍作修改即可,否則就會產生“亂七八糟”的感覺,過猶不及嘛。
意外收穫:
由於每個特徵點都是各自獨立地移動,因此必然會在某一時刻,一部分特徵點彼此靠近一些,而另一部分特徵點則相互遠離一些。這種不均勻的分布,使得電流上的明暗分布產生了變化:小亮點愈集中的地方,視覺效果就越明亮。更有趣的是,在電流不斷蠕動過程中,這些明暗的變化也在“肆意”移動,進一步滿足了喜歡追求新鮮感的眼球。
代碼結構簡介:
範例程式碼中,JasonElectricEffect項目是一個可重用的Windows Phone 7 Library。其中:
1. ElectricEffect是代表一個電流效果的類,它可以包含若多個ElectricFlow對象(顧名思義,代表一股電流)。
2. 每一個ElectricFlow對象,都包含若干個ElectricNode對象(即上文中所提及的特徵點)。
3. 通過ElectricEffectType枚舉變數來指定特徵點之間曲線的計算方法,包括:Line(直線)、Bezier(貝茲路徑)、CatmullRom(翻譯成啥才好?)。不同的曲線可營造出不同的感覺,或鏗鏘尖銳,或婉轉流暢。
4. ElectricEffect類的Density屬性定義了特徵點與特徵點之間,小亮點分布的密度。
5. ElectricFlow的LifeSpan屬性用來定義每隔多久要變更一次小亮點的材質。
關於如何快速產生一個電流效果,請參考JasonElectricEffectDemo項目中GamePage.xaml.cs檔案裡的InitElectricEffect()方法。
這篇文章代碼較少,分析的文字多了些,感謝讀到最後的每一位朋友。
歡迎下載範例程式碼,並分享改善和擴充的想法。