mcpField
E
events-system

events-system

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

events-system について

Phaser 開発者向けのイベントシステムのスキルガイドです。フレームワーク各部でのイベント購読、発火、解除の方法と、主なイベント名前空間を解説します。

主な機能

  1. 01イベントの購読と発火
  2. 02名前付きイベント定数の利用
  3. 03コールバックのコンテキスト設定
  4. 04シーンのライフサイクル監視
  5. 05イベント名前空間の参照

活用シーン

  1. 01ポインター入力やドラッグへの対応
  2. 02シーンの開始と終了の処理
  3. 03イベントによるシーン間通信
  4. 04ロードやアニメーション状態の追跡

インストール

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

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

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

詳細

イベントシステム

Phaser はフレームワーク全体を通じて EventEmitter パターン(eventemitter3 経由)を使用しています。Game、Scene、Input、Loader、Cameras、Sound、Tweens、Physics、Textures、Animations といった主要なシステムはすべて、EventEmitter であるか、EventEmitter を含んでいます。イベントは小文字の文字列キーを使用します。Phaser は、タイプミスを防ぎ IDE のオートコンプリートを有効にするために、すべての組み込みイベントに対して名前付き定数を提供しています。

主要なソースパス: src/events/EventEmitter.js, src/scene/events/, src/core/events/, src/input/events/, src/loader/events/, src/animations/events/, src/cameras/2d/events/, src/sound/events/, src/tweens/events/, src/physics/arcade/events/, src/textures/events/, src/gameobjects/events/, src/time/events/ 関連スキル: ../scenes/SKILL.md, ../input-keyboard-mouse-touch/SKILL.md

クイックスタート

// on — listen for an event (persists until removed)
this.input.on('pointerdown', (pointer) => {
    console.log('clicked at', pointer.x, pointer.y);
});

// once — listen for an event, auto-removes after first fire
this.events.once('shutdown', () => {
    console.log('scene shutting down');
});

// off — remove a specific listener (must pass same function reference)
const handler = (pointer) => { /* ... */ };
this.input.on('pointerdown', handler);
this.input.off('pointerdown', handler);

// emit — fire a custom event with arguments
this.events.emit('player-died', this.player, this.score);

// removeAllListeners — remove all listeners for an event (or all events)
this.events.removeAllListeners('player-died');
this.events.removeAllListeners(); // all events
名前付き定数の使用(推奨)
// Always prefer constants over raw strings to prevent typos
this.events.on(Phaser.Scenes.Events.UPDATE, (time, delta) => {
    // runs every frame
});

this.input.on(Phaser.Input.Events.POINTER_DOWN, (pointer) => {
    // pointer pressed
});

this.game.events.on(Phaser.Core.Events.BLUR, () => {
    // browser tab lost focus
});

中核となる概念

EventEmitter 基底クラス

Phaser.Events.EventEmitter は eventemitter3 を拡張します。どちらも removeAllListeners() を呼び出す shutdown() および destroy() メソッドを追加します。

完全な API(eventemitter3 から継承):

メソッド説明
on(event, fn, context?)永続的なリスナーを追加します。チェーン用に this を返します
addListener(event, fn, context?)on のエイリアス
once(event, fn, context?)一度だけのリスナーを追加します。最初の発火後に自動的に削除されます
off(event, fn?, context?, once?)リスナーを削除します。特定のリスナーを削除するには同じ fn 参照を渡す必要があります
removeListener(event, fn?, context?, once?)off のエイリアス
removeAllListeners(event?)イベントのすべてのリスナーを削除します。引数がない場合はすべてのイベントを削除します
emit(event, ...args)イベントを発火します。リスナーがあった場合は true を返します
listeners(event)イベントのリスナー関数の配列を返します
listenerCount(event)イベントのリスナー数を返します
eventNames()リスナーを持つイベント名の配列を返します
shutdown()removeAllListeners() を呼び出します
destroy()removeAllListeners() を呼び出します
イベント文字列と定数

すべての組み込みイベントは、定数としてエクスポートされた小文字の文字列です。定数名は文字列に予測可能に対応します:

