Skip to main content

particles

Use this skill when creating particle effects in Phaser 4. Covers ParticleEmitter, emission zones, death zones, particle properties, textures, gravity wells, and particle movement. Triggers on: particles, emitter, particle effect, explosion, fire, smoke.

ソース情報

リポジトリ
phaserjs/phaser
ソースの最終更新活動
2026年4月10日 12:38
検出された SKILL.md の言語
英語
スター
40,564
フォーク
7,183

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

ファイルエクスプローラー
2 ファイル

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
particles
description
Use this skill when creating particle effects in Phaser 4. Covers ParticleEmitter, emission zones, death zones, particle properties, textures, gravity wells, and particle movement. Triggers on: particles, emitter, particle effect, explosion, fire, smoke.
# Particle System > Creating and controlling particle effects in Phaser 4 -- ParticleEmitter creation and configuration, emitter ops (value formats), gravity wells, emission and death zones, flow vs burst modes, following game objects, and particle callbacks. **Key source paths:** `src/gameobjects/particles/` **Related skills:** ../sprites-and-images/SKILL.md, ../loading-assets/SKILL.md ## Quick Start ```js // 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 ``` ## Core Concepts ### ParticleEmitter `ParticleEmitter` extends `GameObject` and is added directly to the display list. It is both a game object (positionable, scalable, maskable) and the emitter itself. There is no separate manager -- `this.add.particles()` returns a `ParticleEmitter` instance. **Factory signature:** ```js 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) ``` **Mixins:** AlphaSingle, BlendMode, Depth, Lighting, Mask, RenderNodes, ScrollFactor, Texture, Transform, Visible. So you can call `setPosition()`, `setScale()`, `setDepth()`, `setBlendMode()`, `setMask()`, `setScrollFactor()`, etc. ### Particle A lightweight object owned by its emitter. Key properties: `x`, `y`, `velocityX/Y`, `accelerationX/Y`, `scaleX/Y`, `alpha`, `angle`, `rotation`, `tint`, `life` (total ms), `lifeCurrent` (remaining ms), `lifeT` (0-1 normalized), `bounce`, `delayCurrent`, `holdCurrent`. Particles are pooled internally -- you never create them manually. ### EmitterOp Value Formats Most config properties (speed, scale, alpha, angle, x, y, etc.) accept flexible value formats: ```js 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 ``` **Emit-only** (no onUpdate): `angle`, `delay`, `hold`, `lifespan`, `quantity`, `speedX`, `speedY`. **Emit + Update** (support start/end, onUpdate): `accelerationX/Y`, `alpha`, `bounce`, `maxVelocityX/Y`, `moveToX/Y`, `rotate`, `scaleX/Y`, `tint`, `x`, `y`. ### Flow vs Explode (Burst) **Flow mode** (`frequency >= 0`): emits `quantity` particles every `frequency` ms. Default is `frequency: 0` (every frame) with `emitting: true`. **Explode mode** (`frequency = -1`): emits a batch all at once, then stops. ```js 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 ``` ## Common Patterns ### Scale, Alpha, and Color Over Lifetime ```js // 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 Interpolation The `color` property interpolates through an array of colors over particle lifetime (overrides `tint`): ```js this.add.particles(400, 300, 'spark', { lifespan: 2000, speed: 100, scale: { start: 0.5, end: 0 }, color: [0xfacc22, 0xf89800, 0xf83600, 0x9f0404], colorEase: 'quad.out' }); ``` ### Tinting Particles ```js this.add.particles(400, 300, 'spark', { tint: 0xff0000 }); // static this.add.particles(400, 300, 'spark', { tint: { start: 0xffffff, end: 0xff0000 } }); // over lifetime ``` ### Gravity Wells A `GravityWell` applies inverse-square gravitational force, pulling (or repelling with negative `power`) particles toward a point. ```js 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); ``` ### Emission Zones (Random) A `RandomZone` spawns particles at random positions within a shape. The source must have a `getRandomPoint(point)` method -- all Phaser geometry classes (Circle, Ellipse, Rectangle, Triangle, Polygon, Line) support this, or provide a custom source: ```js // 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; } } }); ``` ### Emission Zones (Edge) An `EdgeZone` places particles sequentially along shape edges. The source must have a `getPoints(quantity, stepRate)` method. Curves, Paths, and all geometry shapes support this: ```js 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 }); ``` **Multiple emission zones:** Pass an array to `emitZone` or call `addEmitZone()` multiple times. Zones iterate in sequence. The `total` property controls how many particles emit before rotating to the next zone (-1 = never rotate). ```js 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) } ] }); ``` ### Death Zones A `DeathZone` kills particles when they enter (or leave) a region. The source must have a `contains(x, y)` method. ```js // 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 } }); ``` ### Following a Game Object ```js 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 } }); ``` ### Particle Callbacks ```js // 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, and Advance ```js // 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); ``` ### Particle Bounds (Bounce) ```js 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); ``` ### Texture Frames and Animations ```js // 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', {
GitHubで見る
この SKILL.md は非常に大きいため、SkillsMP では最初のセクションだけを表示しています。 GitHubで見る