How to make the particle rotation angle align in the direction of the emission

I want to have my particle emitter rotate the emitted particle in the direction angle it is moving.

The spritesheet I am using-
IMG-20231224-0003

What I am getting -

What I want to achieve -

1 Like
rotate: { onEmit: updateParticleRotation, onUpdate: updateParticleRotation },

1 Like

Thank you Samme ,this is want i needed.

Nice, I was about to post the same question. :+1:

Just want to add that you can combine 2 or more Phaser particle emitters for some pretty cool effects. A lot of Nintendo and arcade games have these types of particle effects, see the example screenshot below

@samme quick follow-up question.

I was able to use your code example using onEmit and onUpdate on the particle. See the code example below it is modified from this example, you can copy&paste it in the Phaser sandbox

The explosion lines emitter uses the onUpdate call, meaning it will be called every frame. But it only needs to be called once to set the angle and then it doesn’t change. However, when I change onUpdate to onEmit the angles aren’t correct. It looks like it uses a sprite-pool and the angle is based on the previous (re-used) particle velocity.

So is there any way to only use onEmit and not onUpdate? :thinking: Not sure if it impacts the performance that much, but I figure it’s always something.

class Example extends Phaser.Scene
{
    preload ()
    {
        this.load.atlas('flares', 'assets/particles/flares.png', 'assets/particles/flares.json');
    }

    create ()
    {
        // big flash particle
        this.emit_blast = this.add.particles(0, 0, 'flares', {
            frame: [ 'red', 'yellow', 'green' ],
            lifespan: 100,
            scale: { min: 4.0, max: 6.0 },
            blendMode: 'ADD',
            emitting: false
        });

        // smaller falling particles
        this.emit_particles = this.add.particles(0, 0, 'flares', {
            frame: [ 'red', 'yellow', 'green' ],
            lifespan: 4000,
            speed: { min: 150, max: 250 },
            scale: { start: 0.8, end: 0 },
            gravityY: 150,
            blendMode: 'ADD',
            emitting: false
        });

        // explosion streaks, lines in angled in move direction
        this.emit_sparks = this.add.particles(0, 0, 'flares', {
            frame: [ 'red', 'yellow', 'green' ],
            lifespan: 1000,
            speed: { min: 500, max: 1000 },
            scaleX: 3.0,
            scaleY: 0.2,
            rotate: { onUpdate: function(p) { return Phaser.Math.RadToDeg(Math.atan2(p.velocityY, p.velocityX)); } },
            blendMode: 'ADD',
            emitting: false
        });

        // click mouse for explosion
        this.input.on('pointerdown', function(pointer) {
            this.doExplosion(pointer.x, pointer.y);
        }.bind(this));

        this.add.text(10, 10, 'Click to explode emit particles');
    }

    doExplosion(x, y)
    {
        this.emit_blast.explode(3, x, y);      // one big blast circle
        this.emit_particles.explode(12, x, y); // explosion particles
        this.emit_sparks.explode(8, x, y);     // explosion lines
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#000',
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);
1 Like

The problem with onEmit is that for most properties it’s called before the particle velocity is set.

An alternative is to use a custom Particle class (particleClass):

class AngledParticle extends Phaser.GameObjects.Particles.Particle {
    fire(x, y) {        
        const isAlive = super.fire(x, y);

        this.rotation = Math.atan2(this.velocityY, this.velocityX);
        this.angle = Phaser.Math.RadToDeg(this.rotation);

        return isAlive;
    }
}
this.emit_sparks = this.add.particles(0, 0, 'flares', {
    particleClass: AngledParticle,
    // etc.
});

@samme Thanks for the tip, that looks very useful. I think it could also be used for other effects, like the particles starting in evenly spaced out (instead of random) or in a ring formation away from the center etc.

However, I couldn’t get the class to work, I mean how do I hook the AngledParticle up to an emitter? :thinking: I’ve found other documentation here but no mention of how add it to emitters.

I left that out, sorry. You pass it as particleClass in the particle emitter config (edited above).

@samme Ah I see thanks. Using a custom particle class opens up all kind of possibilities for new effects.

When an emitter calls .explode(16) to create 16 particles, is there a way to read the explosion index from inside the particle? :thinking: So that from inside the onEmit or fire method, the particle can somehow know its sequence order in the explosion, so for example that it is the 5th particle?

I’m asking because I’m looking for a way to create a perfect circle (or star shape etc) of exploding particles. It could be done using the Math.sin and Math.cos in the particles, to set their initial location, but you’d need the index or order nr of the particle.

No, but if you call emitParticle(1, x, y) you could track this yourself.

However, you can also use explode() with Emit Zone shapes. Set an emitter quantity equal to the zone quantity and use a long lifespan, for example.

I forgot there’s emitCallback, which is easier than using a custom particle class.

this.emit_sparks = this.add.particles(0, 0, 'flares', {
  // etc.
  emitCallback: (particle) => {
    particle.angle = Phaser.Math.RadToDeg(
      Math.atan2(particle.velocityY, particle.velocityX)
    );
  }
});