<canvas id="main"></canvas>
* {padding: 0; margin: 0}
/* Dust Plugin */
class Dust {
  constructor(renderingEngine = PIXI) {
    if (renderingEngine === undefined) throw new Error("Please assign a rendering engine in the constructor before using pixiDust.js");

    //Find out which rendering engine is being used (the default is Pixi)
    this.renderer = "";

    //If the `renderingEngine` is Pixi, set up Pixi object aliases
    if (renderingEngine.ParticleContainer) {
      this.Container = renderingEngine.Container;
      this.renderer = "pixi";
    }

    //The `particles` array stores all the particles you make
    this.globalParticles = [];
  }

  //Random number functions
  randomFloat(min, max) {
    return min + Math.random() * (max - min);
  }
  randomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }

  //Use the create function to create new particle effects
  create(
    x = 0,
    y = 0,
    spriteFunction = () => console.log("Sprite creation function"),
    container = () => new this.Container(),
    numberOfParticles = 20,
    gravity = 0,
    randomSpacing = true,
    minAngle = 0, maxAngle = 6.28,
    minSize = 4, maxSize = 16,
    minSpeed = 0.3, maxSpeed = 3,
    minScaleSpeed = 0.01, maxScaleSpeed = 0.05,
    minAlphaSpeed = 0.02, maxAlphaSpeed = 0.02,
    minRotationSpeed = 0.01, maxRotationSpeed = 0.03
  ) {

    //An array to store the curent batch of particles
    let particles = [];

    //Add the current `particles` array to the `globalParticles` array
    this.globalParticles.push(particles);

    //An array to store the angles
    let angles = [];

    //A variable to store the current particle's angle
    let angle;

    //Figure out by how many radians each particle should be separated
    let spacing = (maxAngle - minAngle) / (numberOfParticles - 1);

    //Create an angle value for each particle and push that //value into the `angles` array
    for (let i = 0; i < numberOfParticles; i++) {

      //If `randomSpacing` is `true`, give the particle any angle 
      //value between `minAngle` and `maxAngle`
      if (randomSpacing) {
        angle = this.randomFloat(minAngle, maxAngle);
        angles.push(angle);
      }

      //If `randomSpacing` is `false`, space each particle evenly, 
      //starting with the `minAngle` and ending with the `maxAngle`
      else {
        if (angle === undefined) angle = minAngle;
        angles.push(angle);
        angle += spacing;
      }
    }

    //A function to make particles
    let makeParticle = (angle) => {

      //Create the particle using the supplied sprite function
      let particle = spriteFunction();

      //Display a random frame if the particle has more than 1 frame
      if (particle.totalFrames > 0) {
        particle.gotoAndStop(this.randomInt(0, particle.totalFrames - 1));
      }

      //Set a random width and height
      let size = this.randomInt(minSize, maxSize);
      particle.width = size;
      particle.height = size;

      //Set the particle's `anchor` to its center
      particle.anchor.set(0.5, 0.5);

      //Set the x and y position
      particle.x = x;
      particle.y = y;

      //Set a random speed to change the scale, alpha and rotation
      particle.scaleSpeed = this.randomFloat(minScaleSpeed, maxScaleSpeed);
      particle.alphaSpeed = this.randomFloat(minAlphaSpeed, maxAlphaSpeed);
      particle.rotationSpeed = this.randomFloat(minRotationSpeed, maxRotationSpeed);

      //Set a random velocity at which the particle should move
      let speed = this.randomFloat(minSpeed, maxSpeed);
      particle.vx = speed * Math.cos(angle);
      particle.vy = speed * Math.sin(angle);

      //Push the particle into the `particles` array.
      //The `particles` array needs to be updated by the game loop each frame particles.push(particle);
      particles.push(particle);

      //Add the particle to its parent container
      container.addChild(particle);

      //The particle's `updateParticle` method is called on each frame of the 
      //game loop
      particle.updateParticle = () => {

        //Add gravity
        particle.vy += gravity;

        //Move the particle
        particle.x += particle.vx;
        particle.y += particle.vy;

        //Change the particle's `scale`
        if (particle.scale.x - particle.scaleSpeed > 0) {
          particle.scale.x -= particle.scaleSpeed;
        }
        if (particle.scale.y - particle.scaleSpeed > 0) {
          particle.scale.y -= particle.scaleSpeed;
        }

        //Change the particle's rotation
        particle.rotation += particle.rotationSpeed;

        //Change the particle's `alpha`
        particle.alpha -= particle.alphaSpeed;

        //Remove the particle if its `alpha` reaches zero
        if (particle.alpha <= 0) {
          container.removeChild(particle);
          particles.splice(particles.indexOf(particle), 1);
        }
      };
    };

    //Make a particle for each angle
    angles.forEach(angle => makeParticle(angle));

    //Return the `particles` array back to the main program
    return particles;
  }

  //A particle emitter
  emitter(interval, particleFunction) {
    let emitterObject = {},
      timerInterval = undefined;

    emitterObject.playing = false;

    function play() {
      if (!emitterObject.playing) {
        particleFunction();
        timerInterval = setInterval(emitParticle.bind(this), interval);
        emitterObject.playing = true;
      }
    }

    function stop() {
      if (emitterObject.playing) {
        clearInterval(timerInterval);
        emitterObject.playing = false;
      }
    }

    function emitParticle() {
      particleFunction();
    }

    emitterObject.play = play;
    emitterObject.stop = stop;
    return emitterObject;
  }

  //A function to update the particles in the game loop
  update() {

    //Check so see if the `globalParticles` array contains any
    //sub-arrays
    if (this.globalParticles.length > 0) {

      //If it does, Loop through the particle arrays in reverse
      for (let i = this.globalParticles.length - 1; i >= 0; i--) {

        //Get the current particle sub-array
        let particles = this.globalParticles[i];

        //Loop through the `particles` sub-array and update the
        //all the particle sprites that it contains
        if (particles.length > 0) {
          for (let j = particles.length - 1; j >= 0; j--) {
            let particle = particles[j];
            particle.updateParticle();
          }
        }

        //Remove the particle array from the `globalParticles` array if doesn't
        //contain any more sprites
        else {
          this.globalParticles.splice(this.globalParticles.indexOf(particles), 1);
        }
      }
    }
  }
}
/* Dust Plugin End*/