Phaser.Scenes.Events.UPDATE        // 'update'
Phaser.Scenes.Events.PRE_UPDATE    // 'preupdate'
Phaser.Scenes.Events.SHUTDOWN      // 'shutdown'
Phaser.Core.Events.BOOT            // 'boot'
Phaser.Input.Events.POINTER_DOWN   // 'pointerdown'

一部のイベントは、キーごとのリッスンにキーサフィックスパターンを使用します:

// Loader: listen for a specific file completing
this.load.on(Phaser.Loader.Events.FILE_KEY_COMPLETE + 'image-logo', (key, type, data) => {});
// String value: 'filecomplete-image-logo'

// Animations: listen for a specific animation completing on a sprite
sprite.on(Phaser.Animations.Events.ANIMATION_COMPLETE_KEY + 'walk', () => {});
// String value: 'animationcomplete-walk'

// Textures: listen for a specific texture being added
this.textures.on(Phaser.Textures.Events.ADD_KEY + 'myTexture', () => {});
// String value: 'addtexture-myTexture'
コンテキスト(第3引数)

on/once の第3引数は、コールバック内の this を設定します。デフォルトはエミッターです。

// 'this' inside handler refers to the scene
this.input.on('pointerdown', function (pointer) {
    this.cameras.main.shake(100); // 'this' = scene
}, this);

// Arrow functions ignore the context argument (they capture lexical 'this')
this.input.on('pointerdown', (pointer) => {
    this.cameras.main.shake(100); // 'this' = enclosing scope (scene in create)
});

一般的なパターン

シーンライフサイクルイベント

フレームループの順序:preupdate -> update -> Scene.update() -> postupdate -> prerender -> render

create() {
    this.events.on(Phaser.Scenes.Events.UPDATE, this.onUpdate, this);
    // CRITICAL: always clean up on shutdown to prevent leaks on scene restart
    this.events.on(Phaser.Scenes.Events.SHUTDOWN, () => {
        this.events.off(Phaser.Scenes.Events.UPDATE, this.onUpdate, this);
        this.input.off('pointerdown', this.onPointerDown, this);
    });
}
ゲームレベルのイベント
// game.events fires on the Game instance, shared across all scenes
// Access from a scene via this.game.events
this.game.events.on(Phaser.Core.Events.BLUR, this.handleBlur, this);
this.game.events.on(Phaser.Core.Events.VISIBLE, this.handleVisible, this);
シーン間の通信
// METHOD 1: game.events — a global event bus accessible from all scenes
// Scene A emits:
this.game.events.emit('score-changed', this.score);
// Scene B listens:
this.game.events.on('score-changed', (score) => { this.scoreText.setText(score); });

// METHOD 2: this.registry — a shared DataManager across all scenes
// The registry is a Phaser.Data.DataManager on the Game instance.
// Scene A sets data:
this.registry.set('score', 100);
// Scene B listens for changes:
this.registry.events.on('changedata-score', (parent, value, previousValue) => {
    this.scoreText.setText(value);
});

// METHOD 3: Direct scene access via ScenePlugin
this.scene.get('UIScene').events.emit('update-health', hp);
カスタムイベント
// Emit custom events with arbitrary data arguments
this.events.emit('player-died', this.player, { lives: this.lives });
this.events.on('player-died', (player, data) => {
    console.log('Lives remaining:', data.lives);
});

すべてのイベント名前空間リファレンス

シーンイベント (Phaser.Scenes.Events)

エミッター: this.events (シーンの Systems EventEmitter)

定数文字列タイミング
BOOT'boot'シーン Systems の起動時 (プラグイン向け)
READY'ready'シーン Systems が完全に準備完了
START'start'シーンの実行開始時
CREATE'create'Scene.create() の完了後
PRE_UPDATE'preupdate'毎フレームの update 前
UPDATE'update'毎フレームのメイン update
POST_UPDATE'postupdate'毎フレームの update 後
PRE_RENDER'prerender'毎フレームのレンダリング前
RENDER'render'毎フレームのレンダリング中
PAUSE'pause'シーンが一時停止された
RESUME'resume'シーンが一時停止から再開された
SLEEP'sleep'シーンがスリープ状態になった
WAKE'wake'シーンがスリープから復帰した
SHUTDOWN'shutdown'シーンがシャットダウン中 (再起動の可能性あり)
DESTROY'destroy'シーンが完全に破棄された
ADDED_TO_SCENE'addedtoscene'GameObject がシーンに追加された
REMOVED_FROM_SCENE'removedfromscene'GameObject がシーンから削除された
TRANSITION_INIT'transitioninit'トランジションが初期化された (対象シーン)
TRANSITION_START'transitionstart'トランジションが開始された (対象シーン)
TRANSITION_OUT'transitionout'トランジションのアウト (元のシーン)
TRANSITION_COMPLETE'transitioncomplete'トランジションが完了した
TRANSITION_WAKE'transitionwake'トランジションが対象シーンを復帰させた
ゲームイベント (Phaser.Core.Events)

