mcpField
S
scenes

scenes

github.com/phaserjs開発40.6k973 回インストール10 週間前に更新
リポジトリ

scenes について

Phaser 開発者向けに、シーンのライフサイクル、注入されるシステム、ScenePlugin による複数シーンの管理を解説するリファレンスです。ゲームの流れやシーン遷移、並行実行の整理に役立ちます。

主な機能

  1. 01シーンのライフサイクルと状態管理
  2. 02シーン固有および共有システム
  3. 03シーンの開始、一時停止、休止、再開
  4. 04シーン間のデータとイベントの受け渡し

活用シーン

  1. 01レベルやメニューのシーン構成
  2. 02ゲーム UI シーンの並行実行
  3. 03シーン遷移時のゲームデータ受け渡し

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/phaserjs/phaser --skill scenes

インストール後、Claude Code で/scenesを入力して読み込まれたか確認します。

同梱ファイルreferences/REFERENCE.md

詳細

シーン

シーンは Phaser ゲームの組織的なバックボーンです。各シーンは独自のライフサイクル (init、preload、create、update) と、独自の注入されたシステム (this.add、this.input、this.cameras など) を持ち、開始、停止、一時停止、スリープ、または他のシーンとの並列実行が可能です。ScenePlugin (this.scene) がすべてのマルチシーンオーケストレーションを制御します。

主要なソースパス: src/scene/Scene.js、src/scene/Systems.js、src/scene/SceneManager.js、src/scene/ScenePlugin.js、src/scene/Settings.js、src/scene/const.js、src/scene/events/、src/scene/InjectionMap.js 関連スキル: ../game-setup-and-config/SKILL.md、../loading-assets/SKILL.md、../events-system/SKILL.md

クイックスタート

// Minimal scene with all lifecycle methods
class GameScene extends Phaser.Scene {
    constructor() {
        super('GameScene');
    }

    init(data) {
        // Called first. Receives data passed from other scenes.
        // 'data' is whatever was passed via scene.start('GameScene', { level: 1 })
        this.level = data.level || 1;
    }

    preload() {
        // Called after init. Load assets here.
        this.load.image('logo', 'assets/logo.png');
    }

    create(data) {
        // Called after preload completes. Set up game objects.
        // 'data' is the same object passed to init.
        this.add.image(400, 300, 'logo');
    }

    update(time, delta) {
        // Called every frame while scene is RUNNING.
        // time: current time (ms), delta: ms since last frame (smoothed)
    }
}

const config = {
    width: 800,
    height: 600,
    scene: [GameScene]
};

const game = new Phaser.Game(config);

コアコンセプト

シーンのライフサイクル

ライフサイクルは SceneManager.bootScene() と SceneManager.create() によって駆動されます:

  1. PENDING (0) - シーンは登録されていますが、まだ開始されていません。
  2. INIT (1) - 定義されている場合、scene.init(data) が呼び出されます。データは settings.data から渡されます。
  3. START (2) - Systems.start() が実行されます。start と ready イベントが発行されます。
  4. LOADING (3) - 定義されている場合、scene.preload() が呼び出されます。ローダーが実行されます。完了すると、create へ進みます。
  5. CREATING (4) - 定義されている場合、scene.create(data) が呼び出されます。init と同じ data です。
  6. RUNNING (5) - 毎フレーム scene.update(time, delta) が呼び出されます。シーンがレンダリングされます。
  7. PAUSED (6) - update は行われませんが、レンダリングは続行されます。
  8. SLEEPING (7) - update もレンダリングも行われません。状態はメモリ内に保持されます。
  9. SHUTDOWN (8) - シーンがシャットダウンされ、システムが shutdown を発行します。再起動できます。
  10. DESTROYED (9) - シーンが完全に破棄されます。再起動はできません。

状態定数は Phaser.Scenes にあります: Phaser.Scenes.PENDING、Phaser.Scenes.RUNNING など。

preload が存在しない場合のフロー: init() -> create() -> update() ループ (preload は完全にスキップされます)。

preload が存在する場合のフロー: init() -> preload() -> ローダーが実行 -> create() -> update() ループ。

