mcpField
P
particles

particles

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

particles について

Phaser 4 開発者向けのパーティクルシステムスキルです。ParticleEmitter の作成と設定から、発生、更新、寿命の制御まで扱い、発生モードやゾーン、独自の処理方法も解説します。

主な機能

  1. 01ParticleEmitter の作成と設定
  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 particles

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

同梱ファイルreferences/REFERENCE.md

詳細

パーティクルシステム

Phaser 4 でパーティクルエフェクトを作成および制御する -- ParticleEmitter の作成と設定、エミッター操作(値の形式)、重力ウェル、放出ゾーンと消滅ゾーン、フローモードとバーストモード、ゲームオブジェクトへの追従、およびパーティクルコールバック。

主要なソースパス: src/gameobjects/particles/ 関連スキル: ../sprites-and-images/SKILL.md, ../loading-assets/SKILL.md

クイックスタート

// In a Scene's create() method:

// Basic continuous emitter (flow mode)
const emitter = this.add.particles(400, 300, 'flares', {
    frame: 'red',
    speed: 200,
    lifespan: 2000,
    scale: { start: 1, end: 0 },
    alpha: { start: 1, end: 0 },
    gravityY: 150
});

// One-shot burst (explode mode)
const burst = this.add.particles(400, 300, 'flares', {
    frame: 'blue',
    speed: { min: 100, max: 300 },
    lifespan: 1000,
    scale: { start: 0.5, end: 0 },
    emitting: false   // don't auto-start
});
burst.explode(20);    // emit 20 particles at once

コアコンセプト

ParticleEmitter

ParticleEmitter は GameObject を拡張し、ディスプレイリストに直接追加されます。これはゲームオブジェクト(位置指定、拡大縮小、マスク可能)であると同時に、エミッターそのものです。独立したマネージャーは存在しません -- this.add.particles() は ParticleEmitter インスタンスを返します。

ファクトリシグネチャ:

this.add.particles(x, y, texture, config);
// x, y: world position (both optional, default 0)
// texture: string key or Texture instance
// config: ParticleEmitterConfig object (optional, can call setConfig later)

ミックスイン: AlphaSingle、BlendMode、Depth、Lighting、Mask、RenderNodes、ScrollFactor、Texture、Transform、Visible。したがって、setPosition()、setScale()、setDepth()、setBlendMode()、setMask()、setScrollFactor() などを呼び出せます。

Particle

エミッターが所有する軽量オブジェクトです。主なプロパティ: x、y、velocityX/Y、accelerationX/Y、scaleX/Y、alpha、angle、rotation、tint、life(合計ミリ秒)、lifeCurrent(残りミリ秒)、lifeT(0〜1 に正規化)、bounce、delayCurrent、holdCurrent。パーティクルは内部的にプールされます -- 手動で作成することはありません。

EmitterOp の値の形式

ほとんどの設定プロパティ(speed、scale、alpha、angle、x、y など)は柔軟な値の形式を受け付けます:

x: 400                                        // static value
x: [100, 200, 300, 400]                       // random pick from array
x: { min: 100, max: 700 }                     // random float in range
x: { min: 100, max: 700, int: true }          // random integer
x: { random: [100, 700] }                     // random integer shorthand
scale: { start: 0, end: 1 }                   // ease over lifetime (default linear)
scale: { start: 0, end: 1, ease: 'bounce.out' }  // custom ease
scale: { start: 4, end: 0.5, random: true }   // random start, ease to end
x: { values: [50, 500, 200, 800], interpolation: 'catmull' }  // interpolation
x: { steps: 32, start: 0, end: 576 }          // stepped sequential
x: { steps: 32, start: 0, end: 576, yoyo: true }  // stepped with yoyo
x: {                                           // custom callbacks
    onEmit: (particle, key, t, value) => value,
    onUpdate: (particle, key, t, value) => value
}
x: (particle, key, t, value) => value + 50    // emit-time callback shorthand

放出のみ(onUpdate なし): angle、delay、hold、lifespan、quantity、speedX、speedY。 放出 + 更新(start/end、onUpdate をサポート): accelerationX/Y、alpha、bounce、maxVelocityX/Y、moveToX/Y、rotate、scaleX/Y、tint、x、y。

フローとエクスプロード(バースト)

フローモード(frequency >= 0): frequency ミリ秒ごとに quantity 個のパーティクルを放出します。デフォルトは frequency: 0(毎フレーム)で emitting: true です。

エクスプロードモード(frequency = -1): バッチを一度にまとめて放出し、その後停止します。

