mcpField
P
phaser-input

phaser-input

github.com/yakoub-ai開発29195 回インストール9 週間前に更新
リポジトリ

phaser-input について

phaser-inputは、キーボード、ポインター、タッチ、ゲームパッドを扱うPhaser 4の入力スキルです。APIの使用例に加え、モバイル向け仮想ジョイスティックの実装例を提供します。

主な機能

  1. 01キーボード割り当てとキー状態
  2. 02ポインターイベントとドラッグ&ドロップ
  3. 03タッチとマルチタッチ入力
  4. 04ゲームパッドのボタンとアナログスティック
  5. 05仮想ジョイスティックの実装例

活用シーン

  1. 01ゲーム操作へのキーバインド
  2. 02クリック・ドラッグ可能なオブジェクトの追加
  3. 03マルチタッチ操作の処理
  4. 04モバイル向け移動操作の構築

インストール

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

$npx skills add https://github.com/yakoub-ai/phaser4-gamedev --skill phaser-input

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

同梱ファイルreferences/input-api.mdreferences/virtual-joystick.md

詳細

Phaser 4 入力

Phaser 4 の入力システムは、キーボード、マウス/ポインター、タッチ、ゲームパッドをサポートしています。すべての入力は、シーン内の this.input を通じてアクセスします。

キーボード入力

カーソルキー

矢印キー、スペース、シフトを一度の呼び出しで追跡するカーソルキーセットを作成します:

private cursors!: Phaser.Types.Input.Keyboard.CursorKeys;

create(): void {
  this.cursors = this.input.keyboard!.createCursorKeys();
}

update(): void {
  if (this.cursors.left.isDown) { /* move left */ }
  if (this.cursors.right.isDown) { /* move right */ }
  if (this.cursors.up.isDown) { /* move up / jump */ }
  if (this.cursors.down.isDown) { /* move down / crouch */ }
  if (this.cursors.space.isDown) { /* fire / action */ }
  if (this.cursors.shift.isDown) { /* sprint / modifier */ }
}
WASD キー

addKeys を使用して、任意のキーを名前でバインドします:

private wasd!: { up: Phaser.Input.Keyboard.Key; left: Phaser.Input.Keyboard.Key; down: Phaser.Input.Keyboard.Key; right: Phaser.Input.Keyboard.Key };

create(): void {
  this.wasd = this.input.keyboard!.addKeys({ up: 'W', left: 'A', down: 'S', right: 'D' }) as typeof this.wasd;
}

update(): void {
  if (this.wasd.left.isDown) { /* strafe left */ }
  if (this.wasd.right.isDown) { /* strafe right */ }
}
単一キー

KeyCodes を使用して単一のキーをバインドします:

private spaceKey!: Phaser.Input.Keyboard.Key;
private shiftKey!: Phaser.Input.Keyboard.Key;

create(): void {
  this.spaceKey = this.input.keyboard!.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE);
  this.shiftKey = this.input.keyboard!.addKey(Phaser.Input.Keyboard.KeyCodes.SHIFT);
}
isDown vs JustDown vs JustUp
メソッド動作
key.isDownキーが押されているすべてのフレームで true
Phaser.Input.Keyboard.JustDown(key)キーが最初に押された単一のフレームで true
Phaser.Input.Keyboard.JustUp(key)キーが離された単一のフレームで true
update(): void {
  // Continuous — fires every frame while held
  if (this.cursors.left.isDown) {
    this.player.setVelocityX(-200);
  }

  // One-shot — fires once per key press
  if (Phaser.Input.Keyboard.JustDown(this.spaceKey)) {
    this.fireBullet();
  }

  // Release — fires once per key release
  if (Phaser.Input.Keyboard.JustUp(this.shiftKey)) {
    this.stopSprint();
  }
}
キーの組み合わせ (コナミコマンド、チートコード)
create(): void {
  // Konami: Up Up Down Down Left Right Left Right A B
  const combo = this.input.keyboard!.createCombo(
    [38, 38, 40, 40, 37, 39, 37, 39, 65, 66],
    { resetOnMatch: true }
  );

  this.input.keyboard!.on('keycombomatch', (combo: Phaser.Input.Keyboard.KeyCombo) => {
    console.log('Konami code entered!');
    this.activateCheatMode();
  });
}
ブラウザのデフォルトキーの無効化

ブラウザが矢印キー (ページスクロール) やその他のキーを横取りするのを防ぎます:

create(): void {
  // Disable global capture — let browser handle keys normally
  this.input.keyboard!.disableGlobalCapture();

  // Enable global capture — Phaser intercepts keys before the browser
  this.input.keyboard!.enableGlobalCapture();

  // Capture only specific keys (recommended approach)
  this.input.keyboard!.addCapture([
    Phaser.Input.Keyboard.KeyCodes.UP,
    Phaser.Input.Keyboard.KeyCodes.DOWN,
    Phaser.Input.Keyboard.KeyCodes.LEFT,
    Phaser.Input.Keyboard.KeyCodes.RIGHT,
    Phaser.Input.Keyboard.KeyCodes.SPACE,
  ]);
}

