mcpField
P
physics-arcade

physics-arcade

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

physics-arcade について

Phaser 4 の Arcade Physics を使う開発者向けスキルです。ボディ、移動、重力、衝突、ワールド境界、衝突フィルタリングを解説します。

主な機能

  1. 01動的および静的な物理ボディの作成
  2. 02速度、加速度、重力の設定
  3. 03衝突とオーバーラップ判定の登録
  4. 04ワールド境界とボディ形状の設定
  5. 05カテゴリとマスクによる衝突のフィルタリング
  6. 06物理ワールドの一時停止と設定

活用シーン

  1. 01プレイヤーキャラクターに物理ベースの移動を設定
  2. 02足場と収集アイテムのオーバーラップ判定
  3. 03ボディをワールド境界内に制限
  4. 04衝突可能なボディカテゴリの選択

インストール

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

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

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

詳細

Arcade Physics

Phaser 4 で Arcade Physics をセットアップして使用する方法 -- GameConfig で物理を有効化し、物理対応のスプライト/イメージ/グループを作成し、速度、加速度、重力、衝突(collide/overlap)、ワールド境界、ボディプロパティ、衝突カテゴリを扱います。

主要なソースパス: src/physics/arcade/ArcadePhysics.js、src/physics/arcade/World.js、src/physics/arcade/Body.js、src/physics/arcade/StaticBody.js、src/physics/arcade/Factory.js、src/physics/arcade/components/、src/physics/arcade/events/ 関連スキル: ../game-setup-and-config/SKILL.md、../sprites-and-images/SKILL.md、../tilemaps/SKILL.md、../groups-and-containers/SKILL.md

クイックスタート

class GameScene extends Phaser.Scene {
    create() {
        // Physics sprite (dynamic body, affected by gravity)
        this.player = this.physics.add.sprite(100, 300, 'player');
        this.player.setCollideWorldBounds(true);
        this.player.setBounce(0.2);

        // Static group (immovable platforms)
        this.platforms = this.physics.add.staticGroup();
        this.platforms.create(400, 568, 'ground').setScale(2).refreshBody();

        // Register a persistent collider (checked every frame automatically)
        this.physics.add.collider(this.player, this.platforms);

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

    update() {
        if (this.cursors.left.isDown) {
            this.player.setVelocityX(-160);
        } else if (this.cursors.right.isDown) {
            this.player.setVelocityX(160);
        } else {
            this.player.setVelocityX(0);
        }
    }
}

// Enable Arcade Physics in game config
const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    physics: {
        default: 'arcade',
        arcade: {
            gravity: { y: 300 },
            debug: false
        }
    },
    scene: GameScene
};

const game = new Phaser.Game(config);

基本概念

World (this.physics.world)

Phaser.Physics.Arcade.World はシミュレーション内のすべてのボディを管理します。Scene 内では this.physics.world でアクセスします。

  • gravity -- 毎ステップすべての動的ボディに適用される Vector2。設定または this.physics.world.gravity.y = 300 で設定します。
  • bounds -- ワールド境界を定義する Rectangle。デフォルトはゲームキャンバスのサイズです。
  • bodies -- すべての動的な Body インスタンスの Set。
  • staticBodies -- すべての StaticBody インスタンスの Set。
  • colliders -- 登録された Collider オブジェクトの ProcessQueue(this.physics.add.collider / this.physics.add.overlap から生成)。
  • fps -- 1 秒あたりの物理ステップ数(デフォルト 60)。読み取り専用。変更するには world.setFPS(120) を使用します。
  • fixedStep -- true(デフォルト)で固定タイムステップを使用、false でレンダリング fps に同期します。
  • timeScale -- スケーリング係数: 1.0 = 通常、2.0 = 半速、0.5 = 2 倍速。
  • isPaused -- true のとき、ボディは更新されず、コライダーも実行されません。world.pause() / world.resume() で切り替えます。
  • useTree -- true(デフォルト)で動的ボディに RTree 空間インデックスを使用します。5000 以上のボディでは無効にしてください。
  • drawDebug -- true でデバッグレンダリングを有効にします。設定 debug: true で設定します。
ボディ (Body)