const app = new PIXI.Application({
  view: document.getElementById('main'),
  width: 512,
  height: 512,
  antialias: true,
  transparent: false,
  backgroundColor: 0X000000,
});

const datGuiData = function () {
  this.speed = 0.05;
};

const datGuiTools = new datGuiData();
const gui = new dat.GUI();
const d = new Dust(PIXI);
let stage = app.stage;
const renderer = app.renderer;
let startContainer = new PIXI.Container();


gui.add(datGuiTools, 'speed', 0.00, 1);

let starParticleContainer = new PIXI.ParticleContainer(
  1500,
  { alpha: true, scale: true, rotation: true, uvs: true }
);

startContainer.addChild(starParticleContainer);
app.stage.addChild(startContainer);

AnimatedHex();

function AnimatedHex() {
  const alienImages = ["https://i.imgur.com/xAVBpW0.png", "https://i.imgur.com/gs9NiFX.png"];
  let textureArray = [];

  for (let i = 0; i < alienImages.length; i++) {
    let texture = PIXI.Texture.from(alienImages[i]);
    textureArray.push(texture);
  };

  const animatedSprite = new PIXI.AnimatedSprite(textureArray);
  
  let particleStream = d.emitter(
    100,
    () => d.create(
      250,
      250,
      () => new PIXI.Sprite(
        PIXI.Texture.from('https://i.imgur.com/UEZBrqp.png'),
      ),
      starParticleContainer,
      20,
      0,
      false,
      0, 9.28,
      30, 90,
      1, 3
    )
  )

  app.stage.addChild(animatedSprite);

  animatedSprite.play();

  app.ticker.add((delta) => {
    animatedSprite.animationSpeed = datGuiTools.speed;
    d.update();
    // particleStream.play();
  })

  setTimeout(() => {
    particleStream.play();
  }, 5000);

  setTimeout(() => {
    particleStream.stop();
  }, 10000);
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/pixi.js/5.1.3/pixi.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js
  3. https://raw.githubusercontent.com/kittykatattack/dust/master/src/dust.js