mcpField
W
Writing Phaser 3 Games

Writing Phaser 3 Games

github.com/tomcoolpxl開発0154 回インストール1 日前に更新
リポジトリ

Writing Phaser 3 Games について

実践的な実装パターンを必要とする開発者向けの Phaser 3 ゲーム開発スキルです。18 のトピック別ファイルで、シーン、物理演算、入力、アニメーション、性能などをコード例や注意点とともに扱います。

主な機能

  1. 0118 のトピック別パターンガイド
  2. 02シーン構成とトランジション
  3. 03物理演算、衝突、移動のパターン
  4. 04入力、アニメーション、状態管理
  5. 05オブジェクトプールと性能改善
  6. 06コード構成とよくある問題

活用シーン

  1. 01複数シーンの Phaser ゲームを構成する
  2. 02キーボード、ポインター、タッチ入力を実装する
  3. 03グリッドベースのゲームロジックを構築する
  4. 04性能やメモリの問題を調べる

インストール

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

$npx skills add https://github.com/tomcoolpxl/sugar-splat --skill writing-phaser-3-games

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

knowledgebase/
01-scene-architecture.md
05-animation-system.md
03-physics-collision.md
02-asset-management.md
08-object-pooling-memory.md
09-grid-systems.md
06-input-handling.md
04-movement-patterns.md
10-custom-game-objects.md
07-state-management.md
13-audio-integration.md
12-tween-visual-effects.md
15-algorithm-implementations.md
11-ui-hud-patterns.md
16-performance-optimization.md
TOC.md
14-game-loop-patterns.md
17-code-organization.md
18-development-philosophy.md

詳細

Phaser 3 ゲーム開発スキル

クイックスタート

よく使われるパターン

複数シーンのフロー

const config = {
    scene: [ Boot, Preloader, MainMenu, Game, GameOver ]
};
// Boot → Preloader → MainMenu → Game → GameOver

オブジェクトプーリング

create() {
    this.projectiles = this.physics.add.group({
        classType: Projectile,
        frameQuantity: 20,
        active: false,
        visible: false
    });
}

fire() {
    const projectile = this.projectiles.getFirstDead(false);
    if (projectile) projectile.fire(x, y);
}

グローバルアニメーション

// In Preloader.js create()
this.anims.create({
    key: 'walk',
    frames: this.anims.generateFrameNumbers('player', { start: 0, end: 3 }),
    frameRate: 10,
    repeat: -1
});

JustDown 入力

if (Phaser.Input.Keyboard.JustDown(this.spacebar)) {
    this.jump();
}

ナビゲーションガイド

このスキルの使い方

このスキルでは、Phaser 3 開発のあらゆる側面を網羅する、18 個の包括的なパターンファイルを利用できます。各ファイルには、詳細なパターン、コード例、ベストプラクティスが含まれています。

特定のパターンを見つけるには:

# Read a specific topic
Read knowledgebase/06-input-handling.md

# Search for a pattern across all files
grep -r "object pooling" knowledgebase/