エミッター: this.game.events または game.events

定数文字列タイミング
BOOT'boot'ゲームインスタンスの起動が完了した
READY'ready'ゲームの実行開始準備完了
SYSTEM_READY'systemready'すべてのグローバル Systems の準備完了
PRE_STEP'prestep'ゲームループのステップ前
STEP'step'メインゲームループのステップ
POST_STEP'poststep'ゲームループのステップ後
PRE_RENDER'prerender'すべてのシーンのレンダリング前
POST_RENDER'postrender'すべてのシーンのレンダリング後
PAUSE'pause'ゲームが一時停止された
RESUME'resume'ゲームが再開された
BLUR'blur'ブラウザタブがフォーカスを失った
FOCUS'focus'ブラウザタブがフォーカスを得た
HIDDEN'hidden'Page Visibility API: 非表示
VISIBLE'visible'Page Visibility API: 表示
CONTEXT_LOST'contextlost'WebGL コンテキストが失われた
DESTROY'destroy'ゲームが破棄されようとしている
入力イベント (Phaser.Input.Events)

エミッター: this.input (シーンレベル) または個々の GameObject。イベントは 3 つのレベルで存在します: シーンレベル (this.input)、gameobject プレフィックス付きのシーンレベル、そしてインタラクティブな GameObject に直接です。詳しい使い方は ../input-keyboard-mouse-touch/SKILL.md を参照してください。

シーンレベルのポインターイベント (this.input 上): POINTER_DOWN 'pointerdown' | POINTER_UP 'pointerup' | POINTER_MOVE 'pointermove' | POINTER_OVER 'pointerover' | POINTER_OUT 'pointerout' | POINTER_WHEEL 'wheel' | POINTER_DOWN_OUTSIDE 'pointerdownoutside' | POINTER_UP_OUTSIDE 'pointerupoutside'

シーンレベルの gameobject イベント (this.input 上): GAMEOBJECT_DOWN 'gameobjectdown' | GAMEOBJECT_UP 'gameobjectup' | GAMEOBJECT_MOVE 'gameobjectmove' | GAMEOBJECT_OVER 'gameobjectover' | GAMEOBJECT_OUT 'gameobjectout' | GAMEOBJECT_WHEEL 'gameobjectwheel'

GameObject ごとのイベント (GameObject 自体で発行され、setInteractive() が必要): GAMEOBJECT_POINTER_DOWN 'pointerdown' | GAMEOBJECT_POINTER_UP 'pointerup' | GAMEOBJECT_POINTER_MOVE 'pointermove' | GAMEOBJECT_POINTER_OVER 'pointerover' | GAMEOBJECT_POINTER_OUT 'pointerout' | GAMEOBJECT_POINTER_WHEEL 'wheel'

ドラッグイベント (this.input 上、および同じ文字列を持つ GameObject 上): DRAG_START/GAMEOBJECT_DRAG_START 'dragstart' | DRAG/GAMEOBJECT_DRAG 'drag' | DRAG_END/GAMEOBJECT_DRAG_END 'dragend' | DRAG_ENTER/GAMEOBJECT_DRAG_ENTER 'dragenter' | DRAG_OVER/GAMEOBJECT_DRAG_OVER 'dragover' | DRAG_LEAVE/GAMEOBJECT_DRAG_LEAVE 'dragleave' | DROP/GAMEOBJECT_DROP 'drop'

その他: GAME_OUT 'gameout' | GAME_OVER 'gameover' | POINTERLOCK_CHANGE 'pointerlockchange'

ローダーイベント (Phaser.Loader.Events)

エミッター: this.load