ポインター / マウス入力

グローバルポインターイベント

ゲームキャンバス内のどこでも発生するイベントを this.input でリッスンします:

create(): void {
  this.input.on('pointerdown', (ptr: Phaser.Input.Pointer) => {
    console.log(`Clicked at canvas: ${ptr.x}, ${ptr.y}`);
    console.log(`World position: ${ptr.worldX}, ${ptr.worldY}`);
    console.log(`Left button: ${ptr.leftButtonDown()}`);
    console.log(`Right button: ${ptr.rightButtonDown()}`);
  });

  this.input.on('pointermove', (ptr: Phaser.Input.Pointer) => {
    // ptr.velocity.x / ptr.velocity.y for movement delta
  });

  this.input.on('pointerup', (ptr: Phaser.Input.Pointer) => {
    // handle release
  });
}

カメラが移動している場合は ptr.worldX / ptr.worldY を使用してください — これらはスクリーン空間ではなくワールド空間の位置を返します。

スプライトをインタラクティブにする

特定のオブジェクトでポインターイベントをリッスンする前に、setInteractive() を呼び出します:

create(): void {
  const button = this.add.image(400, 300, 'button');
  button.setInteractive({ useHandCursor: true });  // shows pointer cursor on hover

  button.on('pointerdown', () => {
    this.scene.start('GameScene');
  });

  button.on('pointerover', () => {
    button.setTint(0xcccccc);  // lighten on hover
  });

  button.on('pointerout', () => {
    button.clearTint();
  });
}
ドラッグアンドドロップ

ゲームオブジェクトでドラッグを有効にします:

create(): void {
  const card = this.add.image(200, 200, 'card');
  card.setInteractive();
  this.input.setDraggable(card);

  this.input.on('dragstart', (ptr: Phaser.Input.Pointer, obj: Phaser.GameObjects.Image) => {
    obj.setTint(0x88ff88);
  });

  this.input.on('drag', (ptr: Phaser.Input.Pointer, obj: Phaser.GameObjects.Image, dragX: number, dragY: number) => {
    obj.setPosition(dragX, dragY);
  });

  this.input.on('dragend', (ptr: Phaser.Input.Pointer, obj: Phaser.GameObjects.Image) => {
    obj.clearTint();
  });
}
入力ゾーン

Zone を不可視のインタラクティブ領域として使用します (UI のヒットエリアに便利です):

create(): void {
  const zone = this.add.zone(400, 300, 200, 100).setInteractive();
  zone.on('pointerdown', () => {
    console.log('Zone was clicked');
  });
}
右クリック (コンテキストメニュー)

右クリック時にブラウザのコンテキストメニューが表示されるのを防ぎます:

create(): void {
  this.input.mouse!.disableContextMenu();

  this.input.on('pointerdown', (ptr: Phaser.Input.Pointer) => {
    if (ptr.rightButtonDown()) {
      console.log('Right click at', ptr.worldX, ptr.worldY);
    }
  });
}
イベント伝播の停止

ゲームオブジェクトのクリックがグローバルの pointerdown ハンドラーも発生させるのを防ぎます:

button.on('pointerdown', (
  ptr: Phaser.Input.Pointer,
  localX: number,
  localY: number,
  event: Phaser.Types.Input.EventData
) => {
  event.stopPropagation();
  this.handleButtonClick();
});

タッチ入力

タッチイベントは同じポインター API を共有します — pointerdown、pointermove、pointerup はタッチデバイスで自動的に発生します。

マルチタッチ

追加のポインタースロットを追加します (デフォルトは合計 2 つ、より多くの指のために拡張します):

create(): void {
  // Support up to 4 simultaneous touches
  this.input.addPointer(2);  // adds 2 more (total becomes 4)

  // Access individual touch pointers
  // this.input.pointer1  — first touch
  // this.input.pointer2  — second touch
  // this.input.pointer3  — third touch
}
スワイプ検出

Phaser には組み込みのスワイプ API はありません。開始位置を手動で追跡します:

private swipeStart = { x: 0, y: 0 };
private readonly SWIPE_THRESHOLD = 50; // pixels