# Find patterns by keyword
grep -i "animation" knowledgebase/*.md
grep -i "collision" knowledgebase/*.md

番号からすばやく検索:

  • 01 = シーンアーキテクチャ
  • 02 = アセット管理
  • 03 = 物理演算と衝突
  • 04 = 移動パターン
  • 05 = アニメーションシステム
  • 06 = 入力処理
  • 07 = 状態管理
  • 08 = オブジェクトプーリングとメモリ
  • 09 = グリッドシステム
  • 10 = カスタムゲームオブジェクト
  • 11 = UI/HUD パターン
  • 12 = Tween と視覚効果
  • 13 = オーディオ統合
  • 14 = ゲームループパターン
  • 15 = アルゴリズムの実装
  • 16 = パフォーマンス最適化
  • 17 = コード構成
  • 18 = 開発理念

目次

1. シーンアーキテクチャ

knowledgebase/01-scene-architecture.md

複数シーンのフロー、UI オーバーレイ用の並列シーン、エフェクトを使ったシーン遷移、シーン間のデータ受け渡し。

主なパターン:

  • Boot → Preloader → MainMenu → Game → GameOver のフロー
  • scene.launch() を使った並列 UI シーン
  • カメラのフェード遷移
  • init(data) によるシーンデータの受け渡し
2. アセット管理

knowledgebase/02-asset-management.md

2 段階の読み込み、テクスチャアトラス、複数形式のオーディオ、フォントの同期。

主なパターン:

  • Boot でブートストラップアセットを、Preloader で全アセットを読み込む
  • 複数のスプライトにテクスチャアトラスを使う
  • ブラウザーとの互換性を確保するための複数形式のオーディオ
  • WebFont の読み込み同期
3. 物理演算と衝突

knowledgebase/03-physics-collision.md

物理演算の設定、衝突と重なりの違い、動的な反応、状態に応じた衝突処理。

主なパターン:

  • 物理的なブロックには Collider、トリガーには overlap を使う
  • 位置に基づく動的な反応(パドルへの衝突)
  • 状態に応じた衝突チェック
  • トラック/レイヤーごとの衝突分離
4. 移動パターン

knowledgebase/04-movement-patterns.md

速度ベース、時間ベースの離散移動、タイマーベース、追跡、方向の検証、画面端での折り返し。

主なパターン:

  • 連続的に動くアクションゲームには速度ベースを使う
  • グリッドゲームには時間ベースの離散移動を使う
  • ターン制ゲームにはタイマーベースを使う
  • 方向を検証して 180° の方向転換を防ぐ
5. アニメーションシステム

knowledgebase/05-animation-system.md

グローバルアニメーションの作成、逆再生アニメーション、アニメーション主導のロジック、状態に応じた制御。

主なパターン:

  • Preloader でアニメーションを一度だけ作成し、どこからでも使う
  • ゲームプレイとの同期にアニメーションイベントを使う
  • キャッシュを使った状態ベースのアニメーション制御
  • 外部アニメーション JSON データ
6. 入力処理

knowledgebase/06-input-handling.md

キーボード、ポインター、タッチ、JustDown パターン、2 種類の入力方式への対応、入力制御、クリーンアップ。

主なパターン:

  • 1 回の押下を検出する JustDown
  • キーボードとポインターの両方に対応
  • アニメーション中の入力制御
  • イベント駆動型のポインター移動
  • once() による 1 回限りの入力処理
7. 状態管理

knowledgebase/07-state-management.md

シーンレベルの状態、永続化のためのレジストリ、localStorage、GameObject のデータコンポーネント、ステートマシン。

主なパターン:

  • 設定にはコンストラクター、リセット可能な状態には init() を使う
  • シーン間のデータ共有にレジストリを使う
  • カスタムプロパティには GameObject のデータコンポーネントを使う
  • ブール値フラグとステートマシンの使い分け
8. オブジェクトプーリングとメモリ

knowledgebase/08-object-pooling-memory.md

グループベースのプーリング、有効化/無効化のパターン、オブジェクトの再利用、動的テクスチャのクリーンアップ。

主なパターン:

  • frameQuantity を使って事前に作成し、getFirstDead() で再利用する
  • 作成/破棄の代わりに有効化/無効化する
  • 再利用可能なオブジェクトのリセットパターン
  • 動的テクスチャのクリーンアップを防止する
9. グリッドシステム

knowledgebase/09-grid-systems.md

座標の使い分け、2D 配列、隣接判定ヘルパー、グリッドへの整列、可視化。

主なパターン:

  • グリッド座標とピクセル座標を分離する
  • 境界チェック付きの2D配列
  • 隣接判定ヘルパー(8方向、4方向)
  • グリッドに整列したグループの作成
10. カスタムゲームオブジェクト

knowledgebase/10-custom-game-objects.md

Sprite/Image の拡張、コンポジションパターン、グループの拡張、自己登録。

主なパターン:

  • 物理演算とアニメーションが必要な場合は Sprite を拡張する
  • 物理演算を使う静的スプライトには Image を拡張する
  • 視覚要素を持たないマネージャーにはコンポジションを使う
  • アニメーションには super.preUpdate() の呼び出しが必要
11. UI/HUD のパターン

knowledgebase/11-ui-hud-patterns.md

テキストのスタイル設定、位置指定、動的更新、ビットマップフォント、アイコンカウンター、レイヤー化。

主なパターン:

  • 位置指定にはテキストの原点を使う(左上、中央など)
  • トゥイーンを使ったアニメーション付きカウンター
  • アイコンベースのカウンター(ハート、残機)
  • UI のレイヤー化に深度/Z順序を使う
12. トゥイーンと視覚効果

knowledgebase/12-tween-visual-effects.md

基本的なトゥイーン、段階的なアニメーション、演出シーケンス、カメラ効果、パーティクル。

主なパターン:

  • トゥイーンのコールバックを使ったシーケンス制御
  • グリッドの段階的なアニメーション
  • 遅延を積み重ねた演出シーケンス
  • カメラのシェイク、フラッシュ、フェード
  • パーティクルエミッター
13. オーディオの統合

knowledgebase/13-audio-integration.md

サウンド管理、オーディオロックへの対処、オーディオの一元管理、遅延/シーケンス再生。

主なパターン:

  • 複数形式のオーディオ読み込み
  • オーディオロックの検出と対処
  • UI シーンでのオーディオの一元管理
  • シーンをまたいだ音楽の再生
14. ゲームループのパターン

knowledgebase/14-game-loop-patterns.md

標準的な更新処理、最小限のイベント駆動型処理、カスタムオブジェクトの preUpdate、処理の委譲、タイマー。

主なパターン:

  • update() 内で早期終了ガードを使う
  • ターン制ゲームではイベント駆動型にする
  • タイマーによる繰り返しイベント/単発イベント
  • マネージャーへの更新処理の委譲
15. アルゴリズムの実装

knowledgebase/15-algorithm-implementations.md

フラッドフィル、賢いランダム配置、解けるパズルの生成、近接距離の計算、追従チェーン、AI。

主なパターン:

  • 4方向に広がる再帰的なフラッドフィル
  • 配置を確実にする有効な位置の収集
  • 解けるパズルを生成するウォーカーアルゴリズム
  • ShiftPosition を使った追従チェーン
16. パフォーマンスの最適化

knowledgebase/16-performance-optimization.md

オブジェクトプーリング、テクスチャキャッシュ、更新処理の最小化、イベント駆動型処理、静的グループ。

主なパターン:

  • オブジェクトプーリングで GC の一時停止をなくす
  • 動かないオブジェクトには静的グループを使う
  • update() でのポーリングよりイベント駆動型処理を使う
  • レンダリング性能向上のためにテクスチャアトラスを使う
17. コードの構成

knowledgebase/17-code-organization.md

ファイル構成、ES6 モジュール、定数の管理、関心事の分離。

主なパターン:

  • scenes、gameobjects、managers、utils、constants の各フォルダー
  • ES6 モジュールのインポート
  • スプライト/アニメーション/オーディオのキーをまとめた定数ファイル
  • create() 内で初期化順序を明確にする
18. 開発哲学

knowledgebase/18-development-philosophy.md

アーキテクチャの原則、物理演算を使うタイミング、シーンの判断、更新とイベント、段階的な難易度設定。

主なパターン:

  • 物理演算と手動ロジックを使い分けるタイミング
  • シーンを単一、複数、並列にする場合
  • Update() とイベント駆動型のアプローチ
  • 段階的な難易度設定のパターン

コアパターンのリファレンス

シーンのセットアップ
export default class Game extends Phaser.Scene {
    constructor() {
        super('Game');
        // Configuration constants
        this.GRID_SIZE = 32;
    }

    init() {
        // Reset resettable state
        this.score = 0;
        this.gameOver = false;
    }

    create() {
        // Initialize objects
        this.player = new Player(this);
        this.enemies = this.physics.add.group();

        // Setup collisions
        this.physics.add.collider(this.player, this.enemies, this.onHit, null, this);
    }

    update(time, delta) {
        if (this.gameOver) return;
        // Game logic
    }
}
カスタムゲームオブジェクト
export default class Player extends Phaser.Physics.Arcade.Sprite {
    constructor(scene, x, y) {
        super(scene, x, y, 'player');

        // Self-register
        scene.add.existing(this);
        scene.physics.add.existing(this);

        // Configuration
        this.setCollideWorldBounds(true);
        this.isAlive = true;
    }

    preUpdate(time, delta) {
        super.preUpdate(time, delta);  // ESSENTIAL for animations

        if (!this.isAlive) return;
        this.handleMovement();
    }
}
グリッドシステム
// Dual coordinate system
this.gridX = 5;
this.gridY = 3;
this.sprite.x = this.gridX * TILE_SIZE;
this.sprite.y = this.gridY * TILE_SIZE;

// 2D array with bounds checking
getCellXY(x, y) {
    if (x < 0 || x >= this.width || y < 0 || y >= this.height) {
        return null;
    }
    return this.grid[y][x];
}
衝突処理
// Physical collision
this.physics.add.collider(player, platforms);

// Trigger-based overlap
this.physics.add.overlap(player, coins, this.collectCoin, null, this);

// Collision with state gates
onHit(player, enemy) {
    if (!player.isAlive) return;
    if (player.invincible) return;
    if (enemy.alpha < 1) return;

    this.handleDamage(player, enemy);
}
入力パターン
create() {
    // Cursor keys
    this.cursors = this.input.keyboard.createCursorKeys();

    // Specific key
    this.spacebar = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE);

    // Pointer/touch
    this.input.on('pointerdown', this.handleClick, this);
}

update() {
    // Continuous input
    if (this.cursors.left.isDown) {
        this.player.setVelocityX(-160);
    }

    // Single-press input
    if (Phaser.Input.Keyboard.JustDown(this.spacebar)) {
        this.jump();
    }
}
アニメーションのセットアップ
// In Preloader create() - global animations
this.anims.create({
    key: 'player-walk',
    frames: this.anims.generateFrameNumbers('player', { start: 0, end: 3 }),
    frameRate: 10,
    repeat: -1
});

// In Game create() - use animations
this.player.play('player-walk');

// Animation events
this.player.on('animationcomplete-attack', this.spawnProjectile, this);
状態管理
// Scene-level state
init() {
    this.score = 0;
    this.lives = 3;
    this.gameOver = false;
}

// Registry for cross-scene data
this.registry.set('highscore', this.score);
const highscore = this.registry.get('highscore');

// GameObject data
sprite.setData({ gridX: 5, gridY: 3, type: 'enemy' });
const gridX = sprite.data.values.gridX;

よくある落とし穴

避けるべき重大なミス:

  1. カスタムスプライトで super.preUpdate(time, delta) を呼び忘れる

    • これを呼ばないとアニメーションが動作しません
    • preUpdate() の最初に必ず呼び出してください
  2. 静的グループをスケーリングした後に refreshBody() を呼び出さない

    this.platforms.create(x, y, 'platform')
        .setScale(2)
        .refreshBody();  // REQUIRED
    
  3. オブジェクトプールを使わず、update() 内でオブジェクトを作成する

    • GC の一時停止を引き起こし、パフォーマンスが低下します
    • プールを事前に作成し、有効化/無効化して再利用してください
  4. グリッドへのアクセス時に境界チェックを行わない

    if (x < 0 || x >= width || y < 0 || y >= height) return null;
    
  5. リスナーやタイマーをクリーンアップしない

    shutdown() {
        this.input.off('pointerdown', this.handleClick);
        if (this.timer) this.timer.remove();
    }
    
  6. 誤った衝突処理メソッドを使う

    • 物理的なブロックには collider を使用します
    • トリガーやアイテム取得には overlap を使用します
  7. イベントで対応できる場面で update() 内のポーリングを使う

    • 距離チェックの代わりに、物理演算の overlap を使用します
    • 毎フレーム確認する代わりに、ポインターイベントを使用します
  8. 定数を使わず値をハードコードする

    // Bad: magic numbers
    sprite.x = 400;
    
    // Good: named constants
    const GRID_SIZE = 32;
    sprite.x = gridX * GRID_SIZE;
    
  9. init() で状態をリセットしない

    • シーンを正しく再起動できません
    • リセット可能な状態はコンストラクターではなく init() に設定してください
  10. コールバックのコンテキストバインディングを無視する

    // アロー関数または bind を使用します
    this.time.delayedCall(1000, () => this.start(), [], this);
    

パフォーマンスのヒント

  • 頻繁に作成・破棄するオブジェクトには、オブジェクトプールを使用します
  • テクスチャアトラスを使うと、スプライトを1枚の画像にまとめられます
  • 動かないプラットフォームや壁には、静的グループを使用します
  • update() 内のポーリングより、イベント駆動型のアプローチを使用します
  • 更新ロジックを最小限にし、各フレームで必要な処理だけを行います
  • 検索結果をキャッシュし、毎フレーム配列を検索しないようにします
  • 深度は一度だけ設定し、毎フレームソートしないようにします

詳細ファイルを読むタイミング

新しいゲームを始めますか? → 01-scene-architecture.md を読んでください

パフォーマンスに問題がありますか? → 16-performance-optimization.md を読んでください

グリッドベースのゲームですか? → 09-grid-systems.md を読んでください

複雑なアニメーションですか? → 05-animation-system.md と 12-tween-visual-effects.md を読んでください

入力に問題がありますか? → 06-input-handling.md を読んでください

メモリーリークがありますか? → 08-object-pooling-memory.md を読んでください

アルゴリズムを実装しますか? → 15-algorithm-implementations.md を読んでください

アーキテクチャを決めますか? → 18-development-philosophy.md を読んでください

クイックリファレンス

シーンの流れ
Boot → Preloader → MainMenu → Game → GameOver
this.scene.start('NextScene', { score: this.score });
this.scene.launch('GameUI');  // Parallel scene
物理演算
this.physics.add.collider(a, b);        // Physical blocking
this.physics.add.overlap(a, b, callback); // Trigger only
sprite.setCollideWorldBounds(true);
sprite.setImmovable(true);
グループとプーリング
this.items = this.physics.add.group({ frameQuantity: 20 });
const item = this.items.getFirstDead(false);
item.enableBody(true, x, y, true, true);
item.disableBody(true, true);
入力
this.cursors = this.input.keyboard.createCursorKeys();
Phaser.Input.Keyboard.JustDown(key)
this.input.on('pointerdown', callback, this);
トゥイーン
this.tweens.add({
    targets: sprite,
    x: 400,
    duration: 1000,
    ease: 'Power2',
    onComplete: () => {}
});
カメラ
this.cameras.main.shake(duration, intensity);
this.cameras.main.fadeOut(duration);
this.cameras.main.flash(duration, r, g, b);

このスキルでは、Phaser 3 のパターンを包括的に紹介します。詳細な例や高度なテクニックについては、ナレッジベースの各ファイルをお読みください。

コメント