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
آخر نشاط في المصدر
١٠ أبريل ٢٠٢٦ في ١٢:٣٨
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٤٠٬٤٩٠
التفرعات
٧٬١٧٣

خيارات التثبيت

يُحدَّد 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