Phaser3 シーン管理
Posted
Phaser3 シーン管理
前回の記事
https://mijinc0.github.io/blog/post/20200820_phaser3_about/
Phaser3のシーン管理について。
※ typesriptで書くことを前提にしています
基本
Phaserのシーンを扱う時、チュートリアルに従って書くとSceneを継承したクラスを自分で用意することになると思う。
Sceneクラスにはinit,preload,create,updateを用意し、シーンが開始して終了するまで、それぞれのフェーズで必要な処理をそこに書いていく。
init: 主にpreload前にやっておきたい初期化処理を書くpreload: 主にアセット(スプライトや音楽など)を読込む処理を書くcreate: シーンにタイルマップやスプライトを配置する処理を書く(シーンを作るメインはここ)update: 1フレーム毎に実行される処理を書く
上記は公式のチュートリアルでも説明されていたはずなので上記で簡単におさらい。
preloadはpreload中にLoaderPluginを使ったアセットのロード処理が全て完了したら、次のcreateが呼び出されるようになっている。また、シーンに描写したいスプライトなどを配置する処理を書くのは主にcreateになるが、preload中にオブジェクトを配置しても描写はされる。これは、簡単なローディングシーンを実装するときに使える。
シーンの開始について
SceneManagerのadd関数によって追加されたシーンを開始する方法はいくつかある。
SceneManagerのstart関数SceneManagerのrun関数ScenePluginのstart関数ScenePluginのrun関数ScenePluginのlaunch関数- (
ScenePluginのrestart関数)
SceneManagerはGameクラス内でthis.sceneをするとアクセス出来、ScenePluginはSceneクラス内でthis.sceneをするとアクセス出来る。似たような操作感で似たような関数を使うことになる部分が"ややこしい"ポイント。
import * as Phaser from 'phaser';
export class CustomGame extends Phaser.Game {
constructor() {
const config: Phaser.Types.Core.GameConfig = {
// 色々書く
};
super(config);
// SceneManager
this.scene;
}
}
import * as Phaser from 'phaser';
export class CustomScene extends Phaser.Scene {
init(data: any): void {
// ScenePlugin
this.scene;
}
}
それぞれ簡単に見ていく。
SceneManager.start
これがSceneManagerでシーンを開始する時の基礎的な関数。
SceneManager.run
run関数は指定されたシーンの状態によって挙動を変える。
- pause状態 : resume関数を呼ぶ
- sleep状態 : wake関数を呼ぶ
- 完全な停止状態 : start関数を呼ぶ
全く動いていないシーンに対してはrunでもstartでも、結局のとろこrun関数内でstartを呼ぶので同じことをしている。
ScenePlugin.start
現在のシーン (ScenePluginはSceneクラス内でsceneプロパティにアクセスすることを思い出して欲しい) を停止して、新たに指定したシーンを開始する。
ScenePlugin.run
SceneManagerのrunを呼ぶのと同じ。
ScenePlugin.launch
SceneManagerのstartを呼ぶのと同じ。だが、ScenePlugin.startが現在のシーンを停止して、新しいシーンをstartさせるのに対し、こちらは新たしいシーンをstartさせるだけであることに注目してほしい。
関数の説明に “Launch the given Scene and run it in parallel with this one.” とあるのはそのため。
Sceneの開始まとめ
使い分けとしては以下のようにまとめる。
- Gameクラス内において、シーンを開始するだけであれば
startを使う - Gameクラス内において、シーンの状態によって新規開始、再開、などを分けたければ
runを使う - Sceneクラス内において、現在のシーンを停止して新しいシーンを新規開始したければ
startを使う - Sceneクラス内において、現在のシーンをそのままに新しいシーンをその状態によって新規開始、再開、などを分けて開始したければ
runを使う - Sceneクラス内において、現在のシーンをそのままに新規開始したければ
launchを使う
マルチシーン
Phaser3では並行して複数のシーンを動かすことが出来る。
“並行して” とあるが、非同期で動いているわけではない。一つのフレーム(一回のupdateループ)内で複数のシーンが同時にupdateされるという意味である。動かす順番は、SceneManager.addによって追加した順に動く。(後から変えることも出来る)
この順番は大事で、SceneManager.addで追加された順に描写される、つまり、後から追加されたシーンの描写は重なった時に手前に描写されるということを意味する。
例えば、画面を真っ暗にした状態でメッセージだけ表示したいときのことを考えてみる。勿論一つのシーン内でdepth(z-index)を調整してメッセージのみを表示することは可能だ。だが、とても面倒くさいと思わないか。また、雨のエフェクトを画面に追加するときのことを考えてほしい。
雨のエフェクトはほしいが、メッセージが見づらくなるのは嫌だとなると、一つのシーンでそれを調整するのは面倒ではないか。
これらを解決する方法として、複数のシーンを立てておいてメッセージなどのUIは手前のシーンに描写、キャラクターなどが存在するシーンと分けるという手段がある。これなら、それらをdepthの調整をせずに達成することが出来る。メッセージボックス等のUIを必ず手前のシーンに描写すると決めてしまえば、ゲーム本体のシーンがフェードアウトして真っ暗になってもメッセージボックスは表示できるし、雨のエフェクトがかかっていてもメッセージボックスには影響を与えない。
参考
https://github.com/photonstorm/phaser/blob/v3.22.0/src/scene/SceneManager.js
https://github.com/photonstorm/phaser/blob/v3.22.0/src/scene/ScenePlugin.js
https://photonstorm.github.io/phaser3-docs/Phaser.Scenes.SceneManager.html
https://photonstorm.github.io/phaser3-docs/Phaser.Scenes.ScenePlugin.html