emitter.flow(100, 5);           // 5 particles every 100ms
emitter.flow(100, 5, 50);       // auto-stop after 50 total
emitter.explode(30, 200, 400);  // burst 30 at position
emitter.explode(30);            // burst at emitter position

一般的なパターン

ライフタイムに応じたスケール、アルファ、カラーの変化
// Scale and alpha with custom easing
this.add.particles(400, 300, 'spark', {
    lifespan: 2000,
    speed: 100,
    scale: { start: 1, end: 0, ease: 'power2' },
    alpha: { start: 1, end: 0, ease: 'cubic.in' }
});
カラーの補間

color プロパティはパーティクルのライフタイムにわたってカラーの配列を通じて補間します(tint を上書きします):

this.add.particles(400, 300, 'spark', {
    lifespan: 2000, speed: 100, scale: { start: 0.5, end: 0 },
    color: [0xfacc22, 0xf89800, 0xf83600, 0x9f0404], colorEase: 'quad.out'
});
パーティクルの着色
this.add.particles(400, 300, 'spark', { tint: 0xff0000 });                           // static
this.add.particles(400, 300, 'spark', { tint: { start: 0xffffff, end: 0xff0000 } }); // over lifetime
重力ウェル

GravityWell は逆二乗の引力を適用し、パーティクルを点に向かって引き寄せます(負の power で反発させます)。

const emitter = this.add.particles(400, 300, 'spark', {
    speed: 100, lifespan: 4000, scale: { start: 0.4, end: 0 }, quantity: 2
});

const well = emitter.createGravityWell({
    x: 400, y: 300, power: 2, epsilon: 100, gravity: 50
});

// Update at runtime
well.x = 300;
well.power = -1;  // negative = repel

// Or create manually and add
const well2 = new Phaser.GameObjects.Particles.GravityWell(500, 200, 3, 100, 50);
emitter.addParticleProcessor(well2);
emitter.removeParticleProcessor(well2);
放出ゾーン(ランダム)

RandomZone は図形内のランダムな位置にパーティクルを生成します。ソースには getRandomPoint(point) メソッドが必要です -- すべての Phaser ジオメトリクラス(Circle、Ellipse、Rectangle、Triangle、Polygon、Line)がこれをサポートしています。またはカスタムソースを提供します:

// Using built-in geometry
this.add.particles(400, 300, 'spark', {
    speed: 50, lifespan: 2000,
    emitZone: { type: 'random', source: new Phaser.Geom.Circle(0, 0, 100) }
});

// Custom source object (any object with getRandomPoint)
emitter.addEmitZone({
    type: 'random',
    source: {
        getRandomPoint: (point) => {
            const a = Math.random() * Math.PI * 2;
            point.x = Math.cos(a) * 100;
            point.y = Math.sin(a) * 50;
            return point;
        }
    }
});
放出ゾーン(エッジ)

EdgeZone は図形のエッジに沿ってパーティクルを順番に配置します。ソースには getPoints(quantity, stepRate) メソッドが必要です。Curve、Path、およびすべてのジオメトリ図形がこれをサポートしています:

this.add.particles(400, 300, 'spark', {
    lifespan: 1500, speed: 20,
    emitZone: {
        type: 'edge',
        source: new Phaser.Geom.Circle(0, 0, 150),
        quantity: 48,     // number of points on edge (use 0 with stepRate instead)
        yoyo: false,      // reverse direction at ends
        seamless: true    // remove duplicate endpoint
    }
});

// Or add post-creation with any source that has getPoints
emitter.addEmitZone({ type: 'edge', source: geom, quantity: 50, yoyo: false, seamless: true });

複数の放出ゾーン: emitZone に配列を渡すか、addEmitZone() を複数回呼び出します。ゾーンは順番に反復されます。total プロパティは、次のゾーンに切り替わるまでに何個のパーティクルを放出するかを制御します(-1 = 切り替えない)。

this.add.particles(400, 300, 'spark', {
    emitZone: [
        { type: 'random', source: new Phaser.Geom.Circle(0, 0, 50) },
        { type: 'random', source: new Phaser.Geom.Circle(200, 0, 50) }
    ]
});
消滅ゾーン

DeathZone はパーティクルが領域に入ったとき(または出たとき)に消滅させます。ソースには contains(x, y) メソッドが必要です。

// Kill particles entering a rectangle
this.add.particles(400, 100, 'spark', {
    speed: 200, lifespan: 5000, gravityY: 100,
    deathZone: { type: 'onEnter', source: new Phaser.Geom.Rectangle(300, 400, 200, 50) }
});