シーンに注入されるプロパティ

これらのプロパティは InjectionMap (src/scene/InjectionMap.js) を介してすべてのシーンインスタンスに注入されます。左側が Systems のキー、右側がシーンのプロパティ名です。

グローバルマネージャー (すべてのシーンで共有)
シーンプロパティ型説明
this.gamePhaser.GameGame インスタンス
this.rendererCanvasRenderer | WebGLRendererアクティブなレンダラー
this.animsPhaser.Animations.AnimationManagerグローバルアニメーションマネージャー
this.cachePhaser.Cache.CacheManager画像以外のアセット用のグローバルキャッシュ
this.pluginsPhaser.Plugins.PluginManagerグローバルプラグインマネージャー
this.registryPhaser.Data.DataManagerグローバルデータマネージャー (シーン間で共有)
this.scalePhaser.Scale.ScaleManagerグローバルスケールマネージャー
this.soundNoAudio | HTML5Audio | WebAudioSoundManagerサウンドマネージャー
this.texturesPhaser.Textures.TextureManagerグローバルテクスチャマネージャー
シーン固有のシステム(シーンごとに固有)
シーンプロパティ型説明
this.sysPhaser.Scenes.Systemsシーンシステム(上書きしないでください)
this.eventsPhaser.Events.EventEmitterシーン固有のイベントエミッター
this.camerasPhaser.Cameras.Scene2D.CameraManagerシーンカメラマネージャー
this.addPhaser.GameObjects.GameObjectFactoryファクトリー:作成して表示リストに追加します
this.makePhaser.GameObjects.GameObjectCreatorクリエイター:作成しますが表示リストには追加しません
this.scenePhaser.Scenes.ScenePluginシーンマネージャープラグイン(start/stop/launch)
this.childrenPhaser.GameObjects.DisplayListシーンの表示リスト
this.lightsPhaser.GameObjects.LightsManagerシーンライト(プラグイン)
this.dataPhaser.Data.DataManagerシーン固有のデータマネージャー
this.inputPhaser.Input.InputPluginシーン入力マネージャー(プラグイン)
this.loadPhaser.Loader.LoaderPluginシーンローダー(プラグイン)
this.timePhaser.Time.Clockシーンの時間/クロック(プラグイン)
this.tweensPhaser.Tweens.TweenManagerシーンのトゥイーンマネージャー(プラグイン)
this.physicsPhaser.Physics.Arcade.ArcadePhysicsArcade 物理(設定されている場合)
this.matterPhaser.Physics.Matter.MatterPhysicsMatter 物理(設定されている場合)
インジェクションマップのカスタマイズ
// Rename injected properties via scene config
const config = {
    key: 'MyScene',
    map: {
        add: 'makeStuff',   // this.makeStuff instead of this.add
        load: 'loader'      // this.loader instead of this.load
    }
};
シーンマネージャー

SceneManager(src/scene/SceneManager.js)はゲームレベルのシステムです。そのメソッドを直接呼び出さないでください。代わりに this.scene(ScenePlugin)を使用してください。SceneManager は次のことを行います:

  • シーの順序付き配列を維持します(レンダリング/更新の順序を決定します)
  • 各ゲームステップの開始時に操作(start、stop、sleep など)のキューを処理します
  • すべての ScenePlugin メソッドはキューに入れられ、即時ではなく(次のフレームで)実行されます

一般的なパターン

シーンの切り替え
// start() -- shuts down current scene, starts target scene
// Current scene gets SHUTDOWN event; target gets full lifecycle
this.scene.start('LevelTwo', { score: 100 });

// restart() -- shuts down and restarts the same scene
this.scene.restart({ score: 0 });

// switch() -- sleeps current scene, starts/wakes target scene
// Current scene state is preserved in memory
this.scene.switch('PauseMenu', { fromScene: 'GameScene' });

