使用 Amethyst Engine 實作小行星遊戲 - 12 更多的狀態

這章我們要一口氣新增兩個新的狀態:StateMenu 跟 StateOver,基本上因為不同的 state 都分到不同的檔案,所以多幾個 state 也沒差。
這章其實沒有太多需要介紹的,只有在 state 轉換上面多費點功夫,這部分可以先畫一個狀態圖讓整體更清楚:
stateflow

amethyst 在狀態間切換 Trans 共有幾個不同的方式:

與之對應的,在我們實作各 state 的時候,要實作對應的函式:

下面就概敘一下各 state 的實作內容 :

StateMenu

StatePlay

StatePause

這個只是個空狀態,只要實作 handle_event 處理按下 ESC 的事件即可。

StateOver

fn on_stop(&mut self, data: StateData<'_, GameData<'_, '_>>) {
  let world = data.world;
  world.exec(|(entities, cameras) : (Entities, ReadStorage<Camera>)| {
    for (e,_) in (&entities, !&cameras).join() {
      if let Err(e) = entities.delete(e) {
        log::error!("Failed to destroy entity: {}", e);
      }
    }
  });
}

也就是說,world.exec 會收一個 lambda,這個 lambda 的寫法就跟平常寫 system 時沒什麼兩樣,參數就是各資源及 component; 或者也可以直接呼叫 world.delete_all() 把所有東西都刪光,但這樣在 StateMenu 的 on_resume 就要再一次初始化 camera,比較沒這麼漂亮。

還有一個提一下,如果有想要在不同的 State 間共用的資料(在我的遊戲裡是隕石擊墜數),基本上就要放在 resource 裡面,透過 read_resource 把它讀出來即可, 就如我們在 UI 那章實作了 ScoreRes,在 StateOver 的時候用 read_resource 就可以取出內存的 score 值了。

let score = world.read_resource::<ScoreRes>().score;

寫到這裡一個極簡(而且沒人想玩)遊戲就完成啦,但不管再怎麼複雜的遊戲,最基本用到的東西和這個簡單遊戲也相差無幾,就期待各位大展身手,用 amethyst 寫一個 3A 大作出來(欸。

comments powered by Disqus