// Kill particles leaving a circle (confine to area)
this.add.particles(400, 300, 'spark', {
    speed: 100, lifespan: 5000,
    deathZone: { type: 'onLeave', source: new Phaser.Geom.Circle(400, 300, 150) }
});

// Custom death zone source (any object with contains)
emitter.addDeathZone({
    type: 'onEnter',
    source: { contains: (x, y) => x > 600 && y > 400 }
});
ゲームオブジェクトへの追従
const player = this.add.sprite(100, 100, 'player');
const emitter = this.add.particles(0, 0, 'spark', {
    speed: 50, lifespan: 800, scale: { start: 0.5, end: 0 }
});

emitter.startFollow(player);                       // follow position
emitter.startFollow(player, 10, -20);              // with offset
emitter.startFollow(player, 0, 0, true);           // track visibility too
emitter.stopFollow();

// Or via config:
this.add.particles(0, 0, 'spark', { follow: player, followOffset: { x: 0, y: -20 } });
パーティクルコールバック
// Via config
const emitter = this.add.particles(400, 300, 'spark', {
    speed: 100, lifespan: 2000,
    emitCallback: (particle, emitter) => { /* on emit */ },
    deathCallback: (particle) => { /* on death */ }
});

// Or set after creation
emitter.onParticleEmit((particle, emitter) => { /* ... */ });
emitter.onParticleDeath((particle) => { /* ... */ });

// Iterate alive/dead particles
emitter.forEachAlive((particle, emitter) => { /* particle.x, particle.lifeT */ });
Duration、StopAfter、Advance
// Auto-stop after 3 seconds (alive particles continue until they expire)
this.add.particles(400, 300, 'spark', { speed: 100, duration: 3000 });

// Emit exactly 50 particles then stop
this.add.particles(400, 300, 'spark', { speed: 100, stopAfter: 50 });

// Pre-warm: fast-forward 2 seconds so particles visible on first frame
this.add.particles(400, 300, 'spark', { speed: 100, lifespan: 2000, advance: 2000 });
// Or manually: emitter.fastForward(2000, 50);
パーティクルの境界(バウンス)
this.add.particles(400, 300, 'spark', {
    speed: 200, lifespan: 5000, bounce: 0.8,
    bounds: { x: 100, y: 100, width: 600, height: 400 },
    collideLeft: true, collideRight: true, collideTop: true, collideBottom: true
});
// Or: emitter.addParticleBounds(100, 100, 600, 400);
テクスチャフレームとアニメーション
// Random frame per particle
this.add.particles(400, 300, 'flares', { frame: ['red', 'green', 'blue'] });

// Sequential frames cycling through with quantity per frame
this.add.particles(400, 300, 'flares', {
    frame: { frames: ['red', 'green', 'blue'], cycle: true, quantity: 4 }
});

// Particle animation (plays anim over particle lifetime)
this.add.particles(400, 300, 'explosion', { anim: 'explode_anim', lifespan: 1000 });

// Multiple anims, randomly assigned
this.add.particles(400, 300, 'sheet', {
    anim: { anims: ['fire', 'smoke'], cycle: false, quantity: 1 }
});
パーティクルのソート
this.add.particles(400, 300, 'spark', { sortProperty: 'y', sortOrderAsc: true });
// Or: sortCallback: (a, b) => a.y - b.y
カスタムパーティクルプロセッサー

ParticleProcessor を拡張して、毎フレームカスタムのパーティクルごとのロジックを適用します。update(particle, delta, step, t) を実装します:

class WindProcessor extends Phaser.GameObjects.Particles.ParticleProcessor {
    constructor (windX, windY) {
        super(0, 0);
        this.windX = windX;
        this.windY = windY;
    }

    update (particle, delta, step, t) {
        particle.velocityX += this.windX * step;
        particle.velocityY += this.windY * step;
    }
}

emitter.addParticleProcessor(new WindProcessor(0.5, 0));
カスタムパーティクルクラス

Particle を拡張し、パーティクルごとの動作のために update をオーバーライドします。設定の particleClass で設定します:

class TrailParticle extends Phaser.GameObjects.Particles.Particle {
    update (delta, step, processors) {
        const result = super.update(delta, step, processors);
        this.alpha = this.lifeT;  // custom: alpha matches life progress
        return result;  // must return true if particle is still alive
    }
}

this.add.particles(400, 300, 'spark', {
    particleClass: TrailParticle,
    speed: 100, lifespan: 2000
});