// transition() -- animated transition with duration
this.scene.transition({
    target: 'LevelTwo',
    duration: 1000,
    moveAbove: true,        // render target above this scene
    sleep: false,           // false = stop this scene (default), true = sleep it
    remove: false,          // true = remove this scene from manager after transition
    allowInput: false,      // allow input on this scene during transition
    data: { score: 100 },
    onUpdate: function (progress) {
        // progress: 0 to 1 over duration
    }
});
シーンの並列実行
// launch() -- starts another scene in parallel (does NOT stop current scene)
this.scene.launch('UIScene', { lives: 3 });

// run() -- smart launcher: starts if not running, resumes if paused, wakes if sleeping
this.scene.run('UIScene', { lives: 3 });

// Control render order of parallel scenes
this.scene.bringToTop('UIScene');      // render last (on top)
this.scene.sendToBack('Background');   // render first (behind)
this.scene.moveAbove('GameScene', 'UIScene');  // UIScene renders above GameScene
this.scene.moveBelow('GameScene', 'Background');
this.scene.moveUp('UIScene');          // move one position up
this.scene.moveDown('UIScene');        // move one position down
this.scene.swapPosition('SceneA', 'SceneB');
シーン間でのデータの受け渡し
// Method 1: Pass data via start/launch/restart/switch/wake/run
this.scene.start('LevelScene', { level: 5, score: 1200 });
// In LevelScene:
// init(data) { data.level === 5 }
// create(data) { data.score === 1200 }

// Method 2: Access data later via sys.getData()
// In receiving scene, at any time:
const data = this.sys.getData(); // returns settings.data

// Method 3: Global registry (shared across ALL scenes)
// In Scene A:
this.registry.set('playerHP', 100);
// In Scene B:
const hp = this.registry.get('playerHP'); // 100

// Method 4: Scene-specific data manager
this.data.set('localValue', 42);
this.data.get('localValue'); // 42

// Method 5: Direct scene reference
const otherScene = this.scene.get('OtherScene');
otherScene.somePublicProperty;

// Method 6: Events on the global registry
// In Scene A:
this.registry.events.on('changedata-playerHP', (parent, value, previousValue) => {
    // react to change
});
// In Scene B:
this.registry.set('playerHP', 50); // triggers the event in Scene A
一時停止と再開
// Pause: stops update loop, still renders
this.scene.pause();               // pause this scene
this.scene.pause('OtherScene');   // pause another scene

// Resume: restart update loop
this.scene.resume();
this.scene.resume('OtherScene', { message: 'welcome back' });

// Sleep: no update AND no render, but state preserved
this.scene.sleep();
this.scene.sleep('OtherScene');

// Wake: restore from sleep
this.scene.wake();
this.scene.wake('OtherScene', { data: 'here' });

// Stop: full shutdown, clears display list and timers
this.scene.stop();
this.scene.stop('OtherScene');

// Check state
this.scene.isActive('OtherScene');    // boolean
this.scene.isPaused('OtherScene');    // boolean
this.scene.isSleeping('OtherScene');  // boolean
this.scene.isVisible('OtherScene');   // boolean

// Control visibility/activity independently
this.scene.setActive(false);          // pause
this.scene.setActive(true);           // resume
this.scene.setVisible(false);         // hide but still update
this.scene.setVisible(true);          // show
実行時のシーンの追加と削除
// Add a new scene dynamically
this.scene.add('BonusLevel', BonusLevelScene, false, { someData: true });
// args: key, sceneConfig, autoStart, data

// Remove a scene entirely (destroyed, cannot be restarted)
this.scene.remove('BonusLevel');

// Spawn multiple instances from one class
for (let i = 0; i < 5; i++) {
    this.scene.add('Level' + i, new LevelScene('Level' + i), false);
}
シーン間のイベント通信

あるシーンがカスタムイベントを発行し、別のシーンがそれをリッスンします。発行するシーンは分離されています。

// GameScene emits events
class GameScene extends Phaser.Scene {
    collectCoin(coin) {
        coin.destroy();
        this.events.emit('addScore', 10);
    }
}

// UIScene listens (launched in parallel with { active: true })
class UIScene extends Phaser.Scene {
    constructor() {
        super({ key: 'UIScene', active: true });
    }