定数文字列タイミング
ADD'addfile'ファイルがロードキューに追加されたとき
START'start'ローダーが開始したとき
PROGRESS'progress'全体の進捗が更新されたとき (0-1)
FILE_LOAD'load'個々のファイルがロードされたとき
FILE_PROGRESS'fileprogress'個々のファイルの進捗
FILE_COMPLETE'filecomplete'個々のファイルの処理が完了したとき
FILE_KEY_COMPLETE'filecomplete-'特定のファイルが完了したとき (type-key を追加)
FILE_LOAD_ERROR'loaderror'ファイルのロードに失敗したとき
POST_PROCESS'postprocess'すべてのファイルがロードされ、ポストプロセス中
COMPLETE'complete'すべてのロードが完了したとき
アニメーションイベント (Phaser.Animations.Events)

エミッター: 個々のスプライト (スプライトごと) または this.anims (グローバルな AnimationManager)

定数文字列タイミング
ADD_ANIMATION'add'アニメーションがマネージャーに追加されたとき
REMOVE_ANIMATION'remove'アニメーションがマネージャーから削除されたとき
PAUSE_ALL'pauseall'すべてのアニメーションが一時停止されたとき
RESUME_ALL'resumeall'すべてのアニメーションが再開されたとき
ANIMATION_START'animationstart'スプライトでアニメーションの再生が開始されたとき
ANIMATION_RESTART'animationrestart'スプライトでアニメーションが再開されたとき
ANIMATION_REPEAT'animationrepeat'スプライトでアニメーションが繰り返されたとき
ANIMATION_UPDATE'animationupdate'スプライトでアニメーションフレームが変化したとき
ANIMATION_COMPLETE'animationcomplete'スプライトでアニメーションが終了したとき
ANIMATION_COMPLETE_KEY'animationcomplete-'特定のアニメーションが終了したとき (キーを追加)
ANIMATION_STOP'animationstop'スプライトでアニメーションが停止されたとき
カメライベント (Phaser.Cameras.Scene2D.Events)

エミッター: 個々のカメラインスタンス (例: this.cameras.main)。各カメラエフェクトには START と COMPLETE のペアがあります。

DESTROY 'cameradestroy' | FADE_IN_START 'camerafadeinstart' | FADE_IN_COMPLETE 'camerafadeincomplete' | FADE_OUT_START 'camerafadeoutstart' | FADE_OUT_COMPLETE 'camerafadeoutcomplete' | FLASH_START 'cameraflashstart' | FLASH_COMPLETE 'cameraflashcomplete' | PAN_START 'camerapanstart' | PAN_COMPLETE 'camerapancomplete' | ROTATE_START 'camerarotatestart' | ROTATE_COMPLETE 'camerarotatecomplete' | SHAKE_START 'camerashakestart' | SHAKE_COMPLETE 'camerashakecomplete' | ZOOM_START 'camerazoomstart' | ZOOM_COMPLETE 'camerazoomcomplete' | FOLLOW_UPDATE 'followupdate' | PRE_RENDER 'prerender' | POST_RENDER 'postrender'

サウンドイベント (Phaser.Sound.Events)

エミッター: 個々のサウンドインスタンス、または this.sound (SoundManager)

サウンドインスタンスごとのイベント: PLAY 'play' | PAUSE 'pause' | RESUME 'resume' | STOP 'stop' | COMPLETE 'complete' | LOOP 'loop' | LOOPED 'looped' | SEEK 'seek' | MUTE 'mute' | VOLUME 'volume' | RATE 'rate' | DETUNE 'detune' | PAN 'pan' | DECODED 'decoded' | DESTROY 'destroy'

SoundManager レベルのイベント (this.sound 上): GLOBAL_MUTE 'mute' | GLOBAL_VOLUME 'volume' | GLOBAL_RATE 'rate' | GLOBAL_DETUNE 'detune' | PAUSE_ALL 'pauseall' | RESUME_ALL 'resumeall' | STOP_ALL 'stopall' | DECODED_ALL 'decodedall' | UNLOCKED 'unlocked'

トゥイーンイベント (Phaser.Tweens.Events)

エミッター: 個々のトゥイーンインスタンス

