シーン(Scene)とは
RPGツクールMV / MZにおけるSceneとは、機能を集合させる場、及びUIの機能を操作する場だ。もう少しわかりやすく書くと各画面(タイトル画面・マップ画面など)を作る機能となる。
オーディオ、グラフィック、UI、データベースを各所から引っ張り出し、そのシーンに合うように組み立てていく。プラグイン開発では既存のシーン更新の他に、既存とは全く異なる独自UIやゲームシステムを導入する場合に使用する。UnityのSceneと似たような意味合いだが、UIグループごとに1シーン作る点は異なる。
あくまで理論上だが、新規シーンを作成することでカードゲームやオセロ、音ゲーなどどんなゲームも作成可能となる。
まず、イメージが湧きにくいので既存で用意されているシーンを紹介する。
マップシーン(Scene_Map)
タイトルシーン(Scene_Title)
メニューシーン(Scene_Menu)
戦闘シーン(Scene_Battle)
代表的なシーンはこの4つだ。タイトルシーンではタイトルや背景の表示、各種コマンド選択処理など、マップシーンではキャラの移動やタイルの表示など、他APIでまとめている処理の呼び出しや簡単な処理を定義している。マップシーンで別マップに移動する場合、新たなマップシーンインスタンスを生成して移動する。その一方UIを定義するシーンは各画面ごとにScene_〇〇とクラスが定義してあり、該当のシーンを呼び出す。Scene_Menuのみ紹介したがScene_Save(セーブ画面)、Scene_Skill(スキル画面)など複数のシーンが定義してある。
既存のSceneクラス一覧
以下はコアスクリプトのrmmz_scenes.jsファイルに記載されているSceneクラスの一覧だ。
クラス名 | 親クラス | 説明 |
---|---|---|
Scene_Base | 各種シーンのスーパークラス。 | |
Scene_Boot | Scene_Base | 初期設定シーン。ゲーム実行直後に1回のみ呼び出される。 |
Scene_Splash | Scene_Base | スプラッシュ画面 |
Scene_Title | Scene_Base | タイトル画面 |
Scene_Message | Scene_Base | 戦闘画面やマップ画面で使用するヘルプメッセージやゴールド表示などの各種共通ウィンドウ設定。 |
Scene_Map | Scene_Message | マップ画面 |
Scene_MenuBase | Scene_Base | 各種メニュー画面のスーパークラス |
Scene_Menu | Scene_MenuBase | メニュー画面 |
Scene_ItemBase | Scene_MenuBase | スキル画面、アイテム画面のスーパークラス |
Scene_Item | Scene_ItemBase | アイテム画面 |
Scene_Skill | Scene_ItemBase | スキル画面 |
Scene_Equip | Scene_MenuBase | メニュー画面 |
Scene_Status | Scene_MenuBase | ステータス画面 |
Scene_Options | Scene_MenuBase | オプション画面 |
Scene_File | Scene_MenuBase | セーブ画面・ロード画面のスーパークラス |
Scene_Save | Scene_File | セーブ画面 |
Scene_Load | Scene_File | ロード画面 |
Scene_GameEnd | Scene_MenuBase | ゲーム終了画面 |
Scene_Shop | Scene_MenuBase | ショップ画面 |
Scene_Name | Scene_MenuBase | 名前入力画面 |
Scene_Battle | Scene_Message | 戦闘画面 |
Scene_Gameover | Scene_Base | ゲームオーバー画面 |
表を親子関係のみに絞ってクラス図にした。
Sceneの移動
シーンの呼び出し方法は主に3種類。
SceneManager.goto(Scene_Map); //1.シーン移動
SceneManager.push(Scene_Battle); //2.シーン移動(前シーン保持)
SceneManager.pop(); //3.1つ前のシーンに戻る
goto
全く別のシーンに移動する。前のシーンに戻ることが無い前提であり、現在以下のシーンはメモリから削除される。タイトル画面からマップ画面への移動、マップ画面から別のマップ画面への移動などで使われている。
push
今のシーンを現在の状態で画面を静止させたまま現在のシーンはメモリで確保しつつ、次のシーンへ移動する。前画面がそのまま残るため、前シーンの画面を消したりフィルターをかけたい場合は次シーンのcreateメソッドで処理を適宜記述する。マップ画面からメニュー画面への移動、マップ画面から戦闘画面への移動、メニュー画面からスキル画面、セーブ画面など各種別UI画面への移動などで使われている。
pop
pushで移動したシーンを1つ戻す。戻した際、Scene_〇〇で保持している値はそのまま維持している。Aシーン→Bシーン→Cシーンと移動した後、Cシーンからpopした場合、Bシーンに戻る。再度BシーンからpopするとAシーンに戻る。gotoで移動した後はメモリが初期化するため、popで呼び出せなくなる。
シーンのサンプル
以下はSceneクラスを新規作成するプラグインのひな型だ。主にオーバーライドで使いそうなメソッドをピックアップしている。
/*:
* @plugindesc サンプルPlugin
* @target MZ
* @help
* Sceneクラスのサンプル
*
* @command openScene
* @text シーン開始
* @desc サンプルシーンの開始。
*
*/
(() => {
const pluginName = document.currentScript.src.match(/^.*\/(.*).js$/)[1];
// Plugin Command
PluginManager.registerCommand(pluginName, "openScene", () => {
SceneManager.push(Scene_Sample);
});
class Scene_Sample extends Scene_Base {
initialize() {
super.initialize();
//初期処理1:変数の初期化など
}
create() {
super.create();
//初期処理2:ピクチャー、オーディオの読み込み、UI定義の生成など
}
isReady() {
return super.isReady(); //作業中フラグ、trueだとシーンチェンジが開始する。 }
start() {
super.start();
//1フレーム目で行う処理
}
update() {
super.update();
//毎フレームごとで行う処理
}
isBusy() {
return super.isBusy();
//作業中フラグ、trueだとシーンチェンジが開始する。
}
terminate() {
super.terminate();
//終了処理。
}
}
})();
プラグインコマンドでシーンを呼ぶようにしているので、実行すると真っ暗な画面になれば成功だ。空の何も処理がないシーンとなる。Scene_〇〇はデフォルトが真っ暗な画面で、適宜必要に応じて修正していく。
各処理の説明をしていく。
initialize
コンストラクタ。SceneManager.gotoなどの命令が実行された直後に呼び出される。主にクラス内の変数の初期化などを行う。
create
生成メソッド。initializeの次に実行する。画像、UIの描画などを行う他、初期化処理として必要だがinitializeではエラーになるような他クラスの生成・利用も行う。この処理の後、ローディング画面が表示される。
isReady
準備フラグ。createの次に発生しtrueになるとstartに移行する。デフォルトでは、画像やエフェクト、フォントのプリロードが終わったらtrueになる。他、プリロード対象を追加したい場合などはここで処理を加えると良い。
start
1フレーム目の処理。ローディング画面中に呼ばれるので前準備の中で重い処理はこちらで行うとよい。この処理が終了直後にローディング画面が外れる。
update
毎フレーム実行される処理。主にこのメソッドで更新処理を行う。
isBusy
SceneManager.pushなどで終了処理が走った際、まだ終了させないために利用しているフラグ。デフォルト(Scene_Base)だとフェード処理をしている間Trueになる。このメソッドがfalseにならない限りシーン移動は一時停止している。
terminate
終了処理。主にクラスの破棄などメモリのクリアを行う。
以下はサンプルという文字を表示するプラグインだ。文字は方向キー押下でその方向に移動する。キャンセルボタンで前の画面に戻る。
/*:
* @plugindesc サンプルPlugin
* @target MZ
* @help
* Sceneクラスのサンプル
*
* @command openScene
* @text シーン開始
* @desc サンプルシーンの開始。
*
*/
(() => {
const pluginName = document.currentScript.src.match(/^.*\/(.*).js$/)[1];
// Plugin Command
PluginManager.registerCommand(pluginName, "openScene", () => {
SceneManager.push(Scene_Sample);
});
class Scene_Sample extends Scene_Base {
create() {
super.create();
//「サンプル」と書かれた文字を表示
this._text = new Sprite(new Bitmap(Graphics.width, Graphics.height));
this._text.bitmap.drawText("Sample", 0, 0, Graphics.width, Graphics.height, "center");
this._text.x = (Graphics.width - this._text.bitmap.width) / 2;
this._text.y = (Graphics.height - this._text.bitmap.height) / 2;
this.addChild(this._text);
}
update() {
super.update();
//入力処理
this.updateInput();
}
updateInput() {
const speed = 5;
//方向キー押下で文字を移動する。
if (Input.isPressed("left")) {
this._text.x -= speed;
}
if (Input.isPressed("right")) {
this._text.x += speed;
}
if (Input.isPressed("up")) {
this._text.y -= speed;
}
if (Input.isPressed("down")) {
this._text.y += speed;
}
if (Input.isTriggered("cancel")) {
SceneManager.pop();
}
}
}
})();
単純なシーンだが、シーンクラスでできることは把握できると思う。RPGツクールのAPIの他、pixi5やJavaScriptのAPIを使えばどんな仕様でも実現できるクラスがこのScene_Baseを継承したクラスになる。
シーンの移動処理の動き。
シーンの移動・更新処理はSceneManegerのchangeScene、UpdateSceneに記載されている。以下はSceneManeger独自の動きについてはなるべく省き、SceneManagerのメソッドや変数の動きに注目すして2メソッドを読み解いた流れだ。
イベントでSceneManager.gotoなどを実行すると即座にコンストラクタとしてinitializeが呼ばれる。その後、前シーンの終了処理を経て新シーンのcreateを実行する。。create実行後にローディング画面が表示される。まだこの段階では前シーンの破棄はしない。
ローディング画面中にisReadyが呼ばれTrueになると次の処理に進む。主にピクチャ・エフェクト・オーディオのプリロードが終わればTrueになるが、独自に処理を加えることもできる。
isReadyがTrueになると次シーンの準備ができたと判断、前シーンのエフェクト処理と前シーンが破棄される。その後Startを実行する。Start実行後ローディング画面が終了する。及び、この段階でSceneをpixiへ登録するため、これ以降はリアルタイムで画面表示に反映する。
以降は毎フレームの更新処理となる。
まず、入力データ、エフェクトの更新処理が入った後、次画面への移動可否の確認。isStartedがtrueの場合、updateを実行する。isStartedは_startedがtrueになる場合にtrueとなるが独自に処理を続行してもよい。_startedはstart実行時からtrueになる。isStartedがfalseの場合はそのフレームでのupdate処理をスキップする。
イベントでSceneManager.gotoなど次画面への移動が決定後、isBusyの判定を行う。主にフェード処理などすぐに次画面に移動すると違和感のある処理が終了するまでtrueとなるが独自に処理を続行してもよい。falseになることで次のterminateを実行する。
フローチャートだと以下のようになる。
関連リンク
当サイトのRPGツクールMZプラグイン開発のトップページ。他の記事へのリンクをまとめている。