    create() {
        this.score = 0;
        this.scoreText = this.add.text(10, 10, 'Score: 0');

        // Listen for events from GameScene
        const gameScene = this.scene.get('GameScene');
        gameScene.events.on('addScore', (points) => {
            this.score += points;
            this.scoreText.setText('Score: ' + this.score);
        });
    }
}
シーンごとのプラグインの設定

すべてのデフォルトプラグインを無効化します(コアプラグインのみが残ります):

super({ key: 'MinimalScene', plugins: [] });
// No this.load, this.tweens, this.time, this.input, this.data, this.lights

特定のプラグインのみを含めます:

super({ key: 'PreloadScene', plugins: ['Loader'] });
// Only this.load is available; this.tweens, this.time, etc. are undefined
コンストラクターでのシーン設定

シーンごとの物理、ローダー、または事前読み込みファイルのために super() に設定を渡します:

class Level1 extends Phaser.Scene {
    constructor() {
        super({
            key: 'Level1',
            physics: { arcade: { debug: true, gravity: { y: 200 } } },
            loader: { path: 'assets/levels/1/' },
            // 'pack' loads files before preload() runs -- good for progress bar assets
            pack: {
                files: [
                    { type: 'image', key: 'bar', url: 'loaderBar.png' }
                ]
            }
        });
    }
}
シーンの安全な再起動

状態はコンストラクターではなく init() でリセットします。コンストラクターは一度だけ実行され、init() は開始するたびに実行されます。

class GameScene extends Phaser.Scene {
    constructor() {
        super('GameScene');
        // BAD: this.gameOver = false; -- only set once, not on restart
    }

    init() {
        // GOOD: reset state every time the scene starts
        this.gameOver = false;
        this.score = 0;
    }

    create() {
        // Clean up on shutdown to avoid stale references
        this.events.once('shutdown', () => {
            // Clear any arrays holding game object references
            this.enemies = [];
        });
    }
}

イベント

すべてのイベントは this.events(シーン固有の EventEmitter)で発行され、文字列の値を持ちます。this.events.on('eventname', callback) でリッスンします。

ライフサイクルイベント
イベント文字列定数コールバックシグネチャタイミング
'boot'Phaser.Scenes.Events.BOOT(sys)シーンが最初にインスタンス化されるときに一度(プラグイン用)
'start'Phaser.Scenes.Events.START(sys)シーンシステムの開始時(プラグイン用)
'ready'Phaser.Scenes.Events.READY(sys, data)開始後、ユーザーコード用
'create'Phaser.Scenes.Events.CREATE(scene)create() メソッドの実行後、シーンは RUNNING 状態になります
'preupdate'Phaser.Scenes.Events.PRE_UPDATE(time, delta)毎フレームの update 前
'update'Phaser.Scenes.Events.UPDATE(time, delta)毎フレームの update 中
'postupdate'Phaser.Scenes.Events.POST_UPDATE(time, delta)毎フレームの update 後
'prerender'Phaser.Scenes.Events.PRE_RENDER(renderer)シーンのレンダリング前
'render'Phaser.Scenes.Events.RENDER(renderer)シーンのレンダリング後
状態変更イベント
イベント文字列定数コールバックシグネチャ発生タイミング
'pause'Phaser.Scenes.Events.PAUSE(sys, data)シーンが一時停止されたとき
'resume'Phaser.Scenes.Events.RESUME(sys, data)シーンが再開されたとき
'sleep'Phaser.Scenes.Events.SLEEP(sys, data)シーンがスリープ状態になったとき
'wake'Phaser.Scenes.Events.WAKE(sys, data)シーンが復帰したとき
'shutdown'Phaser.Scenes.Events.SHUTDOWN(sys, data)シーンがシャットダウン中のとき
'destroy'Phaser.Scenes.Events.DESTROY(sys)シーンが破棄されているとき
遷移イベント
イベント文字列定数コールバックシグネチャ発行元
'transitionout'TRANSITION_OUT(targetScene, duration)遷移元シーン
'transitioninit'TRANSITION_INIT(fromScene, duration)遷移先シーン(init 中)
'transitionstart'TRANSITION_START(fromScene, duration)遷移先シーン(create 後)
'transitionwake'TRANSITION_WAKE(fromScene, duration)遷移先シーン(スリープから復帰した場合)
'transitioncomplete'TRANSITION_COMPLETE(scene)遷移先シーン(完了時)
ゲームオブジェクトイベント
イベント文字列定数コールバックシグネチャ
'addedtoscene'ADDED_TO_SCENE(gameObject, scene)
'removedfromscene'REMOVED_FROM_SCENE(gameObject, scene)