this.physics.add.sprite() または this.physics.add.image() を使用すると、動的ボディが自動的に作成されます。gameObject.body でアクセスします。

主要なプロパティ(すべて Body 上にあります):

  • velocity -- Vector2、ピクセル/秒
  • acceleration -- Vector2、ピクセル/秒^2
  • drag -- Vector2、減速度(加速度がゼロのときのみ適用)
  • gravity -- Vector2、ワールド重力に加算されるボディごとの重力
  • bounce -- Vector2、1 に対する反発係数
  • friction -- Vector2、デフォルト (1, 0) -- 動かないボディが乗っているボディに与える速度
  • maxVelocity -- Vector2、デフォルト (10000, 10000) | maxSpeed -- スカラー上限、デフォルト -1(なし)
  • mass -- デフォルト 1、衝突時の運動量交換に影響します
  • immovable -- false。true の場合、衝突によって移動しません
  • pushable -- true。false の場合、衝突相手のボディに速度を反射します
  • moves -- true。false の場合、物理によって位置/回転が更新されません
  • enable -- true。false でシミュレーションから除外されます
  • useDamping -- false。true の場合、drag は線形ではなく乗数(0-1)になります
  • collideWorldBounds -- false。onWorldBounds/onCollide/onOverlap -- false、イベントを発生させるには true を設定します

形状: isCircle(setCircle で設定)、width/height、offset(Vector2)、center(読み取り専用の中点)。

衝突状態(読み取り専用、毎ステップリセット): touching / blocked / wasTouching -- { none, up, down, left, right }。embedded -- 両方が重なっており速度がゼロ。

角度: angularVelocity(度/秒)、angularAcceleration、angularDrag、maxAngular(デフォルト 1000)、allowRotation(デフォルト true)。

静的ボディ(StaticBody)

静的ボディは決して移動せず、重力や速度の影響も受けません。高速な空間検索のために最適化された RTree を使用します。

  • this.physics.add.staticSprite()、this.physics.add.staticImage()、または this.physics.add.staticGroup() で作成します。
  • 親 Game Object の位置やスケールを変更した後は、body.reset() または gameObject.refreshBody() を呼び出して同期してください。
  • 動的ボディと同様に collisionCategory と collisionMask を持ちます。
  • 速度、加速度、ドラッグ、重力のプロパティは持ちません。

一般的なパターン

既存の Game Object で物理を有効にする
// Add a physics body to any existing Game Object
this.physics.add.existing(mySprite);           // dynamic body
this.physics.add.existing(mySprite, true);     // static body

// Or enable via the world directly
this.physics.world.enable(mySprite);           // dynamic
this.physics.world.enable(mySprite, Phaser.Physics.Arcade.STATIC_BODY);
物理スプライトと画像を作成する
// Via the physics factory (this.physics.add)
const player = this.physics.add.sprite(100, 200, 'player');     // dynamic body
const coin = this.physics.add.image(300, 100, 'coin');          // dynamic body
const wall = this.physics.add.staticImage(400, 300, 'wall');    // static body
const platform = this.physics.add.staticSprite(400, 500, 'plat'); // static body

// Standalone bodies (no Game Object)
const sensor = this.physics.add.body(200, 200, 32, 32);        // dynamic Body
const zone = this.physics.add.staticBody(100, 100, 64, 64);    // static Body
速度と重力
// Direct velocity
player.setVelocity(200, -300);          // x=200 px/s, y=-300 px/s (upward)
player.setVelocityX(200);
player.body.velocity.set(200, -300);    // equivalent via Vector2

// Acceleration + max velocity
player.setAcceleration(100, 0);
player.setMaxVelocity(300, 600);

// Per-body gravity (added to world gravity)
player.body.gravity.y = 200;
player.body.allowGravity = false;       // exempt from world gravity

// Drag (applied only when acceleration is zero)
player.setDrag(300);                    // linear deceleration
player.body.useDamping = true;
player.setDrag(0.05);                   // damping mode: keeps 5% velocity/sec

// Bounce
player.setBounce(0.5);                  // both axes
player.setBounceY(1);                   // full vertical bounce
Collide と Overlap

2 つのアプローチがあります: 永続的な Collider(毎フレーム自動的にチェックされます)または 単発のチェック(update() 内で呼び出します)。

