GoldFire

More advanced particles?

Recommended Posts

We are in the process of porting our Phaser-CE game to Phaser 3 and have been using Particle Storm. We were able to make a lot of great particle effects with this and it looked like the Phaser 3 particle system was fairly similar. However, we are finding some serious limitations that render the vast majority of our particle effects impossible in Phaser 3. I'm hoping this isn't actually the case and I'm just overlooking something. For example, a lot of our particles start with a random alpha value, fade in from 0 to full opacity at the half point and then back to 0 at the end:

alpha {
  value: {min: 0.5, max: 1},
  control: [{x: 0, y: 0}, {x: 0.5, y: 1}, {x: 1, y: 0}],
}

However, two issues in Phaser 3:

1. You can't use min/max in addition to start/end, so it is an either/or with having random values and values that tween.

2. You can no longer define a control, you can only provide an easing function, which means you can only either fade in or fade out, but not both.

Is there any way to accomplish this in Phaser 3 that I'm overlooking?

Share this post


Link to post
Share on other sites

With some help of some nice people in the Discord channel, we came to the conclusion that this isn't possible with the standard particle system. However, we also found that you could pass custom onEmit and onUpdate methods to the emitter, which allowed for a custom solution to add this functionality. Since we were porting from Phaser 2 with Particle Storm, I decided to write this in a way that prevented us from having to re-do all of our particle configs, so we simply include value and control in the same format and pass the following two methods as onEmit and onUpdate.

/**
 * Custom particle update callback that handles Particle Storm style controls.
 * @param  {Object} particle Particle to act on.
 * @param  {String} key      Property name.
 * @return {Number}          New value.
 */
static controlUpdate(particle, key) {
  const {control} = particle.emitter[key].propertyValue;
  const initial = particle[`${key}Initial`] || 1;
  const percent = particle.lifeT;
  let index = 0;
  let point = control[index];

  if (point.x === percent) {
    return point.y;
  }

  // Find the next point based on the current percent.
  while (point.x <= percent) {
    if (index >= control.length - 1) {
      return point.x;
    }

    index += 1;
    point = control[index];
  }

  const prev = control[index - 1];

  // Follow curve with linear interpolation: f(x) = y0 + (y1 - y0) * (x - x0) / (x1 - x0).
  const valueMulti = prev.y + (percent - prev.x) * (point.y - prev.y) / (point.x - prev.x);

  return valueMulti * initial;
}

/**
 * Custom particle emit event to set the initial value.
 * @param  {Object} particle Particle to act on.
 * @param  {String} key      Property name.
 */
static initialOnEmit(particle, key) {
  const values = particle.emitter[key].propertyValue;

  // Handle a random value.
  if (typeof values.value === 'object') {
    particle[`${key}Initial`] = randomBetween(values.value.min, values.value.max);
  } else if (values.value) {
    particle[`${key}Initial`] = values.value;
  }
}

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.