2013年6月14日 星期五

Flash遊戲引擎 CitrusEngine (五) 建立你的第一個遊戲- LevelManager 場景控制

State的作用類似flash的Scenes的功能 (之前的例子一開始的StarlingDemoGameState就是一個State物件),負責目前的畫面, LevelManager 物件則是幫你處理各State的切換。
LevelManager有個levels屬性,他是一個Array,你可以把每個場景依序放進去,等到需要切換畫面時在依照序號切換不同的State。
需要切換畫面時你可以使用LevelManager.nextLevel()切換到下一個場景或是使用LevelManager.gotoLevel(_stateId)方法來切換到不同的State,當LevelManager變動時會觸發onLevelChanged這個Signal。
繼續用之前的遊戲例子來說明,我們希望角色在生命值等於0(lives==0)時切換到結束畫面。
所以我們需要製作一個結束畫面的State。
import citrus.core.starling.StarlingState;
 import org.osflash.signals.Signal;
 /**
  * 基本的State
  */
 public class MyState extends StarlingState 
 {
  public var lvlEnded:Signal;
  public function MyState() 
  {
   super();
   //場景結束Signal
   lvlEnded = new Signal();
  }
  
 }
先作一個空的State(MyState),裏面有一個Signal物件叫作lvlEnded,State結束前會先觸發它,往後遊戲每個場景可以直接繼承它,就會有lvlEnded這個Signal
import citrus.objects.CitrusSprite;
 import starling.text.TextField;
 import flash.utils.setTimeout;
 /**
  * 結束的畫面
  */
 public class EndState extends MyState 
 {
  public function EndState() 
  {
   super();
  }
  
  override public function initialize () : void
  {
   super.initialize();
   add(new CitrusSprite("endTd", {
     view:new TextField(500, 400, "GameOver", "", 60,0xff0000)
    }));
  }
 }
結束畫面的EndState是繼承MyState,然後我們在畫面上加上TextField並填上GameOver。

把原來的StarlingDemoGameState也改成繼承MyState,然後我們再gameData變動時加上lives==0就觸發場景結束這個條件。
private function gameDataChanged(data:String, num:int ):void 
  {
   var _citrusSprite:CitrusSprite;
   switch (data) 
   {
    case "lives": //生命值變動
     _citrusSprite = getObjectByName("livesTd") as CitrusSprite;
      TextField(_citrusSprite.view).text = "生命:" + num;
     if (num<=0)
     {
                                                //生命值小於0就觸發lvlEnded
      lvlEnded.dispatch();
     }
    break;
    case "score": //分數變動
     _citrusSprite = getObjectByName("scoreTd") as CitrusSprite;
      TextField(_citrusSprite.view).text = "分數:" + num;
    break;
    default:
     trace(data, num);
   }
  }
StarlingDemoGameState繼承了MyState,所以也擁有lvlEnded這個Signal,我們可以用lvlEnded.dispatch();來觸發它。
在Main的init()裡,我們new一個LevelManager物件,並把StarlingDemoGameState與EndState場景放進levels陣列。
//new一個LevelManager場景控制
   levelManager = new LevelManager(MyState); //切換MyState
   levelManager.levels = [StarlingDemoGameState,EndState]; //依序放入State 
   levelManager.onLevelChanged.add(_onLevelChanged);
   levelManager.gotoLevel();
new LevelManager(MyState),作一個LevelManager物件,需要填入一個State參數,因為場景都繼承MyState,所以我們可以直接用MyState。(這也是我們之前建立MyState的用意,也方便管理)。
levelManager有變動就觸發_onLevelChanged()。最後是讓遊戲一開始就起動第一個State (gotoLevel()方法預設是1)。
再來實作_onLevelChanged方法。
private function _onLevelChanged(lvl:MyState):void 
  {
   state = lvl; //設成新的state 
   lvl.lvlEnded.add(_nextState);
  }
  
  private function _nextState():void 
  {
   levelManager.nextLevel();
  }
_onLevelChanged會傳入要切換的MyStat,然後把目前的state設成新的MyState。
把MyStat的lvlEnded加上_nextState()這個方法,讓場觸發結束時作levelManager.nextLevel();這個動作,切換到下一個MyState。
輸出試看看,當角色生命值變成0時,遊戲的場景就會切換。
另外,如果你希望結束畫面可以再回到StarlingDemoGameState時,你可以使用levelManager.gotoLevel(1),它可以讓你切換到第一個State。
PS.你會發現在EndState裏面使用levelManager.nextLevel(),或lvlEnded.dispatch()沒有作用,因為EndState已經是最後一個Stat了,沒有沒有nextLevel...
然後也請記得在StarlingDemoGameState.initialize()裡先把gameData的分數與生命初始化,避免下一次進去遊戲生命值就是0的情況。

Demo預覽
原始碼下載

Flash遊戲引擎 CitrusEngine (六) 建立你的第一個遊戲- 場景編輯ObjectMaker與Camera控制

沒有留言: