[Wonderfl] 3D Rotatable Constructor
/**
* Copyright gya ( http://wonderfl.net/user/gya )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/ozrb
*/
// 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.Shape;
import flash.display.Sprite;
import flash.display.Graphics;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.filters.BlurFilter
[SWF(width = "465", height = "465", backgroundColor = "0x000000", 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;
//------------------------------------------------------
// Constructor
//------------------------------------------------------
public function Main() {
stage.scaleMode = StageScaleMode.SHOW_ALL;
graphics.beginFill(0)
graphics.drawRect(0, 0, M_WIDTH, M_HEIGH)
graphics.endFill()
_canvas = new BitmapData(M_WIDTH, M_HEIGH, true, 0xffffff);
_bmp = new Bitmap(_canvas);
_bmp.smoothing = true;
addChild(_bmp)
Particle.originX = OX, Particle.originY = OY
init();
stage.addEventListener(MouseEvent.CLICK,onClick);
stage.addEventListener(Event.ENTER_FRAME,enterframeHandler);
}
//------------------------------------------------------
// Initialisation
//------------------------------------------------------
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, 0xFFFFFF);
update();
}
private function onClick(e:MouseEvent):void {
_canvas.lock();
_canvas.fillRect(_canvas.rect, 0xFFFFFF);
_canvas.unlock();
init();
}
/////////////////////////////////////////
private var sh:Shape = new Shape
private var g:Graphics = sh.graphics
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 function update():void {
p = first
cnt = 0
g.clear()
// 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)
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, false, "normal", "none")
g.lineTo(pos.x, 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
}