淺談cocos2d游戲中天氣系統的簡單實現


一、前言

   此博客由一個新手游戲程序編寫,沒有高深的技術,基本是天氣效果表現和代碼設計的淺談,如果有更好的實現方法,歡迎指正。

二、背景

   該系統設計背景:2D游戲、正交45度表現地圖、以及同一張地圖上存在不同氣候的區域/地形,需要體現不同天氣效果以及不同天氣的切換

   類似游戲:三國群英傳(地圖相似)、塞爾達傳說-眾神的三角力量(天氣表現相似)、口袋妖怪綠寶石(天氣表現相似)

三、全局計算和局部表現

   額外系統:區域划分系統

   根據地圖的設計,各個理論上會出現不同氣候的地形均放在一張地圖里面,因此在游戲中就需要有一個類似“氣象台”的系統來控制不同區域的天氣,然后根據玩家所在區域去“表現”當前區域的天氣,該設計的目的就是為了節省cpu和內存。

   眾所周知,天氣的表現是會有不小的消耗的(2d游戲中,大量的雨滴粒子以及地面滴水表現;3d游戲中則是畫面的渲染),直接全場景添加天氣的效果明顯不現實,所以采用全局計算天氣的狀態,再根據位置表現天氣的方式去實現該系統

  1、全局計算

   “氣象台”的實現需要引入另外一個系統:區域划分系統。該系統系統主要的作用有兩點:1)根據玩家的位置得出當前所在區域。2)根據時間變化實施計算各個天氣的狀態

   第一點的實現,在此不展開講,區域划分的方式因人而異,博主采用的方式就是把區域看成一個多邊形去做,如果使用這種方法的話,區域判定提供兩種方式:

    1)一定時間判斷點與多邊形的包含關系。

     這個可以去搜索“判斷點是否在多邊形內部”,然后定時去計算。

     參考:https://www.jianshu.com/p/ba03c600a557

     優點:空間上的精准;實現方式清晰,復雜度可以自己控制。缺點:頻繁調用,時間上不夠精准。

    2)物理框碰撞。

     這個方法是博主朋友提議的,並未實現。也是把區域看成一個多邊形,不過這個多邊形是一個物理框,玩家(也需要有物理框)進入和離開區域的時候去調用其碰撞函數,再去判定位置

     優點:時間上的精准;方法不用自己實現。缺點:空間上的准確度有待商榷;需要進一步優化需要學習底層代碼。

   天氣狀態也是因人而異,不過最重要的就是“天氣”和“天數”了。

  2、局部表現

   不管用什么方式得到當前區域的天氣之后,就需要去表現天氣。表現的方式就是在攝像機上,把粒子和效果添加到相機節點上(或者根據相機位置添加到地圖上),具體的表現和實現在下一節講述。

四、天氣表現效果

   天氣系統的運作方式決定了之后,就是去設計天氣的表現效果了。

   博主設計的天氣目前有四種:小雨、烈日、沙暴和暴雨

  1、小雨和暴雨

   效果參考:

   

   該天氣推薦使用cocos2d的粒子編輯器(Particle Builder)做。粒子編輯器可以用一張圖片表現各種效果,如下面兩張圖,只需要調節參數就可以做出下雨特效

     

      

   下雨的時候可以在相機上再添加一個圖片精靈(或者着色精靈)去實現變暗效果,通過修改顏色和透明度起到天變暗的效果,在暴雨天下,設置可以在幾幀內瞬間改變亮度和顏色,起到打雷的表現效果

   根據我的理解,粒子編輯器只能針對一張圖片做特效,而地面滴水需要一個動畫表示,所以需要創建精靈節點去播放動畫,實現方式下文再講。下圖是植物大戰僵屍滴水特效:

   

   滴水精靈節點需要添加在地圖節點上,如果添加在相機節點上的話,那么如果相機跟隨人物移動的話,滴水還沒消失就會移動會看上去很別扭。

   滴水效果添加是很有必要的,博主表達能力不強,所以只能用“感覺上沒滴水的雨很別扭”這句話去形容。

     最終效果:

           

  2、沙暴

    

    看到圖應該就能理解了,目前實現方式為一張圖片循環移動。

  3、烈日

    烈日實現的效果目前參考口袋妖怪綠寶石的烈日的效果,在之前下雨的着色精靈把透明度調高,改變顏色實現(和雨天的閃電閃屏效果類似),不過效果並不是很好……

    

五、技術點(代碼和數值設計的原因)

  1、所有天氣精靈獨立

    各個表現天氣的精靈都需要獨立,目的是防止在“切換”表現天氣時出現沖突。人物從一個區域走到另外一個區域的時候,天氣系統需要做的事是:原區域天氣逐漸消失,現區域天氣逐漸出現,如果所有精靈(或者個別精靈)共用一個節點的話,那么“新”的天氣精靈會覆蓋之前的天氣精靈,導致原區域天氣瞬間消失。

    
        def __init__(self):
            # 雨天精靈
            self.RainSprite = None
            # 沙暴精靈
            self.SandStormSprite = None
            # 暴雨精靈
            self.RainStormSprite = None    
View Code

 

  2、區域划分的時候需要有過渡區

    說簡單一點就是划分區域的時候,把邊緣部分再划分一個區域。其目的是防止不同區域刷出完全對立的天氣導致的不合理,比如說沙漠目前處於烈日狀態,而沙漠外的草原在下暴雨,如果沒有做過渡區,會出現“烈日漸漸消失,暴雨漸漸出現”的天氣切換效果,雖然是漸變效果,但還是出現了烈日和暴雨同時出現的畫面,非常不合理。

  3、滴水效果實現方法

    前文講了,滴水效果是動畫效果,不能用粒子編輯器來做。所以博主的實現方式是:在初始化天氣的時候,直接創建一堆精靈(比如暴雨天,地面上需要有300個滴水效果),每幀(時間間隔可以改)去播放動畫,在播放動畫之前把精靈移動到攝像機視野范圍內。當前區域天氣的表現結束的時候,也不要銷毀精靈, 而是繼續保留,其目的是防止頻繁的創建精靈導致的消耗,水滴精靈的內存占用和地圖相比,通常只占了很小一部分,權衡之下,可以用空間去換時間。

六、后記

    因為博主個人原因,代碼不願意公開,所以本篇博文不過是個技術總結罷了。

    總而言之,天氣系統在游戲中不是一個很難實現的系統,不過在實際編寫代碼的過程中還是會遇到很多問題。

    天氣系統的主要難點只有兩個,一是各種漸變效果,二是天氣的表現效果,沒有很硬核的技術。

    最后感謝您看到這里,如果有好的想法和建議,歡迎留言~

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM