mcpField
P
phaser-arcade-physics

phaser-arcade-physics

github.com/gamedev-skills開発5.4k6.2k 回インストール1 日前に更新
リポジトリ

phaser-arcade-physics について

Phaser 4.2のゲームにArcade Physicsを導入するためのスキルです。移動、重力、衝突に加え、動的・静的ボディやグループの扱いを説明します。

主な機能

  1. 01Arcade Physicsワールドの設定
  2. 02動的・静的ボディの作成
  3. 03速度・加速度・反発の制御
  4. 04衝突とオーバーラップの処理
  5. 05物理グループとワールド境界の利用

活用シーン

  1. 01トップダウン型の移動実装
  2. 02プラットフォームジャンプと接地判定
  3. 03アイテム取得やトリガーの処理
  4. 04デバッグ時のボディ確認

インストール

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

$npx skills add https://github.com/gamedev-skills/awesome-gamedev-agent-skills --skill phaser-arcade-physics

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

同梱ファイルreferences/bodies-and-collision.md

詳細

Phaser 4 Arcade Physics

軽量な Arcade Physics エンジン(AABB の長方形と円のみ)を使って、Phaser ゲームに移動と衝突を追加します。新規プロジェクトでは Phaser 4.2 を対象とします。既存のプロジェクトを編集する前に、インストール済みのメジャーバージョンを確認してください。

使用する場面

  • トップダウンまたはプラットフォームゲームでの移動、速度/加速度/重力、跳ね返り、ワールド境界、スプライト、グループ、タイル間の衝突や重なりの解決に使用します。
  • シーンで physics: { default: 'arcade' } を有効にし、コードで this.physics.add.*、body.setVelocity、または this.physics.add.collider を呼び出す場合に使用します。

使用しない場面: Game の設定、シーン構成、アセットの読み込み、カメラには → phaser-core を使用します。ヒンジ、バネ、複雑なポリゴン、剛体の積み重ねには → Matter physics を使用します(別のエンジンです。Arcade と Matter のボディは相互作用しません)。エンジンに依存しない操作感の調整については physics-tuning を参照してください。

基本的なワークフロー

  1. ワールドを有効にします。 ゲームまたはシーンの設定で physics: { default: 'arcade', arcade: { gravity: {...}, debug: true } } を設定します。構築中は debug をオンにして、ボディの輪郭と速度ベクトルを確認します。
  2. スプライトにボディを設定します。 this.physics.add.sprite(...)(動的)または this.physics.add.staticImage(...)(静的)で作成するか、既存のオブジェクトに this.physics.add.existing(obj) でアタッチします。
  3. x/y を設定せず、ボディを通じて動かします。 setVelocity、setAcceleration、重力、setBounce、setCollideWorldBounds を使用します。エンジンは各ステップで速度から位置を積分します(すでにフレームレートに依存しない方式です)。
  4. 相互作用を解決します。 this.physics.add.collider(a, b) はボディを分離し、this.physics.add.overlap(a, b, cb) は分離せずに検出します(アイテム取得、トリガー)。反応させるにはコールバックを渡します。
  5. 複数のオブジェクトをグループ化します。 this.physics.add.group()(動的)または staticGroup()(プラットフォーム)を使うと、1 回のコライダー呼び出しですべてのメンバーを処理できます。
  6. ジャンプ前に body.onFloor()/body.blocked.down で接地を確認します。 debug: true で実行し、ボディ、接触、境界を確認します。

パターン

1. Arcade Physics を有効にする(ゲーム設定)
const config = {
  type: Phaser.AUTO,
  width: 800, height: 600,
  physics: {
    default: 'arcade',
    arcade: {
      gravity: { x: 0, y: 600 },  // top-down? use { x: 0, y: 0 }
      debug: false                // true to draw bodies + velocity while building
    }
  },
  scene: [PlayScene]
};
new Phaser.Game(config);
2. トップダウンの移動(入力から速度を設定)
create() {
  this.player = this.physics.add.sprite(400, 300, 'player');
  this.player.setCollideWorldBounds(true);
  this.cursors = this.input.keyboard.createCursorKeys();
}