設定リファレンス

ParticleEmitterConfig -- シンプルプロパティ
プロパティ型デフォルト説明
activebooleantruefalse = エミッターはまったく更新されません
emittingbooleantruefalse = 新しいパーティクルを生成しません(生存中のパーティクルは引き続き更新されます)
blendModestring/number0レンダリング時のブレンドモード
frequencynumber0フローサイクル間のミリ秒。0 = 毎フレーム、-1 = 爆発
gravityX, gravityYnumber0重力(px/s^2)
maxParticlesnumber0パーティクルオブジェクトの総数の上限(0 = 無制限)
maxAliveParticlesnumber0同時に生存できるパーティクルの最大数(0 = 無制限)
durationnumber0指定ミリ秒後に自動停止(0 = 無期限)
stopAfternumber0N 個のパーティクルを放出した後に自動停止(0 = 無制限)
advancenumber0生成時に早送りする時間(ミリ秒)
radialbooleantruetrue = speed+angle、false = speedX/speedY
particleBringToTopbooleantrue新しいパーティクルを最前面に描画します
timeScalenumber1更新時の時間倍率
followVector2Likenull追従するオブジェクト
followOffsetVector2Like追従ターゲットからのオフセット
trackVisiblebooleanfalse追従ターゲットの表示状態に合わせます
reservenumberパーティクルオブジェクトを事前に確保します
particleClassfunctionParticleカスタムパーティクルクラス
sortPropertystringソートに使用するパーティクルのプロパティ
sortOrderAscbooleantrue の場合は昇順でソートします
ParticleEmitterConfig -- EmitterOp プロパティ

すべて、上記で説明した柔軟な値の形式を受け付けます。

プロパティデフォルトE/U説明
x, y0E+Uエミッターからのパーティクルのオフセット
speed0E放射方向の速度(speedX を設定し、speedY を無効化します)
speedX, speedY0E方向別の速度(radial=false を設定します)
angle{min:0,max:360}E放出角度(度)
scale1E+U均一スケール(scaleX を設定し、scaleY を無効化します)
scaleX, scaleY1E+U非均一スケール
alpha1E+Uアルファ透明度
rotate0E+U回転(度)
tint0xffffffE+Uティントカラー(WebGL)
colorE+U補間するカラー配列(tint を上書きします)
colorEaseカラー補間のイージング
lifespan1000E生存時間(ミリ秒)
delay0E表示されるまでの遅延(ミリ秒)
hold0E消滅前に寿命の終わりで保持する時間(ミリ秒)
quantity1Eフローサイクルごとのパーティクル数
accelerationX/Y0E+U加速度(px/s^2)
maxVelocityX/Y10000E+U最大速度
bounce0E+U反発係数(0~1)
moveToX, moveToY0E+Uターゲット位置(angle/speed を上書きします)

E = 放出のみ、E+U = 放出 + 更新(start/end、onUpdate をサポート)

Zone 設定プロパティ
設定キー型プロパティ
emitZoneobject または array{ type: 'random', source: <shape> }
{ type: 'edge', source: <shape>, quantity, stepRate, yoyo, seamless, total }
deathZoneobject または array{ type: 'onEnter'|'onLeave', source: <shape> }
boundsobject{ x, y, width, height } または { x, y, w, h }

イベント

すべてのイベントは ParticleEmitter インスタンス自体で発行されます。

イベント文字列コールバック引数発生タイミング
START'start'(emitter)start() が呼び出され、エミッターが放出を開始したとき
STOP'stop'(emitter)stop() が呼び出されたとき、または duration/stopAfter の上限に達したとき
COMPLETE'complete'(emitter)エミッターの停止後、最後の生存パーティクルが消滅したとき
EXPLODE'explode'(emitter, particle)explode() が呼び出されたとき
DEATH_ZONE'deathzone'(emitter, particle, zone)デスゾーンがパーティクルを消滅させたとき
emitter.on('stop', (emitter) => { /* stopped emitting */ });
emitter.on('complete', (emitter) => { /* all particles dead */ });
emitter.on('deathzone', (emitter, particle, zone) => { /* ... */ });

API クイックリファレンス

ParticleEmitter の主要メソッド

ライフサイクル: start(advance?, duration?)、stop(kill?)、pause()、resume()、flow(frequency, count?, stopAfter?)、explode(count?, x?, y?)、emitParticleAt(x?, y?, count?)、emitParticle(count?, x?, y?)、fastForward(time, delta?)。

設定: setConfig(config)、updateConfig(config)。