詳細な API リファレンスの表とソースファイルの対応については、リファレンスガイドを参照してください。

落とし穴とよくある間違い

  1. 操作はキューに入れられ、即時には実行されません。 this.scene.start('X') を呼び出しても、X が同期的に開始されるわけではありません。これは次の SceneManager の更新時に行われます。同じフレーム内でターゲットシーンの状態に依存しないでください。

  2. start() は呼び出し元のシーンをシャットダウンします。 this.scene.start('X') は現在のシーンを停止し、X を開始します。両方を実行させたい場合は、launch() または run() を使用してください。

  3. switch() はスリープさせ、start() はシャットダウンします。 switch() は現在のシーンをメモリ内に保持し(スリープ)、start() は完全なシャットダウンを引き起こします。スリープ中のシーンでも、そのイベントと参照は生きたままです。

  4. 一時停止したシーンも依然としてレンダリングされます。 pause() は更新ループを停止するだけです。シーンは依然として描画されます。更新とレンダリングの両方を停止するには sleep() を使用してください。

  5. this.sys を上書きしないでください。 Scene クラスの JSDoc は明示的に警告しています。this.sys を上書きするとすべてが壊れます。

  6. キーを指定せずに this.scene.start() を呼び出すと、現在のシーンが再起動されます。 これは this.scene.restart() と同等です。

  7. start()/launch() に渡されたデータは、init(data) と create(data) の両方で利用できます。 これは settings.data に保存され、後で this.sys.getData() を介してアクセスできます。

  8. スリープ中のシーンも他のシーンからイベントを受信できます。 シーン A がスリープ中でも、シーン B がグローバルレジストリでイベントを発行すると、シーン A のリスナーは依然として発火します。スリープ中のシーンにあるアクティブなリスナーには注意してください。

  9. シーンのレンダリング順序 = 配列の順序です。 配列内で後にあるシーンほど上にレンダリングされます。レイヤリングを制御するには bringToTop()、sendToBack()、moveAbove()、moveBelow() を使用してください。

  10. shutdown と destroy の違い。 シャットダウンはシーンを休止状態にします(再起動可能)。destroy はシーンを完全に削除します。再起動時に再作成すべきリソースを解放するには 'shutdown' をリッスンしてください。最終的なクリーンアップには 'destroy' をリッスンしてください。

  11. this.physics や this.matter のようなプラグインプロパティは、物理システムが構成されている場合にのみ利用できます。 それ以外の場合は undefined になります。

  12. create イベントは、create() メソッドが戻った後、ステータスが RUNNING に変わった後に発火します。 create 後のセットアップを行う必要がある場合は、このイベントをリッスンしてください。

  13. 状態のリセットはコンストラクターではなく init() で行ってください。 コンストラクターはシーンが最初にインスタンス化されたときに一度だけ実行されます。init() はシーンが開始/再起動されるたびに実行されます。状態のリセットはそこに配置してください。

  14. 古い参照を避けるために shutdown でクリーンアップしてください。 ゲームオブジェクトを保持する配列のクリア、外部イベントリスナーの削除などを行うには、this.events.once('shutdown', ...) をリッスンしてください。破棄されたゲームオブジェクトへの古い参照は、再起動時にエラーを引き起こします。

  15. switch() は一時停止したシーンを再起動し、決して再開しません。 再開動作が必要な場合は、代わりに run() を使用してください。

  16. シーンは逆順で更新され、順方向にレンダリングされます。 最上位のシーンは最初に更新され(入力の優先権を取得)、最後にレンダリングされます(上に表示されます)。ゲーム設定のシーン配列でレンダリング順序を設定してください。

コメント