with EFLA
Extremely Fast Line Algorithm : http://wonderfl.net/c/A69m
/**
* Copyright 0xABCDEF ( http://wonderfl.net/user/0xABCDEF )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/bOQc
*/
// forked from codeonwort's transition 3D rotatable
// forked from codeonwort's transition 3D
// forked from codeonwort's forked from: transition
// forked from Nyarineko's transition
package {
import flash.geom.Vector3D
import flash.geom.Point;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.display.Graphics;
import flash.filters.BlurFilter
[SWF(width = "465", height = "465", backgroundColor = "0xffffff", frameRate = "60")]
public class Main extends Sprite {
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 = 60;
private var max:uint = 5;
private var amax:uint = 0;
private var _canvas:BitmapData
private var _bmp:Bitmap;
private var first:Particle;
//------------------------------------------------------
//コンストラクタ
//------------------------------------------------------
public function Main() {
graphics.beginFill(0)
graphics.drawRect(0, 0, M_WIDTH, M_HEIGH)
graphics.endFill()
_canvas = new BitmapData(M_WIDTH, M_HEIGH, false, 0 );
_bmp = new Bitmap(_canvas);
addChild(_bmp)
Particle.originX = OX, Particle.originY = OY
init();
stage.addEventListener(MouseEvent.CLICK,onClick);
stage.addEventListener(Event.ENTER_FRAME,enterframeHandler);
}
//------------------------------------------------------
//初期化
//------------------------------------------------------
private function init():void {
first = new Particle
var p:Particle = first;
for(var i:uint = 0;i < max;i++){
p.phi = 360 * i / max
p.theta = Math.random() * 180 //180 * i / max
p.phiVel = 1
p.radius = 1
p.thetaVel = 0
if(i != max - 1){
p.next = new Particle
p = p.next;
}
}
}
private var zero:Point = new Point
private var blur:BlurFilter = new BlurFilter(8, 8)
private function enterframeHandler(e:Event):void {
_canvas.fillRect(_canvas.rect, 0 );
update();
}
private function onClick(e:MouseEvent):void {
_canvas.lock();
_canvas.fillRect(_canvas.rect, 0xFFFFFF);
_canvas.unlock();
init();
}
// Extremely Fast Line Algorithm : http://wonderfl.net/c/A69m
private function efla(bmd:BitmapData, x:int, y:int, x2:int, y2:int, color:uint):void {
var shortLen:int = y2 - y;
var longLen:int = x2 - x;
if (!longLen) if (!shortLen) return;
var i:int, id:int, inc:int;
var multDiff:Number;
bmd.lock();
// TODO: check for this above, swap x/y/len and optimize loops to ++ and -- (operators twice as fast, still only 2 loops)
if ((shortLen ^ (shortLen >> 31)) - (shortLen >> 31) > (longLen ^ (longLen >> 31)) - (longLen >> 31)) {
if (shortLen < 0) {
inc = -1;
id = -shortLen % 4;
} else {
inc = 1;
id = shortLen % 4;
}
multDiff = !shortLen ? longLen : longLen / shortLen;
if (id) {
bmd.setPixel32(x, y, color);
i += inc;
if (--id) {
bmd.setPixel32(x + i * multDiff, y + i, color);
i += inc;
if (--id) {
bmd.setPixel32(x + i * multDiff, y + i, color);
i += inc;
}
}
}
while (i != shortLen) {
bmd.setPixel32(x + i * multDiff, y + i, color);
i += inc;
bmd.setPixel32(x + i * multDiff, y + i, color);
i += inc;
bmd.setPixel32(x + i * multDiff, y + i, color);
i += inc;
bmd.setPixel32(x + i * multDiff, y + i, color);
i += inc;
}
} else {
if (longLen < 0) {
inc = -1;
id = -longLen % 4;
} else {
inc = 1;
id = longLen % 4;
}
multDiff = !longLen ? shortLen : shortLen / longLen;
if (id) {
bmd.setPixel32(x, y, color);
i += inc;
if (--id) {
bmd.setPixel32(x + i, y + i * multDiff, color);
i += inc;
if (--id) {
bmd.setPixel32(x + i, y + i * multDiff, color);
i += inc;
}
}
}
while (i != longLen) {
bmd.setPixel32(x + i, y + i * multDiff, color);
i += inc;
bmd.setPixel32(x + i, y + i * multDiff, color);
i += inc;
bmd.setPixel32(x + i, y + i * multDiff, color);
i += inc;
bmd.setPixel32(x + i, y + i * multDiff, color);
i += inc;
}
}
bmd.unlock();
}
/////////////////////////////////////////
private var ran:Number
private var p:Particle
private var cnt:uint
private var zRate:Number, pos:Vector3D, track:Vector.<Vector3D>
private var i:int, len:int
private var prevX:int, prevY:int;
private var b:uint;
private function update():void {
p = first
cnt = 0
// rotate
Particle.theta0 += (mouseX-OX)/OX*2
Particle.phi0 += (mouseY-OY)/OY*2
//_canvas.lock();
while(p){
cnt++;
if(p.radius > 400){
p = p.next;
continue;
}
ran = Math.random();
if(ran < 0.1){
p.phiVel = p.thetaVel = 0;
p.radVel = V;
}else if(ran < 0.2){
p.phiVel = -V;
p.radVel = p.thetaVel = 0;
}else if(ran < 0.3){
p.phiVel = V;
p.radVel = p.thetaVel = 0;
}else if(ran < 0.4){
p.thetaVel = V
p.phiVel = p.radVel = 0
}else if(ran < 0.5){
p.thetaVel = -V
p.phiVel = p.radVel = 0
}else if(ran < 0.504 && amax < OBJ_MAX){
var newP:Particle = new Particle();
newP.phi = p.phi
newP.theta = p.theta
newP.radius = p.radius
if(p.phiVel == 0){
newP.phiVel = 0
newP.radVel = 1
}else{
newP.phiVel = Math.random() < 0.5 ? -1 : 1
newP.radVel = 0
}
newP.next = p.next;
p.next = newP;
}
p.radius += p.radVel
p.phi += p.phiVel
p.theta += p.thetaVel
p.saveCurrentCoord()
track = p.getTrack()
//g.moveTo(track[0].x, track[0].y)
prevX = track[ 0 ].x;
prevY = track[ 0 ].y;
len = track.length
for(i=1 ; i<len ; i++){
pos = track[i]
zRate = (pos.z + p.radius) / (p.radius + p.radius)
//g.lineStyle(1+zRate*0.5, 0xffffff, zRate)
//g.lineTo(pos.x, pos.y)
b = zRate*0xFF;
efla( _canvas, prevX, prevY, pos.x, pos.y, b<<16|b<<8|b );
prevX = pos.x;
prevY = pos.y;
}
p = p.next;
}
//_canvas.draw(sh);
//_canvas.unlock();
amax = cnt;
}
}
}
import flash.geom.Vector3D
internal class Particle {
public static var originX:Number, originY:Number
private static var t0:Number = 0 // theta0
private static var p0:Number = 0 // phi0
public static function get theta0():Number { return t0 * Kinv }
public static function set theta0(v:Number):void { t0 = v * K }
public static function get phi0():Number { return p0 * Kinv }
public static function set phi0(v:Number):void { p0 = v * K }
private static const K:Number = Math.PI / 180
private static const Kinv:Number = 180 / Math.PI
private static const GO_FORWARD:uint = 0
private static const ROTATE:uint = 1
private var _theta:Number = 0
private var _phi:Number = 0
public var radius:Number = 0
public var thetaVel:Number = 0, phiVel:Number = 0, radVel:Number = 0
public var track:Vector.<Coord> = new <Coord>[]
public var next:Particle
private var state:uint = GO_FORWARD
public function saveCurrentCoord():void {
var newState:uint = radVel ? GO_FORWARD : ROTATE
var c:Coord = new Coord
c.r = radius
c.phi = _phi
c.theta = _theta
if(state == GO_FORWARD && newState == state){
track.pop()
}
track.push(c)
state = newState
}
public function getTrack():Vector.<Vector3D> {
var t:Vector.<Vector3D> = new <Vector3D>[]
for each(var c:Coord in track){
t.push(getPosition(c.r, c.phi+p0, c.theta+t0))
}
return t
}
private function getPosition(r:Number, phi:Number, theta:Number):Vector3D {
var v:Vector3D = new Vector3D(
r * Math.cos(phi) * Math.cos(theta),
r * Math.sin(phi),
r * Math.cos(phi) * Math.sin(theta))
v.x += originX, v.y += originY
return v
}
public function get phi():Number { return _phi * Kinv }
public function set phi(v:Number):void { _phi = v * K }
public function get theta():Number { return _theta * Kinv }
public function set theta(v:Number):void { _theta = v * K }
}
internal class Coord {
public var r:Number, phi:Number, theta:Number
}