追従: startFollow(target, offX?, offY?, trackVisible?)、stopFollow()。

ゾーン: addEmitZone(config)、removeEmitZone(zone)、clearEmitZones()、addDeathZone(config)、removeDeathZone(zone)、clearDeathZones()。

プロセッサー: createGravityWell(config)、addParticleProcessor(processor)、removeParticleProcessor(processor)、getProcessors()。

境界: addParticleBounds(x, y, w, h, collideL?, collideR?, collideT?, collideB?)。

コールバック/イテレーション: onParticleEmit(cb, ctx?)、onParticleDeath(cb, ctx?)、killAll()、forEachAlive(cb, ctx?)、forEachDead(cb, ctx?)。

カウント: getAliveParticleCount()、getDeadParticleCount()、getParticleCount()、atLimit()、reserve(count)。

プロパティセッター: setParticleSpeed(x, y?)、setParticleScale(x, y)、setParticleGravity(x, y)、setParticleAlpha(value)、setParticleTint(value)、setParticleLifespan(value)、setEmitterAngle(value)、setQuantity(qty)、setFrequency(freq, qty?)、setRadial(value)、setEmitterFrame(frames, random?, qty?)、setAnim(anims, random?, qty?)。

並べ替え: setSortProperty(property, ascending?)、setSortCallback(callback)、depthSort()。

ユーティリティ: getBounds(padding?, advance?, delta?, output?)、overlap(target)。

GravityWell
プロパティ/メソッド説明
x、yウェルのワールド座標
power力の強さ(負の値で反発)
epsilon力の計算における最小距離(デフォルト 100)
gravity重力定数(デフォルト 50)
active処理の有効/無効(ParticleProcessor から継承)

コンストラクター: new GravityWell(x, y, power, epsilon, gravity) または new GravityWell(config)。ここで config は { x, y, power, epsilon, gravity } です。

注意点

  • ParticleEmitterManager はありません: v3.60 で削除されました。this.add.particles() は ParticleEmitter を直接返します。
  • speed と speedX/speedY: speed は speedX を設定し、speedY を無効化します(放射状)。speedX/speedY はポイントモード(radial: false)に切り替えます。
  • scale と scaleX/scaleY: scale は scaleX に適用され、scaleY を無効化します。非均一なスケーリングには両方を使用してください。
  • color は tint を上書きします: これらは排他的であり、color(配列)が優先されます。
  • moveToX/moveToY: 有効化するには両方を設定する必要があります。angle と speed を上書きします。
  • emitting と active: emitting: false = 新しいパーティクルは生成されませんが、生存中のパーティクルは更新されます。active: false = エミッター全体が凍結されます。
  • stop と complete: 'stop' はエミッションが停止したときに発火します。'complete' は最後の生存パーティクルが消滅したときに発火します。
  • frequency: 0: 「決して生成しない」ではなく、毎フレーム生成する(最大レート)という意味です。生成を防ぐには emitting: false を使用してください。
  • frequency: -1: エミッターを爆発モードにします -- 自動的には流れません。バーストを生成するには explode() を使用してください。
  • hold はパーティクルを凍結します: ライフスパンが切れた後、hold は指定されたミリ秒の間、パーティクルを表示したまま凍結し、その後消滅させます。トレイルや残留エフェクトに便利です。
  • advance は早送りします: 作成時に指定されたミリ秒をシミュレートしてエミッターを事前に温めるため、最初のフレームですでにパーティクルが表示されます。
  • reserve(count) は事前に割り当てます: reserve() を呼び出すか、設定で reserve を指定して、パーティクルオブジェクトを事前に作成し、ゲームプレイ中のオンデマンド割り当てによる GC スパイクを回避します。
  • ゾーンソースのメソッド: RandomZone には getRandomPoint(point) が必要です。EdgeZone には getPoints(quantity, stepRate) が必要です。DeathZone には contains(x, y) が必要です。
  • パーティクルプール: maxParticles は総オブジェクト数(生存数ではない)を制限します。表示数の制限には maxAliveParticles を使用してください。
  • テクスチャが必要です: エミッターには有効なテクスチャキーが必要です。マルチフレームテクスチャには frame 設定を使用してください。

ソースファイル

完全なソースファイルマップについては references/REFERENCE.md を参照してください。主要なエントリポイント: src/gameobjects/particles/ParticleEmitter.js(メインクラス)、src/gameobjects/particles/Particle.js(個々のパーティクル)、src/gameobjects/particles/zones/(ゾーンクラス)。

コメント