package net.eidiot.particles
{
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Rectangle;
/**
* Dispatched when the snow is stoped and all the snowflakes are cleared.
*
* @eventType net.eidiot.snow.SnowSprite.CLEAR_COMPLETE
*/
[Event(name="clearComplete", type="net.eidiot.snow.SnowSprite")]
/**
* A snow system as a Sprite.
*
* @example
* The simplest way to use it:<br />
* <code>addChild(new SnowSystem(640, 480));</code>
*
* @author eidiot ( http://eidiot.net )
*/
public class SnowSystem extends Sprite
{
/** Constant for the clearComplete event. */
public static const CLEAR_COMPLETE:String = "clearComplete";
private var m_showWidth:Number;
private var m_showHeight:Number;
private var m_skinClass:Class;
private var m_minSize : Number = 5;
private var m_maxSize : Number = 8;
private var m_minAlpha : Number = 0.5;
private var m_maxAlpha : Number = 1;
private var m_minXV:Number = 0;
private var m_maxXV:Number = 1;
private var m_minYV:Number = 1;
private var m_maxYV:Number = 5;
private var m_margin : Number = 10;
private var m_landHeight : Number = 60;
private var m_spawnRate:Number = 1;
private var m_isStop:Boolean = false;
private var m_collector : Array = new Array();
private var m_spawnValue : Number = 0;
private var m_spawnLeft:Number;
private var m_spawnWidth:Number;
private var m_spawnRight:Number;
private var m_landY:Number;
/**
* Create a snow system.
*
* @param showWidth The width of the system to show.
* @param showHeight The height of the system to show.
* @param skinClass The class to create a snowflake.
* @param autoStart If start snow immediately.
*/
public function SnowSystem(showWidth:Number, showHeight:Number, skinClass:Class = null, autoStart:Boolean = true)
{
m_showWidth = showWidth;
m_showHeight = showHeight;
m_skinClass = skinClass ? skinClass : DefaultSkin;
scrollRect = new Rectangle(0, 0, showWidth, showHeight);
mouseEnabled = mouseChildren = false;
setMargin(m_margin);
setLandHeight(m_landHeight);
if (autoStart) start();
}
/**
* Is the sonw stoped.
*/
public function get isStop():Boolean
{
return m_isStop;
}
/**
* Start snow.
*
* @param clear If clear all the snowflakes before start.
*/
public function start(clear:Boolean = false):void
{
if (clear) while (numChildren > 0) removeChildAt(0);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
m_isStop = false;
}
/**
* Stop snow.
*
* @param clear If clear all the snowflakes after stop.
*/
public function stop(clear:Boolean = false):void
{
m_collector = new Array();
if (clear) while (numChildren > 0) removeChildAt(0);
if (numChildren == 0) clearOver();
m_isStop = true;
}
/**
* Set the skin class.
*
* @param skinClass The class to create a snowflake.
*/
public function setSkin(skinClass:Class):void
{
m_skinClass = skinClass;
}
/**
* Set the size range of snowflakes.
*
* @param min The minimum size of snowflakes.
* @param max The maximum size of snowflakes.
*/
public function setSize(min:Number, max:Number):void
{
m_minSize = min;
m_maxSize = max;
}
/**
* Set the alpha range of snowflakes.
*
* @param min The minimum alpha of snowflakes.
* @param max The maximum alpha of snowflakes.
*/
public function setAlpha(min:Number, max:Number):void
{
m_minAlpha = min;
m_maxAlpha = max;
}
/**
* Set the x velocity range of snowflakes.
*
* @param min The minimum x velocity of snowflakes.
* @param max The maximum x velocity of snowflakes.
*/
public function setXV(min:Number, max:Number):void
{
m_minXV = min;
m_maxXV = max;
}
/**
* Set the y velocity range of snowflakes.
*
* @param min The minimum y velocity of snowflakes.
* @param max The maximum y velocity of snowflakes.
*/
public function setYV(min:Number, max:Number):void
{
m_minYV = min;
m_maxYV = max;
}
/**
* Set the height of the land where snowflakes disappear.
*
* @param landHeight The height of the land.
*/
public function setLandHeight(landHeight:Number):void
{
m_landHeight = landHeight;
m_landY = m_showHeight - m_landHeight;
}
/**
* Set the margin where snowflakes spawned outside the show scope.
*
* @param margin Where snowflakes spawned outside the show scope.
*/
public function setMargin(margin:Number):void
{
m_margin = margin;
m_spawnLeft = -m_margin;
m_spawnWidth = m_showWidth + m_margin * 2;
m_spawnRight = m_spawnLeft + m_spawnWidth;
}
/**
* Set how many snowflakes spawned per-frame.
* Can be noninteger and be less than 1.
*
* @param spawnRate How many snowflakes spawned per-frame.
*/
public function setSpawnRate(spawnRate:Number):void
{
m_spawnRate = spawnRate;
}
private function spawnNew():void
{
var particle:SnowParticle = m_collector.length > 0 ?
m_collector.pop() :
new SnowParticle(m_skinClass);
var distance : Number = Math.random();
particle.place(m_spawnLeft + Math.random() * m_spawnWidth, 0);
particle.setAlpha(m_minAlpha + (m_maxAlpha - m_minAlpha) * distance);
particle.setSize(m_minSize + (m_maxSize - m_minSize) * distance);
var xv:Number = m_minXV + (m_maxXV - m_minXV) * distance;
if (Math.random() > 0.5) xv *= -1;
var yv:Number = m_minYV + (m_maxYV - m_minYV) * distance;
particle.setV(xv, yv);
particle.setScope(m_spawnLeft, m_spawnRight, m_landY + m_landHeight * distance);
addChild(particle);
}
private function clearOver():void
{
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
dispatchEvent(new Event(CLEAR_COMPLETE));
}
private function onEnterFrame(e:Event):void
{
if (!m_isStop)
{
m_spawnValue += m_spawnRate;
while (m_spawnValue >= 1)
{
spawnNew();
m_spawnValue--;
}
}
for (var i:int = 0; i < numChildren; i++)
{
var particle:SnowParticle = getChildAt(i) as SnowParticle;
if (particle.update())
{
removeChild(particle);
m_collector.push(particle);
i--;
if (m_isStop && numChildren == 0) clearOver();
}
}
}
}
}
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.display.Shape;
import flash.display.GradientType;
internal class DefaultSkin extends Shape
{
public function DefaultSkin()
{
with (graphics)
{
var type:String = GradientType.RADIAL;
var colors:Array = [0xE8FDFD, 0xE8FDFD, 0xFFFFFF];
var alphas:Array = [1, 1, 0];
var radios:Array = [0, 5, 15];
beginGradientFill(type, colors, alphas, radios);
drawCircle(0, 0, 5);
endFill();
}
}
}
internal class SnowParticle extends Sprite
{
private var m_xv:Number;
private var m_yv:Number;
private var m_left:Number;
private var m_right:Number;
private var m_bottom:Number;
public function SnowParticle(skinClass:Class)
{
addChild(new skinClass());
mouseEnabled = mouseChildren = false;
}
internal function place(initX:Number, initY:Number):void
{
x = initX;
y = initY;
}
internal function setAlpha(initAlpha:Number):void
{
alpha = initAlpha;
}
internal function setSize(size:Number):void
{
width = size;
scaleY = scaleX;
}
internal function setV(xv:Number, yv:Number):void
{
m_xv = xv;
m_yv = yv;
}
internal function setScope(left:Number, right:Number, bottom:Number):void
{
m_left = left;
m_right = right;
m_bottom = bottom;
}
internal function update():Boolean
{
x += m_xv;
y += m_yv;
if (x < m_left || x > m_right || y > m_bottom) return true;
return false;
}
}