// --- Persistent Colliders (preferred) ---
// Created via this.physics.add.collider / this.physics.add.overlap
// Automatically checked every physics step

const collider = this.physics.add.collider(player, platforms);
const overlap = this.physics.add.overlap(player, coins, collectCoin, null, this);

function collectCoin (player, coin) {
    coin.disableBody(true, true); // disable physics and hide
}

// Collider management
collider.active = false;   // temporarily disable
collider.destroy();        // remove permanently

// With processCallback (must return boolean to allow collision)
this.physics.add.collider(player, enemies, onHit, canCollide, this);
function canCollide (player, enemy) {
    return !player.getData('invincible');
}

// --- One-shot checks (in update) ---
// Called manually each frame; no Collider object created

this.physics.collide(player, platforms);
this.physics.overlap(player, coins, collectCoin, null, this);

// Self-collision within a single group
this.physics.add.collider(enemies, enemies);
グループ
// Dynamic physics group -- members get dynamic bodies automatically
const bullets = this.physics.add.group({
    classType: Phaser.Physics.Arcade.Sprite,  // default: ArcadeSprite
    maxSize: 20,
    collideWorldBounds: true,
    bounceX: 1,
    bounceY: 1,
    velocityX: 200,
    velocityY: 0,
    allowGravity: false,
    immovable: false
});

// Static physics group -- members get static bodies
const platforms = this.physics.add.staticGroup();
platforms.create(400, 568, 'ground');
platforms.create(600, 400, 'ground');

// After modifying a static group member's transform, refresh:
platforms.create(400, 568, 'ground').setScale(2).refreshBody();

// Group velocity helpers
bullets.setVelocity(200, 0);       // all members
bullets.setVelocityX(200);
bullets.setVelocityY(0, 10);       // with step increment per member

PhysicsGroup の設定キー(新しいメンバーにデフォルトとして適用されます): collideWorldBounds、bounceX/Y、accelerationX/Y、dragX/Y、gravityX/Y、frictionX/Y、velocityX/Y、angularVelocity、angularAcceleration、angularDrag、maxVelocityX/Y、maxSpeed、mass、immovable、allowDrag、allowGravity、allowRotation、useDamping、enable。

ワールド境界
// Set bounds size and which edges collide (left, right, up, down)
this.physics.world.setBounds(0, 0, 1600, 1200, true, true, false, true);
this.physics.world.setBoundsCollision(true, true, false, true); // edges only

// Per-body world bounds
player.setCollideWorldBounds(true);
player.body.setBoundsRectangle(new Phaser.Geom.Rectangle(100, 100, 600, 400));
player.body.worldBounce = new Phaser.Math.Vector2(0.5, 0.5);

// Detect world bounds hit via event (requires opt-in)
player.body.onWorldBounds = true;
this.physics.world.on('worldbounds', (body, up, down, left, right) => {
    console.log('Hit edge:', { up, down, left, right });
});
ボディのプロパティ
// Size and shape
player.body.setSize(24, 32, true);     // width, height, re-center on GO
player.body.setOffset(4, 0);           // offset from GO position
player.body.setCircle(16);             // circular body, radius 16
player.body.setCircle(16, 4, 4);       // circular with offset

// Collision behavior
player.body.setImmovable(true);        // not moved by collisions
player.body.setPushable(false);        // reflects velocity to collider
player.body.slideFactor.set(0, 0);     // Sokoban-style: stops after push
player.body.setMass(2);               // affects momentum exchange

// Enable / disable
player.disableBody(true, true);        // disable body + hide Game Object
player.enableBody(true, x, y, true, true); // re-enable at position + show

// Per-direction collision check
player.body.checkCollision.up = false; // don't collide from above
player.body.syncBounds = true;         // auto-sync size to texture
衝突カテゴリ

衝突カテゴリを使用すると、ビットマスク値を使ってどのボディ同士が衝突できるかをフィルタリングできます。最大 32 個のカテゴリです。

// Get unique category values from the physics plugin
const CAT_PLAYER = this.physics.nextCategory();   // 0x0002
const CAT_ENEMY  = this.physics.nextCategory();   // 0x0004
const CAT_BULLET = this.physics.nextCategory();   // 0x0008

