Aug 28, 2013

Particles manager from gamedev.tutsplus.com

Made simple implementation of Particles manager for my game based on this article.
Here is Source code for it.

ParticlesManager.hx

package mmg.particles;
package particles;

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
/**
 * ...
 * @author gordev
 */
typedef Action = Particle -> Void;

class CircularParticleArray
{
 private var _start:Int;
 private var _list:Array;
 private var _targetClass:Class;
 private var _args:Array;
 
 public var start(get, set):Int;
  public function get_start():Int { return _start; }
 public function set_start(value:Int) { _start = value % _list.length; return 0; }
 public var capacity(get, never):Int;
 public function get_capacity():Int { return _list.length; }
 public var list(get, never):Array;
 public function get_list():Array { return _list; }
 public var count:Int = 0;

 public function new(targetClass:Class, initialCapacity:Int, args:Array)
 {
  _targetClass = targetClass;
  _list = [];
  _args = args;
  
  for (i in 0...initialCapacity)
        {
   _list.push(Type.createInstance(_targetClass, _args));
  }
 }
 
 public function get(i:Int):T
 {
  return _list[(_start + i) % _list.length];
 }
 
 public function set(i:Int, value:T):Void
 {
  _list[(_start + i) % _list.length] = value;
 }
}

class ParticlesManager extends Sprite
{
 private var update_particle:Action;
 private var particle_list:CircularParticleArray;
 
 public function new(capacity:Int, update_particle:Action, isDisplayList:Bool) 
 {
  super();
  this.update_particle = update_particle;
  particle_list = new CircularParticleArray(Particle, capacity, []);
  if(isDisplayList)
  {
   for(particle in particle_list.list)
   {
    addChild(particle.bitmap);
   }
  }
 }
 
 public function Create_particle(texture:BitmapData, 
  position:Point, 
  color:UInt, 
  duration:Float, 
  scale:Point, 
  state:Dynamic, 
  theta:Float = 0, 
  sizeReduction:Float = 1,
  fading:Float = 1):Void
 {
  var particle:Particle;
  if (particle_list.count == particle_list.capacity)
  {
   // if the list is full, overwrite the oldest particle, and rotate the circular list
   particle = particle_list.get(0);
   particle_list.start++;
  }else{
   particle = particle_list.get(particle_list.count);
   particle_list.count++;
  }
  
  // Create the particle
  particle.texture = texture;
  removeChild(particle.bitmap);
  particle.bitmap = new Bitmap(texture);
  addChild(particle.bitmap);
  
  particle.position = position;
  particle.color = color;
  particle.duration = duration;
  particle.percent_life = 1.0;
  particle.scale = scale;
  particle.bitmap.scaleX = scale.x;
  particle.bitmap.scaleY = scale.y;
  particle.orientation = theta;
  particle.state = state;
  particle.sizeReduction = sizeReduction;
  particle.fading = fading;
 }
 
 public function Update()
 {
  var removal_count:Int = 0;
  var index:Int = 0;
  for (i in 0...particle_list.count)
  {
   var particle:Particle = particle_list.get(i);
   update_particle(particle);
   particle.percent_life -= 1.0 / particle.duration;
   Swap(particle_list, index - removal_count, index);
   if (particle.percent_life < 0) removal_count++;
   index++;
  }
  particle_list.count -= removal_count;
 }
 
 public function Draw(canvas:Bitmap)
 {
  canvas.bitmapData.fillRect(canvas.bitmapData.rect, 0x00000000);
  for (i in 0...particle_list.count)
  {
   var particle:Particle = particle_list.get(i);
   var origin:Point = new Point(particle.texture.width / 2, particle.texture.height / 2);
   var mat:Matrix = new Matrix();
   mat.translate(particle.position.x - origin.x, particle.position.y - origin.y);
   canvas.bitmapData.draw(particle.texture, mat); //and so on
  }
 }
 
 public function Move()
 {
  for (i in 0...particle_list.count)
  {
   var particle:Particle = particle_list.get(i);
   particle.bitmap.x = particle.position.x - particle.bitmap.width  * 0.5;
   particle.bitmap.y = particle.position.y - particle.bitmap.height * 0.5;
  }
 }
 
 public function Swap(list:CircularParticleArray, index1:Int, index2:Int):Void
 {
  var temp:Particle = list.get(index1);
  list.set(index1, list.get(index2));
  list.set(index2, temp);
 }
 
 public function RenderBitmap(canvas:Bitmap):Void
 {
  Update();
  Draw(canvas);
 }
 
 public function RenderDisplayList():Void
 {
  Update();
  Move();
 }
}

Particle.hx

package particles;

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.geom.Point;

/**
 * ...
 * @author gordev
 */
class Particle
{
 public var texture:BitmapData;
 public var bitmap:Bitmap;
 public var position:Point;
 public var origin:Point;
 public var orientation:Float;
 public var scale:Point;
 public var color:UInt;
 public var duration:Float;
 public var percent_life:Float;
 public var state:Dynamic;
 public var fading:Float;
 public var sizeReduction:Float;
 
 public function new()
 {
  bitmap = new Bitmap();
  scale = new Point(1, 1);
  percent_life = 1.0;
 }
}



I will write about usage and step by step description later.