定数文字列発生タイミング
TWEEN_ACTIVE'active'トゥイーンがアクティブになる
TWEEN_START'start'トゥイーンが最初の再生を開始する
TWEEN_UPDATE'update'トゥイーンが値を更新する
TWEEN_YOYO'yoyo'トゥイーンがヨーヨーする (方向を反転する)
TWEEN_REPEAT'repeat'トゥイーンがリピートする
TWEEN_LOOP'loop'トゥイーンがループする
TWEEN_PAUSE'pause'トゥイーンが一時停止する
TWEEN_RESUME'resume'トゥイーンが再開する
TWEEN_COMPLETE'complete'トゥイーンが完了する
TWEEN_STOP'stop'トゥイーンが手動で停止される
Arcade Physics イベント (Phaser.Physics.Arcade.Events)

エミッター: this.physics.world

定数文字列発生タイミング
COLLIDE'collide'2 つのボディが衝突する
OVERLAP'overlap'2 つのボディが重なる
TILE_COLLIDE'tilecollide'ボディがタイルと衝突する
TILE_OVERLAP'tileoverlap'ボディがタイルと重なる
WORLD_BOUNDS'worldbounds'ボディがワールドの境界に達する
WORLD_STEP'worldstep'物理ワールドが 1 ステップ完了する
PAUSE'pause'物理ワールドが一時停止する
RESUME'resume'物理ワールドが再開する
テクスチャイベント (Phaser.Textures.Events)

エミッター: this.textures (TextureManager)

定数文字列発生タイミング
ADD'addtexture'任意のテクスチャが追加される
ADD_KEY'addtexture-'特定のテクスチャが追加される (キーを付加)
REMOVE'removetexture'任意のテクスチャが削除される
REMOVE_KEY'removetexture-'特定のテクスチャが削除される (キーを付加)
LOAD'onload'テクスチャソースが読み込まれる
ERROR'onerror'テクスチャソースの読み込みエラー
READY'ready'テクスチャマネージャーが準備完了
GameObject イベント (Phaser.GameObjects.Events)

エミッター: 個々の GameObject

定数文字列発生タイミング
ADDED_TO_SCENE'addedtoscene'GameObject がシーンに追加されたとき
REMOVED_FROM_SCENE'removedfromscene'GameObject がシーンから削除されたとき
DESTROY'destroy'GameObject が破棄されたとき

Video GameObject イベント (Video GameObject 上): VIDEO_PLAY 'play' | VIDEO_PLAYING 'playing' | VIDEO_COMPLETE 'complete' | VIDEO_LOOP 'loop' | VIDEO_STOP 'stop' | VIDEO_CREATED 'created' | VIDEO_ERROR 'error' | VIDEO_LOCKED 'locked' | VIDEO_UNLOCKED 'unlocked' | VIDEO_METADATA 'metadata' | VIDEO_SEEKED 'seeked' | VIDEO_SEEKING 'seeking' | VIDEO_STALLED 'stalled' | VIDEO_TEXTURE 'textureready' | VIDEO_UNSUPPORTED 'unsupported'

Time イベント (Phaser.Time.Events)

エミッター: Phaser.Time.TimerEvent インスタンス

定数文字列発生タイミング
COMPLETE'complete'TimerEvent がすべてのリピートを終了したとき
イベント削除の安全性

on() で使用したものとまったく同じ関数参照 かつ 同じコンテキスト/スコープを off() に渡す必要があります。無名関数やインラインのアロー関数は削除できません。

// BAD: arrow function cannot be removed later
this.events.on('update', () => { this.doStuff(); });

// GOOD: named method can be removed
this.events.on('update', this.onUpdate, this);
this.events.off('update', this.onUpdate, this);
once() は自動削除

once() は最初の発火後にリスナーを自動的に削除します。手動でのクリーンアップは不要です。

this.events.once(Phaser.Scenes.Events.CREATE, this.onFirstCreate, this);
ユーティリティメソッド
emitter.listenerCount('update');          // number of listeners for an event
emitter.eventNames();                      // ['update', 'player-died'] -- all registered event names
emitter.removeAllListeners('player-died'); // remove all listeners for one event
emitter.removeAllListeners();              // remove ALL listeners for ALL events
スタンドアロンの EventEmitter の作成
const bus = new Phaser.Events.EventEmitter();
bus.on('inventory-changed', (items) => { console.log(items.length); });
bus.emit('inventory-changed', this.inventory);
Scene イベントと Game イベント
  • this.events -- シーン固有。シーンのライフサイクルイベントを発火します。シーンが破棄されるとクリーンアップされます。
  • this.game.events -- グローバル。ゲームレベルのイベント (blur、focus、pause、resume) を発火します。シーンの再起動をまたいで持続するため、SHUTDOWN でクリーンアップしてください。