// Assign categories to bodies or groups
player.setCollisionCategory(CAT_PLAYER);
enemy.setCollisionCategory(CAT_ENEMY);
bullet.setCollisionCategory(CAT_BULLET);

// Set what each body collides with
player.setCollidesWith([CAT_ENEMY]);              // player hits enemies only
enemy.setCollidesWith([CAT_PLAYER, CAT_BULLET]);  // enemies hit player + bullets
bullet.setCollidesWith([CAT_ENEMY]);              // bullets hit enemies only

// Add/remove individual categories from existing mask
player.addCollidesWith(CAT_BULLET);
player.removeCollidesWith(CAT_ENEMY);

// Check if a body will collide with a category
player.willCollideWith(CAT_ENEMY); // returns boolean

// Reset to default (collides with everything)
player.resetCollisionCategory();

// Works on Groups too
enemies.setCollisionCategory(CAT_ENEMY);
enemies.setCollidesWith([CAT_PLAYER, CAT_BULLET]);

デフォルト: すべてのボディはカテゴリ 0x0001 と collisionMask 1 を持ちます。(1 & 1) !== 0 であるため、すべては依然としてすべてと衝突します。PhysicsGroup のデフォルトはマスク 2147483647(すべてのビット)です。カテゴリを変更した後にマスクをすべてのビットに設定するには、resetCollisionCategory() を呼び出してください。

設定リファレンス

ArcadeWorldConfig -- GameConfig または SceneConfig 内の physics.arcade を介して渡されます:

PropertyDefaultDescription
fps601 秒あたりの物理ステップ数
fixedSteptrueレンダリング同期ではなく固定タイムステップを使用
timeScale1シミュレーション速度の倍率
gravity{ x: 0, y: 0 }ワールドの重力(px/秒)
x, y0ワールド境界の原点
width, heightgame sizeワールド境界のサイズ
checkCollisionall true{ up, down, left, right } の端の衝突
overlapBias4分離のためのオーバーラップしきい値
tileBias16タイルのオーバーラップしきい値
forceXfalse先に水平方向に分離
isPausedfalseシミュレーションを一時停止状態で開始
debugfalseデバッグレンダリングを有効化
debugShowBody / debugShowStaticBody / debugShowVelocitytrueデバッグ表示の切り替え
debugBodyColor / debugStaticBodyColor / debugVelocityColor0xff00ff / 0x0000ff / 0x00ff00デバッグの色
maxEntries16ノードあたりの RTree アイテム数
useTreetrue動的ボディに RTree を使用
customUpdatefalsetrue の場合、自分で world.update() を呼び出します

シーンレベルの設定はゲームレベルの設定を上書きします(マージされます)。

イベント

すべてのイベントは this.physics.world で発行されます:

EventStringConditionCallback Args
COLLIDE'collide'2 つのボディが衝突し、少なくとも一方が onCollide = true を持つ(gameObject1, gameObject2, body1, body2)
OVERLAP'overlap'2 つのボディがオーバーラップし、少なくとも一方が onOverlap = true を持つ(gameObject1, gameObject2, body1, body2)
WORLD_BOUNDS'worldbounds'ボディがワールドの端に当たり、onWorldBounds = true を持つ(body, up, down, left, right)
TILE_COLLIDE'tilecollide'ボディがタイルと衝突する(gameObject, tile, body)
TILE_OVERLAP'tileoverlap'ボディがタイルとオーバーラップする(gameObject, tile, body)
WORLD_STEP'worldstep'各物理ステップの後(delta)
PAUSE'pause'ワールドが一時停止されたなし
RESUME'resume'ワールドが再開されたなし

イベントはボディごとにオプトインが必要です: body.onCollide、body.onOverlap、または body.onWorldBounds を true に設定してください。

API クイックリファレンス

