/**
* Copyright lespleen ( http://wonderfl.net/user/lespleen )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/AjSo
*/
/**
* forked from codeonwort's forked from: transition
* forked from Nyarineko's transition
*
*@author Andrea Bovo spleen666@gmail.com
*
*@see http://lab.polygonal.de/2007/07/18/fast-and-accurate-sinecosine-approximation/
*@see http://jacksondunstan.com/articles/1217#more-1217
*/
package
{
import flash.text.engine.SpaceJustifier;
import flash.geom.Point;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.display.Graphics;
import flash.filters.BlurFilter
import net.hires.debug.Stats;
[SWF(width = "465", height = "465", backgroundColor = "0xffffff", frameRate = "60")]
public class Main extends Sprite
{
//private const TF:Boolean = false; //transition mode
private const M_WIDTH:Number = 465;
private const M_HEIGH:Number = 465;
private const OX:Number = 465 / 2;
private const OY:Number = 465 / 2;
private const V:Number = 2;
private const OBJ_MAX:Number = 50;
private var max:uint = 50;
private var amax:uint = 0;
private var _canvas:BitmapData;
private var dst:BitmapData
private var _bmp:Bitmap;
private var _sp:Sprite;
private var _sr:Number;
private var _vr:Number;
private var first:Particle;
private var zero:Point = new Point
private var blur:BlurFilter = new BlurFilter(2, 2, 3);
private var _pixels:Vector.<uint>;
private var sqrtLUT:LUT;
public function Main()
{
_sp = new Sprite();
_canvas = new BitmapData(M_WIDTH, M_HEIGH, true, 0x00000000);
_pixels = _canvas.getVector( _canvas.rect );
sqrtLUT = new LUT(2, 200000, Math.sqrt);
_bmp = new Bitmap(_canvas);
_bmp.smoothing = true;
_bmp.blendMode = "invert";
_bmp.x = -M_WIDTH / 2;
_bmp.y = -M_HEIGH / 2;
_sp.addChild(_bmp);
_sp.x = M_WIDTH / 2;
_sp.y = M_HEIGH / 2;
addChild(_sp);
addChild( new Stats())
init();
stage.addEventListener(MouseEvent.CLICK,click,false,0,true);
stage.addEventListener(Event.ENTER_FRAME,loop,false,0,true);
}
private function init():void
{
var p:Particle;
_sr = 1;
_vr = 0.00005;
first = new Particle();
p = first;
for(var i:uint = 0;i < max;i++)
{
p.ang = i * 360 / max;
p.vang = 1;
p.r = 10;
p.vr = 0;
p.x = OX;
p.y = OY;
if(i != max - 1)
{
p.next = new Particle();
p = p.next;
}
}
}
private function loop(e:Event):void
{
update();
}
private function click(e:MouseEvent):void
{
_canvas.lock();
_canvas.fillRect( _canvas.rect, 0xFFFFFF);
_pixels = _canvas.getVector( _canvas.rect );
_canvas.unlock();
init();
}
private function update():void
{
var sh:Shape = new Shape();
var g:Graphics = sh.graphics;
var ang:Number;
var ax:Number;
var ay:Number;
var rr:Number;
var anga:Number;
var px:Number;
var py:Number;
var r:Number;
var ran:Number;
var p:Particle = first;
var cnt:uint = 0;
_canvas.lock();
while( p )
{
g.lineStyle(p.thickness, p.color, p.alpha);
cnt++;
if(p.r > 400)
{
p = p.next;
continue;
}
ran = Math.random();
if(ran < 0.1){
p.vang = 0;
p.vr = V;
}
else
if(ran < 0.2){
p.vang = -V;
p.vr = 0;
}
else
if(ran < 0.3)
{
p.vang = V;
p.vr = 0;
}
else
if(ran < 0.304 && amax < OBJ_MAX)
{
var newP:Particle = new Particle();
newP.ang = p.ang;
if(p.vang == 0)
newP.vang = 0;
else
newP.vang = (Math.random() < 0.5)?-1:1;
newP.r = p.r;
if(p.vang == 0)
newP.vr = 1;
else
newP.vr = 0;
newP.x = p.x;
newP.y = p.y;
newP.next = p.next;
p.next = newP;
}
r = p.ang + p.vang;
p.r = p.r + p.vr;
var sin:Number;
var cos:Number;
ang = Math.PI/180 * r;
sin = 0.0
cos = 0.0
//always wrap input angle to -PI..PI
if (ang < -3.14159265) ang += 6.28318531;
else
if (ang > 3.14159265) ang -= 6.28318531;
//compute sine
if (ang < 0) {
sin = 1.27323954 * ang + .405284735 * ang * ang;
if (sin < 0) sin = .225 * (sin * -sin - sin) + sin;
else sin = .225 * (sin * sin - sin) + sin;
} else {
sin = 1.27323954 * ang - 0.405284735 * ang * ang;
if (sin < 0) sin = .225 * (sin * -sin - sin) + sin;
else sin = .225 * (sin * sin - sin) + sin;
}
ay = p.r * sin;
//compute cosine: sin(x + PI/2) = cos(x)
ang += 1.57079632;
if (ang > 3.14159265) ang -= 6.28318531;
if (ang < 0) {
cos = 1.27323954 * ang + 0.405284735 * ang * ang
if (cos < 0) cos = .225 * (cos * -cos - cos) + cos;
else cos = .225 * (cos * cos - cos) + cos;
} else {
cos = 1.27323954 * ang - 0.405284735 * ang * ang;
if (cos < 0) cos = .225 * (cos * -cos - cos) + cos;
else cos = .225 * (cos * cos - cos) + cos;
}
ax = p.r * cos
//
rr = sqrtLUT.val(ax * ax + ay * ay);
anga = Math.PI/180 * (r - (r - p.ang) / 2);
sin = 0.0
cos = 0.0
//always wrap input angle to -PI..PI
if (anga < -3.14159265) anga += 6.28318531;
else if (anga > 3.14159265) anga -= 6.28318531;
//compute sine
if (anga < 0) {
sin = 1.27323954 * anga + .405284735 * anga * anga;
if (sin < 0) sin = .225 * (sin * -sin - sin) + sin;
else sin = .225 * (sin * sin - sin) + sin;
} else {
sin = 1.27323954 * anga - 0.405284735 * anga * anga;
if (sin < 0) sin = .225 * (sin * -sin - sin) + sin;
else sin = .225 * (sin * sin - sin) + sin;
}
py = rr * sin
//compute cosine: sin(x + PI/2) = cos(x)
anga += 1.57079632;
if (anga > 3.14159265) anga -= 6.28318531;
if (anga < 0) {
cos = 1.27323954 * anga + 0.405284735 * anga * anga
if (cos < 0) cos = .225 * (cos * -cos - cos) + cos;
else cos = .225 * (cos * cos - cos) + cos;
} else {
cos = 1.27323954 * anga - 0.405284735 * anga * anga;
if (cos < 0) cos = .225 * (cos * -cos - cos) + cos;
else cos = .225 * (cos * cos - cos) + cos;
}
px = rr * cos
g.moveTo(p.x,p.y);
g.curveTo(px+OX, py+OY,ax+OX, ay+OY);
//g.lineTo(ax+OX, ay+OY);
//eflaVec( _pixels, M_WIDTH, p.x, p.y, px+OX, py+OY, 0x0);
p.x = ax+OX;
p.y = ay+OY;
p.ang = r;
p = p.next;
}
/** if(_sr < 400 && TF){
g.beginFill(0xFFFFFF);
if(_vr < 8) _vr += _vr/30;
_sr = _sr + _vr;
g.drawCircle(OX,OY,_sr);
g.endFill();
}*/
//_canvas.setVector( _canvas.rect, _pixels);
_canvas.draw(sh);
//_canvas.applyFilter(_canvas, _canvas.rect, zero, blur)
var tmp:BitmapData = _canvas.clone()
//_canvas.draw(tmp, null, null, "add")
//
//dst.draw(temp, null, null, "screen")
_canvas.unlock();
tmp.dispose()
g = null;
sh = null;
amax = cnt;
}
/**
* "Extremely Fast Line Algorithm"
* @author Po-Han Lin (original version: http://www.edepot.com/algorithm.html)
* @author Simo Santavirta (AS3 port: http://www.simppa.fi/blog/?p=521)
* @author Andrea Bovo - added setVector lookup
*/
private function eflaVec( pixels:Vector.<uint>, width:int, x:int, y:int, x2:int, y2:int, color:uint): void
{
var shortLen:int = y2-y;
var longLen:int = x2-x;
var yLonger:Boolean
var index:uint =0
if ( (shortLen ^ (shortLen >> 31)) - (shortLen >> 31) > (longLen ^ (longLen >> 31)) - (longLen >> 31))
{
shortLen ^= longLen;
longLen ^= shortLen;
shortLen ^= longLen;
yLonger = true;
}
else
{
yLonger = false;
}
var inc:int = longLen < 0 ? -1 : 1;
var i:int = 0
var multDiff:Number = longLen == 0 ? shortLen : shortLen / longLen;
if (yLonger)
{
for (i = 0; i != longLen; i += inc)
{
//bmd.setPixel(x + i*multDiff, y+i, color);
pixels[ xyToOff(x + i*multDiff, y+i, width) ] = color
}
}
else
{
for (i = 0; i != longLen; i += inc)
{
//bmd.setPixel(x+i, y+i*multDiff, color);
pixels[ xyToOff( x+i, y+i*multDiff, width)] = color
}
}
}
private function xyToOff( x:int , y:int , width:int ): int {
return (y * width) + x;
}
}
}
class Particle
{
public var ang:Number;
public var vang:Number;
public var r:Number;
public var vr:Number;
public var x:Number;
public var y:Number;
public var next:Particle;
public var alpha:Number = 0.3 + Math.random()*0.2
public var thickness:uint = Math.random() * 4
private var from:uint = Math.random() * 0xffffff
private var to:uint = Math.random() * 0xffffff
private var prog:Number = 0
public function get color():uint {
prog += 0.05
if(prog > 1){
prog = 0
from = to
to = Math.random() * 0xffffff
}
return interpolate(0x0, 0xff0000, prog)
}
}
/**
* A generic lookup table useful for caching the results of a function
* @author Jackson Dunstan
*/
class LUT
{
/** 2 * PI, the number of radians in a circle*/
public static const TWO_PI:Number = 2.0 * Math.PI;
/** The static TWO_PI cached as a non-static field*/
private const TWO_PI:Number = LUT.TWO_PI;
/** Table of function values*/
public var table:Vector.<Number>;
/** 10^decimals of precision*/
public var pow:Number;
/**
* Make the look up table
* @param max Maximum value to cache
* @param numDigits Number of digits places of precision
* @param func Function to call to generate stored values.
* Must be valid on [0,max).
* @throws Error If func is null or invalid on [0,max)
*/
public function LUT(numDigits:uint, max:Number, func:Function)
{
var pow:Number = this.pow = Math.pow(10, numDigits);
var round:Number = 1.0 / pow;
var len:uint = 1 + max*pow;
var table:Vector.<Number> = this.table = new Vector.<Number>(len);
var val:Number = 0;
for (var i:uint = 0; i < len; ++i)
{
table[i] = func(val);
val += round;
}
}
/**
* Look up the value of the given input
* @param val Input value to look up the value of
* @return The value of the given input
*/
public function val(val:Number): Number
{
return this.table[ int(val*this.pow) ];
}
/**
* Look up the value of the given number of radians
* @param radians Radians to look up the value of
* @return The value of the given number of radians
*/
public function valTrig(radians:Number): Number
{
return radians >= 0
? this.table[int((radians%this.TWO_PI)*this.pow)]
: this.table[int((TWO_PI+radians%this.TWO_PI)*this.pow)];
}
/**
* Look up the value of the given number of radians
* @param radians Radians to look up the value of. Must be positive.
* @return The sine of the given number of radians
* @throws RangeError If radians is not positive
*/
public function valTrigPositive(radians:Number): Number
{
return this.table[int((radians%this.TWO_PI)*this.pow)];
}
/**
* Look up the value of the given number of radians
* @param radians Radians to look up the value of. Must be on (-2pi,2pi).
* @return The value of the given number of radians
* @throws RangeError If radians is not on (-2pi,2pi)
*/
public function valTrigNormalized(radians:Number): Number
{
return radians >= 0
? this.table[int(radians*this.pow)]
: this.table[int((this.TWO_PI+radians)*this.pow)];
}
/**
* Look up the value of the given number of radians
* @param radians Radians to look up the value of. Must be on [0,2pi).
* @return The value of the given number of radians
* @throws RangeError If radians is not on [0,2pi)
*/
public function valTrigNormalizedPositive(radians:Number): Number
{
return this.table[int(radians*this.pow)];
}
}
/** interpolate color **/
internal function interpolate(from:uint, to:uint, t:Number):uint
{
var r1:uint = (from >> 16) & 0xFF, g1:uint = (from >> 8) & 0xFF, b1:uint = from & 0xFF
var r2:uint = (to >> 16) & 0xFF, g2:uint = (to >> 8) & 0xFF, b2:uint = to & 0xFF
var r:uint = r1+(r2-r1)*t, g:uint = g1+(g2-g1)*t, b:int = b1+(b2-b1)*t
return (r<<16) | (g<<8) | b
}