• Team somethingCoded() is:
    Bundy Kim (@bundy_kim)
    Josh Nielsen (@joshontheweb)
    Travis Sisti (@travhimself)
    Michael Toymil (@mtoymil)

  • Hire us!
  • We specialize in Node.js, Backbone.js, and Design.
  • 2012-11-16

    Particle Effects: Adding Texture To Your Canvas Game

    by @joshontheweb

    This is part 4, the conclusion to a series that details our team’s journey to creating disasteroids.com for NodeKnockout 2012, a 48 hour coding competition that showcases projects built on node.js. You can find part one here, part two here, and part three here.

    We Need Eye Candy!

    Once we got the basic physics and rendering in place it was time to figure out how to make the explosions and rocket trails.  We initially had something like Scorched Earth in mind where the rockets draw a permanent trail, but we weren’t tied to the idea. After some quick hunting around we came across Javascript Particle System by @jsoverson and we were sold.  It’s more of a demo than a library meant for reuse, so there are no docs.  Luckily it was written pretty well and it wasn’t too hard to discern how to use it and pull out the functionality we needed.

    There are six objects at the core of the particle system.

    • Display - Wrapper for canvas element
    • ParticleSystem - This runs the show and tells all the other element what to do
    • Vector - A wrapper for x,y coords with some convenience methods
    • Particle - represents an individual particle
    • Field - Basically a source of gravity.  negative gravity is repulsion.
    • Emitter - Emits particles

    Initialization

    Basically how it works is you wrap a canvas element in a Display object which you then pass into ParticleSystem’s init like so:

    // wrap canvas with Display and initialize
    var display = new Display(this.canvas);
    display.init();
    
    // Initialize ParticleSystem and init with display
    var particleSystem = new ParticleSystem().init(display);
    
    // set an upper limit for total number of particles
    particleSystem.maxParticles = 10000;
    
    // start
    display.start();
    

    Missile Thruster Particle Trail

    Once this is done all you need to do is create an Emitter and push into the appropriate array and the particle system will do the rest. for example, here is a piece the render method for a missile:

        
    render: function(canvas, particleSystem) {
      var self = this;
    
      // play shoot sound
      app.playAudio('rocketShoot');
    
      // create local handle for particle system
      this.particleSystem = particleSystem;
          
      // create new emitter called thruster
      this.thruster = new Emitter();
    
      // set parameters
      this.thruster.position = new Vector(self.model.get('x'), self.model.get('y'));
      this.thruster.velocity = Vector.fromAngle(self.model.get('angle')*180/Math.PI, 5);
      this.thruster.size = 0;
      this.thruster.particleLife = 100;
      this.thruster.spread = .5;
      this.thruster.emissionRate = 0.5;
      this.thruster.jitter = 0;
      this.thruster.particleColor = [255,130,0,1];
    
      // push emitter into particle system
      particleSystem.emitters.push(this.thruster);
    }
    

    This starts shooting particles out of the back of the missile.  Since we already have all the math done to update the missiles position and angle, we can simple hook into that in the missiles reposition method.

        
    reposition: function(model) {
      var self = this;
      
      // reposition the missile
      this.object.set('left',self.model.get('x'));
      this.object.set('top', self.model.get('y'));
      this.object.set('angle', self.model.get('angle')*180/Math.PI);
          
      // reposition the thruster emitter
      var thrusterVector = Vector.fromAngle(self.model.get('angle') + Math.PI/2, self.model.get('height')/2);
      this.thruster.position = new Vector(self.model.get('x') + thrusterVector.x, self.model.get('y') + thrusterVector.y);
          
      // update the angle so it is always shooting out the tail of the missile
      // velocity takes a vector that governs the angle as well as the speed
      this.thruster.velocity = Vector.fromAngle(self.model.get('angle') + Math.PI/2, 2);
    }
    

    That gives us a missile with a particle trail!

    Explosions and Blasts

    Now we just need to handle what happens when the missile hits something.  Basically what we want to do is:

    1. remove the truster emitter
    2. create an explosion emitter
    3. create a repulsion field so the particles don’t just emit in a circle but get blasted away
    4. wait a bit and remove the explosion and repulsion field.
    Heres what it looks like in the missile’s exit method:
    exit: function() {
      var self = this;
    
      // play impact sound
      app.playAudio('rocketImpact');
          
      // remove thruster
      this.particleSystem.removeEmitter(this.thruster);
    
      // create explosion emitter and set params
      this.explosion = new Emitter();
      this.explosion.position = new Vector(this.model.get('x'), this.model.get('y'));
      this.explosion.velocity = new Vector(0, 5);
      this.explosion.size = 0;
      this.explosion.particleColor = [255,50,0,1];
      this.explosion.spread = 50;
      this.explosion.emissionRate = 10;
      this.explosion.particleLife = 7;
    
      // create repulsion field and set params
      // remember negative gravity will repel
      this.repulsion = new Field(this.explosion.position, -1000);
      this.repulsion.size = 0;
    
      // push explosion and repulsion field into particleSystem
      this.particleSystem.fields.push(this.repulsion);
      this.particleSystem.emitters.push(this.explosion);
      
      // wait 250ms and remove the explosion
      setTimeout(function() {
        self.particleSystem.removeEmitter(self.explosion);
      }, 250);
    
      // wait 1500ms and remove the repulsion field
      // the wait is longer here so the particles can all get blown away
      setTimeout(function() {
        self.particleSystem.removeField(self.repulsion);
      }, 1500);
    }
    

    That gives us a nice particle explosion that blasts away debris

    The End

    Thats the gist of how the particle physics implementation works.  Thanks for taking time to read and we hope you have fun playing the game as well.

    Note: We did have to customize the Javascript Particle System a bit to meet our needs.  Primarily to allow for different sized particles and different colors.  It also depended on require.js, which we removed as well.  Here is the custom code on github.  Thanks again to @jsoverson for making such a cool and extendable project.  

    VOTE!

    If you enjoyed disasteroids.com or this post, please consider throwing us a vote on our team’s page. It requires Facebook authentication to ensure that there isn’t rampant cheating, but the awesome NodeKnockout organizers @visnup and @gerad would never use your information in a malicious way. They’ve been crazy enough to organize this event for the 3rd year now despite the operational headaches of putting together such a massive event.