シーンプラグイン (this.physics)
メソッド説明
this.physics.add.sprite(x, y, key, frame)動的ボディを持つスプライトを作成
this.physics.add.image(x, y, key, frame)動的ボディを持つ画像を作成
this.physics.add.staticSprite(x, y, key, frame)静的ボディを持つスプライト
this.physics.add.staticImage(x, y, key, frame)静的ボディを持つ画像
this.physics.add.group(config)動的物理グループ
this.physics.add.staticGroup(config)静的物理グループ
this.physics.add.existing(go, isStatic?)既存のゲームオブジェクトにボディを追加
this.physics.add.body(x, y, w?, h?)単独の動的ボディ (GO なし)
this.physics.add.staticBody(x, y, w?, h?)単独の静的ボディ (GO なし)
this.physics.add.collider(a, b, cb?, proc?, ctx?)永続的なコライダー
this.physics.add.overlap(a, b, cb?, proc?, ctx?)永続的なオーバーラップ
this.physics.collide(a, b, cb?, proc?, ctx?)1 回限りの衝突判定
this.physics.overlap(a, b, cb?, proc?, ctx?)1 回限りのオーバーラップ判定
this.physics.nextCategory()次のカテゴリビットマスク
this.physics.pause() / resume()シミュレーションの一時停止/再開
this.physics.accelerateTo(go, x, y, spd?, maxX?, maxY?)指定した点に向かって加速
this.physics.move(go, x, y, spd?, maxTime?)指定した点に向かって指定速度で移動
this.physics.velocityFromAngle(angle, speed?, vec2?)角度 (度) から速度を算出
this.physics.velocityFromRotation(rot, speed?, vec2?)回転 (ラジアン) から速度を算出
this.physics.closest(source, targets?)最も近いボディを取得
this.physics.furthest(source, targets?)最も遠いボディを取得
this.physics.overlapRect(x, y, w, h, dyn?, static?)矩形内のボディを検索
this.physics.overlapCirc(x, y, r, dyn?, static?)円内のボディを検索

その他: accelerateToObject、moveToObject、collideTiles、overlapTiles、enableUpdate、disableUpdate。

ワールド (this.physics.world)
メソッド説明
setBounds(x, y, w, h, left?, right?, up?, down?)境界と端の判定を設定
setBoundsCollision(left?, right?, up?, down?)衝突する端を設定
setFPS(framerate)物理ステップレートを変更
enable(object, bodyType?)オブジェクト/グループ/配列で物理を有効化
disable(object)オブジェクト/グループ/配列で物理を無効化
add(body) / remove(body)シミュレーションにボディを追加/削除
addCollider / addOverlapコライダーを作成 (ファクトリと同じ引数)
removeCollider(collider)コライダーを削除
pause() / resume()シミュレーションの一時停止/再開
createDebugGraphic()デバッグ描画用グラフィックを作成
ボディのメソッド
メソッド説明
setVelocity(x, y) / setVelocityX / setVelocityY速度を設定
setAcceleration(x, y) / setAccelerationX / Y加速度を設定
setMaxVelocity(x, y) / setMaxSpeed(speed)速度の上限
setBounce(x, y) / setDrag(x, y)反発と抵抗
setDamping(bool)減衰モードを有効化
setFriction(x, y) / setGravity(x, y)摩擦とボディごとの重力
setMass(val) / setImmovable(bool) / setPushable(bool)質量と衝突挙動
setSize(w, h, center?) / setOffset(x, y)ボディのサイズ変更/オフセット
setCircle(radius, offX?, offY?)円形ボディに切り替え
setCollideWorldBounds(val, bX?, bY?)ワールド境界との衝突
setBoundsRectangle(rect)カスタム境界矩形
setAllowGravity / setAllowDrag / setAllowRotation物理機能の切り替え
setEnable(val)ボディの有効化/無効化
setCollisionCategory / setCollidesWith / addCollidesWith / removeCollidesWithカテゴリフィルタリング
resetCollisionCategory()デフォルト (すべて) にリセット
reset(x, y) / stop()位置をリセットまたは速度をゼロに