update() {
  const speed = 220;
  const body = this.player.body;
  body.setVelocity(0);                              // reset each frame
  if (this.cursors.left.isDown)  body.setVelocityX(-speed);
  if (this.cursors.right.isDown) body.setVelocityX(speed);
  if (this.cursors.up.isDown)    body.setVelocityY(-speed);
  if (this.cursors.down.isDown)  body.setVelocityY(speed);
  body.velocity.normalize().scale(speed);           // keep diagonals same speed
}
3. プラットフォームゲームのジャンプ(重力+接地判定)
create() {
  this.player = this.physics.add.sprite(100, 450, 'player');
  this.player.setCollideWorldBounds(true);

  // Static platforms: one body each, never moved by collisions.
  this.platforms = this.physics.add.staticGroup();
  this.platforms.create(400, 568, 'ground');
  this.physics.add.collider(this.player, this.platforms);

  this.cursors = this.input.keyboard.createCursorKeys();
}

update() {
  const onGround = this.player.body.blocked.down; // or this.player.body.onFloor()
  if (this.cursors.left.isDown)  this.player.setVelocityX(-160);
  else if (this.cursors.right.isDown) this.player.setVelocityX(160);
  else this.player.setVelocityX(0);

  if (this.cursors.up.isDown && onGround) this.player.setVelocityY(-450);
}
4. コライダーとオーバーラップ(分離と検出)
// Push apart and react: player vs enemies.
this.physics.add.collider(this.player, this.enemies, (player, enemy) => {
  this.handleHit(player, enemy);
});

// Detect without pushing: collect coins. The 4th arg is an optional
// process callback returning a boolean to filter pairs before the main callback.
this.physics.add.overlap(this.player, this.coins, (player, coin) => {
  coin.disableBody(true, true);              // deactivate + hide
  this.registry.inc('score', 10);
});
5. 移動するオブジェクトのグループ
this.bullets = this.physics.add.group({
  defaultKey: 'bullet',
  maxSize: 30                  // pool size; reuse instead of allocating
});

fire(x, y) {
  const bullet = this.bullets.get(x, y);     // reuses a dead bullet if available
  if (!bullet) return;
  bullet.enableBody(true, x, y, true, true);
  bullet.setVelocityY(-500);
}

注意点

  • スプライトが物理演算に反応しない → this.physics.add.sprite(または this.physics.add.existing(obj))ではなく this.add.sprite で追加されているため、ボディがありません。
  • sprite.x を直接設定するとエンジンと競合する → 動的ボディは setVelocity/setAcceleration で動かします。位置を直接書き換えると、コライダーをすり抜けることがあります。
  • 斜め移動の速度が上がる → X と Y の速度が個別に加算されるため、速度ベクトルを正規化し、意図した速度に合わせて再スケーリングします。
  • プラットフォームがプレイヤーに押される → staticGroup を使うか、動的なプラットフォームで body.setImmovable(true) を設定します。
  • onFloor() が常に false になる → ボディには衝突対象が必要です。接地判定の前に地面/プラットフォームとの collider を追加し、重力が有効であることを確認します。
  • 静的ボディを動かした後、衝突判定が古いままになる → 静的ボディは自動同期されません。body.updateFromGameObject()(またはゲームオブジェクトの refreshBody())を呼び出します。
  • コライダーを毎フレーム追加している → collider/overlap は update ではなく、create で一度だけ登録します。

参考資料

  • ボディの構造と調整(ドラッグ、跳ね返り、最大速度、カスタム setSize/setCircle/setOffset ヒットボックス、衝突カテゴリ/マスク、worldbounds イベント)については、references/bodies-and-collision.md を参照してください。

関連スキル

  • phaser-core — ゲーム設定、シーン、ローダー、カメラ(前提となるセットアップ)。
  • physics-tuning — エンジンに依存しない操作感(固定タイムステップ、すり抜け、ジッター)。
  • platformer/tower-defense — このスキルを組み合わせて使うジャンル。
  • level-design — これらのボディが衝突するタイル/プラットフォームのジオメトリを配置します。

コメント