create() {
    this.events.on(Phaser.Scenes.Events.UPDATE, this.onUpdate, this);
    this.game.events.on(Phaser.Core.Events.BLUR, this.onBlur, this);
    this.events.once(Phaser.Scenes.Events.SHUTDOWN, () => {
        this.game.events.off(Phaser.Core.Events.BLUR, this.onBlur, this);
    });
}

注意点

リスナーを削除しないことによるメモリリーク

最も一般的なバグの原因です。シーンで on() を使用し、そのシーンが scene.restart() で再起動すると、on() は自動削除しないため古いリスナーが残り続けます。再起動のたびに重複したリスナーが追加されます。

// BAD: leaks listeners on every scene restart
create() {
    this.input.on('pointerdown', this.shoot, this);
}

// GOOD: clean up in shutdown
create() {
    this.input.on('pointerdown', this.shoot, this);
    this.events.once(Phaser.Scenes.Events.SHUTDOWN, () => {
        this.input.off('pointerdown', this.shoot, this);
    });
}

// ALSO GOOD: use once() for events you only need fired once
create() {
    this.events.once(Phaser.Scenes.Events.CREATE, this.onFirstCreate, this);
}
shutdown と destroy
  • SHUTDOWN はシーンが停止したときに発火しますが、後で再起動できます。ここでリスナーをクリーンアップします。
  • DESTROY はシーンが完全に削除されたときに発火します。最終的なクリーンアップに使用します。
  • シーンの再起動では SHUTDOWN、次に START、次に CREATE が発火します。DESTROY は発火しません。
コンテキストのバインド

on/once の第 3 引数はコールバック内の this を設定します。これがない場合、this はシーンではなくエミッターがデフォルトになります。通常の関数で第 3 引数に this を渡すか、レキシカルな this をキャプチャするアロー関数を使用してください。

off() には正確な参照が必要

off() は、on() で使用したものとまったく同じ関数参照 (およびコンテキスト) を渡した場合にのみ機能します。無名関数やアロー関数リテラルは削除できません。参照を保存するか、クラスメソッドを使用してください。

入力イベントの階層

入力イベントは次の順序で発火します: (1) GameObject 上の GAMEOBJECT_POINTER_DOWN、(2) this.input 上の GAMEOBJECT_DOWN、(3) this.input 上の POINTER_DOWN。上位のハンドラーは伝播を停止できます。

Game イベントと Scene イベント

this.game.events と this.events は異なるエミッターです。Game イベントはすべてのシーンをまたいでゲームループのティックごとに 1 回発火します。Scene イベントはシーンごとに発火します。game.events のリスナーはシーンの再起動をまたいで持続するため、必ず SHUTDOWN でクリーンアップしてください:

create() {
    this.game.events.on(Phaser.Core.Events.BLUR, this.onBlur, this);
    this.events.once(Phaser.Scenes.Events.SHUTDOWN, () => {
        this.game.events.off(Phaser.Core.Events.BLUR, this.onBlur, this);
    });
}

Source File Map

PathDescription
src/events/EventEmitter.jsBase EventEmitter class (wraps eventemitter3)
src/scene/events/Scene lifecycle events (22 events)
src/core/events/Game-level events (16 events)
src/input/events/Input/pointer/drag events (48 events)
src/loader/events/Asset loading events (10 events)
src/animations/events/Animation playback events (11 events)
src/cameras/2d/events/Camera effect events (18 events)
src/sound/events/Sound playback events (24 events)
src/tweens/events/Tween lifecycle events (10 events)
src/physics/arcade/events/Arcade physics events (8 events)
src/textures/events/Texture manager events (7 events)
src/gameobjects/events/GameObject lifecycle + Video events (18 events)
src/time/events/TimerEvent events (1 event)

コメント