注意点

  1. 本番環境での debug: true -- デバッグ描画は負荷が高くなります。リリースビルドでは必ず無効にしてください。

  2. 静的ボディのトランスフォーム変更 -- 静的ボディのゲームオブジェクトの位置、スケール、原点を変更した後は、body.reset() または gameObject.refreshBody() を呼び出す必要があります。静的ボディは自動同期されません。

  3. collide と overlap -- collide は分離処理を行います(ボディ同士を押し離します)。overlap は何も動かさずに交差を検出するだけです。アイテム収集などのトリガーには overlap を使用してください。

  4. 永続的な Collider と単発チェック -- this.physics.add.collider() は毎フレーム自動的にチェックされる Collider を作成します。this.physics.collide() は単発チェックであり、update() 内で毎フレーム呼び出す必要があります。永続的な Collider を推奨します。

  5. イベントはオプトインが必要 -- ワールドイベント('collide'、'overlap'、'worldbounds')は、対応するボディプロパティ(onCollide、onOverlap、onWorldBounds)が true に設定されている場合にのみ発火します。

  6. 衝突カテゴリのデフォルト -- デフォルトでは、すべてのボディはカテゴリ 0x0001 とマスク 1 を持ちます(PhysicsGroup のデフォルトはマスク 2147483647)。新しいカテゴリ値を取得するには this.physics.nextCategory() を呼び出してください。カテゴリは最大 32 個です。カテゴリを変更した後は、resetCollisionCategory() を使用してマスクをすべてのビットに設定してください。

  7. グループのデフォルトは作成時にのみ適用 -- PhysicsGroup の defaults(velocityX、bounceY など)は、メンバーが追加または作成されるときに適用されます。後から defaults を変更しても、既存のメンバーには遡って反映されません。

  8. customUpdate 設定 -- arcade 設定で customUpdate: true を設定すると、シーンの UPDATE イベントでワールドが自動更新されなくなります。this.physics.world.update(time, delta) を手動で呼び出す必要があります。

  9. useDamping のドラッグ値 -- useDamping が true の場合、ドラッグ値は乗数として機能するため、小さな値(例: 0.05)にしてください。0.05 という値は、ボディが毎秒その速度の 5% を保持することを意味します。

  10. immovable と pushable -- immovable = true は、衝突によってボディがまったく動かされないことを意味します。pushable = false は、ボディが衝突してきたボディに速度を反射して返しますが、分離は依然として可能であることを意味します。

  11. TilemapLayer とのオーバーラップ -- TilemapLayer で overlapOnly を使用する場合、個々のタイルの衝突設定に関係なく、すべてのタイルがチェックされます。

  12. RTree のしきい値 -- RTree 空間インデックス(デフォルトで有効)は、動的ボディの数が非常に多くなると再構築の負荷が高くなります。動的ボディが 5000 個以上の場合は useTree: false の設定を検討してください。

ソースファイルマップ

ファイル目的
src/physics/arcade/ArcadePhysics.jsシーンプラグイン(this.physics) -- collide、overlap、moveTo、accelerateTo、nextCategory
src/physics/arcade/World.js物理ワールド -- ボディ、重力、境界、コライダー、ステップループ、setBounds、addCollider
src/physics/arcade/Body.js動的ボディ -- 速度、加速度、反発、抗力、重力、質量、immovable、pushable
src/physics/arcade/StaticBody.js静的ボディ -- immovable、速度なし、最適化された RTree 検索
src/physics/arcade/Factory.jsthis.physics.add -- sprite、image、group、staticGroup、body、existing、collider、overlap
src/physics/arcade/Collider.jsコライダーオブジェクト -- コールバック付きの永続的な衝突/オーバーラップチェック
src/physics/arcade/PhysicsGroup.jsメンバーごとのデフォルト値を持つ動的物理グループ
src/physics/arcade/StaticPhysicsGroup.js自動更新を備えた静的物理グループ
src/physics/arcade/components/index.jsボディコンポーネントミックスイン -- Acceleration、Angular、Bounce、Collision、Debug、Drag、Enable、Friction、Gravity、Immovable、Mass、Pushable、Size、Velocity
src/physics/arcade/components/Collision.js衝突カテゴリ/マスクメソッド -- setCollisionCategory、setCollidesWith、addCollidesWith、removeCollidesWith
src/physics/arcade/events/イベント定数 -- COLLIDE、OVERLAP、WORLD_BOUNDS、TILE_COLLIDE、TILE_OVERLAP、WORLD_STEP、PAUSE、RESUME
src/physics/arcade/typedefs/ArcadeWorldConfig.jsarcade 物理設定オプションの TypeDef

コメント