create(): void {
  this.input.on('pointerdown', (ptr: Phaser.Input.Pointer) => {
    this.swipeStart = { x: ptr.x, y: ptr.y };
  });

  this.input.on('pointerup', (ptr: Phaser.Input.Pointer) => {
    const dx = ptr.x - this.swipeStart.x;
    const dy = ptr.y - this.swipeStart.y;

    if (Math.abs(dx) > this.SWIPE_THRESHOLD || Math.abs(dy) > this.SWIPE_THRESHOLD) {
      if (Math.abs(dx) > Math.abs(dy)) {
        console.log(dx > 0 ? 'Swipe Right' : 'Swipe Left');
      } else {
        console.log(dy > 0 ? 'Swipe Down' : 'Swipe Up');
      }
    }
  });
}
ブラウザのジェスチャーの防止
create(): void {
  // Prevent pinch-zoom, browser swipe navigation, pull-to-refresh
  this.input.mouse!.disableContextMenu();
  // In your HTML, also add to the canvas element:
  // style="touch-action: none;"
  // Or in Phaser config: input: { activePointers: 3 }
}

ゲームパッド入力

Gamepad プラグインは Phaser 4 にデフォルトで含まれています。this.input.gamepad を通じてアクセスします。

接続
create(): void {
  this.input.gamepad!.on('connected', (pad: Phaser.Input.Gamepad.Gamepad) => {
    console.log(`Gamepad connected: ${pad.id}`);
  });

  this.input.gamepad!.on('disconnected', (pad: Phaser.Input.Gamepad.Gamepad) => {
    console.log(`Gamepad disconnected`);
  });
}
ボタンの読み取り
update(): void {
  const pad = this.input.gamepad!.pad1;
  if (!pad) return;

  // Face buttons
  if (pad.A) { this.jump(); }
  if (pad.B) { this.dodge(); }
  if (pad.X) { this.attack(); }
  if (pad.Y) { this.interact(); }

  // Shoulder / trigger buttons
  if (pad.L1) { /* left bumper */ }
  if (pad.R1) { /* right bumper */ }
  if (pad.L2) { /* left trigger (analog, 0–1) */ }
  if (pad.R2) { /* right trigger (analog, 0–1) */ }

  // D-pad
  if (pad.up)    { /* d-pad up */ }
  if (pad.down)  { /* d-pad down */ }
  if (pad.left)  { /* d-pad left */ }
  if (pad.right) { /* d-pad right */ }
}
アナログスティック

値は各軸で -1 から 1 の範囲です。ドリフトを防ぐためにデッドゾーンを適用します:

private readonly DEAD_ZONE = 0.1;

update(): void {
  const pad = this.input.gamepad!.pad1;
  if (!pad) return;

  let lx = pad.leftStick.x;
  let ly = pad.leftStick.y;
  let rx = pad.rightStick.x;
  let ry = pad.rightStick.y;

  // Apply dead zone
  if (Math.abs(lx) < this.DEAD_ZONE) lx = 0;
  if (Math.abs(ly) < this.DEAD_ZONE) ly = 0;
  if (Math.abs(rx) < this.DEAD_ZONE) rx = 0;
  if (Math.abs(ry) < this.DEAD_ZONE) ry = 0;

  this.player.setVelocity(lx * 300, ly * 300);

  // Aim with right stick
  if (rx !== 0 || ry !== 0) {
    const angle = Math.atan2(ry, rx) * (180 / Math.PI);
    this.player.setAngle(angle);
  }
}

バーチャルジョイスティック (モバイル)

Phaser 4 には組み込みのバーチャルジョイスティックはありません。モバイルゲームでは、ポインターベースのジョイスティックを実装するか、リファレンス実装を使用してください。

ベース円とサムを描画し、正規化された direction.x / direction.y 値を公開する、完全で実運用可能な TypeScript クラスについては references/virtual-joystick.md を参照してください。

そのリファレンスファイルには 2 つのよくあるバグが記載されています: (1) 初回接触ロック — ドラッグ中はベースがロックされたままである必要があります。ユーザーがドラッグするときにベースが「ジャンプ」する場合、誰かが onPointerMove で baseX/baseY を更新しています。(2) シーン間のリスナー喪失 — ジョイスティックがあるシーンでは動作するが別のシーンでは動作しない場合、ゲームプレイシーンごとではなく、scene.launch() で起動される永続的な InputScene で一度だけインスタンス化してください。

使用パターン:

private joystick!: VirtualJoystick;

create(): void {
  this.joystick = new VirtualJoystick(this, 120, this.scale.height - 120);
}

update(): void {
  if (this.joystick.isActive) {
    this.player.setVelocity(
      this.joystick.direction.x * 200,
      this.joystick.direction.y * 200
    );
  } else {
    this.player.setVelocity(0, 0);
  }
}

追加リソース

リファレンスファイル
  • references/input-api.md — InputPlugin、KeyboardPlugin、Key、Pointer、Gamepad、およびすべての入力イベントの完全な API リファレンス
  • references/virtual-joystick.md — モバイルゲーム向けの完全な TypeScript バーチャルジョイスティック実装

コメント