PlasmaBall
/**
* Copyright okoi ( http://wonderfl.net/user/okoi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/mvAX
*/
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.geom.ColorTransform;
import flash.geom.Point;
import flash.geom.Matrix;
import flash.filters.BlurFilter;
import flash.filters.GlowFilter;
[SWF(width = "465", height = "465", frameRate = "60")]
/**
* ...
* @author
*/
public class Main extends Sprite
{
public static const WIDTH:int = 465;
public static const HEIGHT:int = 465;
private var _canvas:BitmapData;
private var _back:BitmapData;
private var _ray:ElectroRay;
private var _rayList:/*ElectroRay*/Array;
private var _sphere:Sphere;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
graphics.beginFill(0);
graphics.drawRect(0, 0, WIDTH, HEIGHT);
graphics.endFill();
_back = new BitmapData(WIDTH, HEIGHT, true, 0);
addChild( new Bitmap(_back) );
_canvas = new BitmapData(WIDTH,HEIGHT,true,0);
addChild( new Bitmap(_canvas) );
_sphere = new Sphere( 200 );
_sphere.x = WIDTH / 2;
_sphere.y = WIDTH / 2;
addChild( _sphere );
_ray = new ElectroRay();
_ray.Reset( WIDTH / 2, HEIGHT / 2, 0 );
_rayList = [];
for ( var i:int = 0; i < 30; i++ )
{
_rayList.push( new ElectroRay() );
_rayList[i].Reset( WIDTH / 2, HEIGHT / 2, Math.random() * 360 );
}
addEventListener( Event.ENTER_FRAME, EnterFrameHandler );
}
private function EnterFrameHandler( e:Event ) : void
{
var colorTrans:ColorTransform = new ColorTransform(1, 0.5, 0.5, 0.5);
_canvas.lock();
_canvas.fillRect( _canvas.rect, 0 );
for ( var i:int = 0; i < _rayList.length; i++ )
{
_rayList[i].Update();
_canvas.draw( _rayList[i].shape, null, colorTrans, "add" );
}
_canvas.applyFilter( _canvas, _canvas.rect, new Point(), new GlowFilter(0xAA3333, 1, 3, 3, 2, 3, false, false));
_canvas.unlock();
colorTrans = new ColorTransform(0, 0, 0, 0, 0xFF, 0x55, 0xFF, 0xFF);
_back.lock();
_back.fillRect( _back.rect, 0 );
_back.draw( _canvas, null, colorTrans );
_back.applyFilter( _back, _back.rect, new Point, new BlurFilter(10,10) );
_back.unlock();
}
}
}
import flash.display.Graphics;
import flash.geom.Point;
import flash.display.Shape;
import flash.display.Sprite;
import flash.geom.Matrix;
class ElectroRay {
private static const MAX_DEPTH:int = 5;
private var _angle:Number;
private var _top:Path = null;
private var _x:Number;
private var _y:Number;
private var _life:int;
public var shape:Shape = new Shape();
public function Reset( x:Number, y:Number, angle:Number = 0 ) : void
{
_angle = angle;
_x = x;
_y = y;
_life = int(Math.random() * 200) + 60;
_top = new Path();
_top.x = x;
_top.y = y;
SetPathChild( _top, angle, 90 );
}
/**
* 再帰処理を使ってパスを設定していく
* @param parent
* @param startAngle
* @param offsetAngle
* @param depth
*/
private function SetPathChild( parent:Path, startAngle:Number, offsetAngle:Number, depth:int = 1 ) : void
{
if ( depth == MAX_DEPTH ) return;
if ( parent == null ) parent = new Path();
var childNum:int = 1;
if ( depth >= 2 )
{
if ( int(Math.random() * 3) == 0 ) childNum = int(Math.random() * 3) + 1;
}
for ( var i:int = 0; i < childNum; i++ )
{
var child:Path;
child = new Path();
child.parent = parent;
child.offsetAngle = startAngle + (Math.random() * offsetAngle) - offsetAngle/2;
child.offsetX = Math.cos( child.offsetAngle * Math.PI / 180 ) * 50;// * (MAX_DEPTH - depth) / MAX_DEPTH;
child.offsetY = Math.sin( child.offsetAngle * Math.PI / 180 ) * 50;// * (MAX_DEPTH - depth) / MAX_DEPTH;
child.x = parent.x + child.offsetX;
child.y = parent.y + child.offsetY;
child.rotateSpeed = (Math.random() * 2 - 1) * (MAX_DEPTH - depth)*0.6;
child.depth = depth;
parent.child.push( child );
SetPathChild( child, startAngle, offsetAngle, depth + 1 );
}
}
public function Draw() : void
{
if ( _top == null ) return;
shape.graphics.clear();
RecursiveDraw( shape.graphics, _top );
}
/**
* 再帰処理を利用して描画
* @param g
* @param path
*/
private function RecursiveDraw( g:Graphics, path:Path ) : void
{
var p1:Point, p2:Point, p3:Point, p4:Point;
var i:int, j:int;
if ( path.child.length == 0 ) return;
if ( path.parent != null ) p1 = new Point( path.parent.x, path.parent.y );
else p1 = new Point( path.x, path.y );
p2 = new Point( path.x, path.y );
for ( i = 0; i < path.child.length; i++ )
{
p3 = new Point( path.child[i].x, path.child[i].y );
if ( path.child[i].child.length != 0 )
{
p4 = new Point();
for ( j = 0; j < path.child[i].child.length; j++ )
{
p4.x += path.child[i].child[j].x;
p4.y += path.child[i].child[j].y;
}
p4.x /= path.child[i].child.length;
p4.y /= path.child[i].child.length;
}else
{
p4 = new Point( path.child[i].x, path.child[i].y );
}
var point:Point;
g.lineStyle( (MAX_DEPTH - path.depth), 0xFFFFFF );
for ( j = 0; j < 40; j++ )
{
point = Util.CatmullRom(p1, p2, p3, p4, (j+1) / 40);
if ( j == 0 ) g.moveTo( point.x, point.y );
else g.lineTo( point.x, point.y );
}
RecursiveDraw( g, path.child[i] );
}
}
public function Update() : void
{
if ( _top == null ) return;
RecursivePathMove( _top );
if ( --_life == 0 ) Reset( _x, _y, _angle );
Draw();
}
/**
* 再帰処理を使ってパスを移動させる
* @param path
*/
private function RecursivePathMove( path:Path ) : void
{
if ( path.parent != null )
{
var rotateSpeed:Number = path.rotateSpeed;
//if ( int(Math.random() * (100-path.depth*2)) == 0 ) rotateSpeed = -rotateSpeed * 20;
var sin:Number = Math.sin( rotateSpeed * Math.PI / 180 );
var cos:Number = Math.cos( rotateSpeed * Math.PI / 180 );
path.x = path.parent.x + path.offsetX;
path.y = path.parent.y + path.offsetY;
var vx:Number = path.x - path.parent.x;
var vy:Number = path.y - path.parent.y;
path.x = vx * cos - vy * sin + path.parent.x;
path.y = vx * sin + vy * cos + path.parent.y;
path.offsetX = path.x - path.parent.x;
path.offsetY = path.y - path.parent.y;
}
if ( path.child.length == 0 ) return;
for ( var i:int = 0; i < path.child.length; i++ )
{
RecursivePathMove( path.child[i] );
}
}
}
class Path {
public var x:Number;
public var y:Number;
public var offsetAngle:Number;
public var offsetX:Number;
public var offsetY:Number;
public var depth:int;
public var rotateSpeed:Number;
public var parent:Path;
public var child:/*Path*/Array = [];
public function Path() {
parent = null;
x = 0;
y = 0;
offsetX = 0;
offsetY = 0;
offsetAngle = 0;
rotateSpeed = 0;
}
}
class Sphere extends Sprite {
public function Sphere(radius:Number) {
var mat:Matrix = new Matrix();
mat.createGradientBox( radius * 2, radius * 2, 0, -radius*1.5, -radius*1.5 );
graphics.beginGradientFill(
"radial",
[0xFFFFFF, 0xAAAAAA],
[0.9, 0.2],
[0, 255],
mat
);
graphics.drawCircle(0, 0, radius);
graphics.endFill();
}
}
class Util {
public static function CatmullRom( p0:Point, p1:Point, p2:Point, p3:Point, t:Number ) : Point
{
var point:Point = new Point();
var v0:Number = (p2.x - p0.x) * 0.5;
var v1:Number = (p3.x - p1.x) * 0.5;
point.x = (2*p1.x - 2*p2.x + v0 + v1)*t*t*t + (-3*p1.x + 3*p2.x - 2*v0 - v1)*t*t + v0*t + p1.x;
v0 = (p2.y - p0.y) * 0.5;
v1 = (p3.y - p1.y) * 0.5;
point.y = (2*p1.y - 2*p2.y + v0 + v1)*t*t*t + (-3*p1.y + 3*p2.y - 2*v0 - v1)*t*t + v0*t + p1.y;
return point;
}
}