Onedayitwillmake - Added pooling so it wouldn't slow down, and tried some more optimizations
Wish i understood it better "toni", because its very beautiful, but im not as smart as you :)
/**
* Copyright onedayitwillmake ( http://wonderfl.net/user/onedayitwillmake )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/25tD
*/
// Onedayitwillmake - Added pooling so it wouldn't slow down, and tried some more optimizations
// Wish i understood it better "toni", because its very beautiful, but im not as smart as you :)
// forked from toni's 波を動かしてみる
// forked from toni's 波を動かしてみる
package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import com.flashdynamix.utils.SWFProfiler;
[SWF(width="465", height="465", backgroundColor="#000000", framerate="60")]
public class WaveLines extends Sprite {
private var pointNum:Number;
private var pointSpeed:Number;
private var pointSpeedDisorder:Number;
private var lineFallSpeed :Number;
private var point : Array;
private var anchor : Array;
private var rs : Number;
private var gs : Number;
private var bs : Number;
private var ra : Number;
private var ga : Number;
private var ba : Number;
private var lcount : Number;
private var lmax : Number;
private var colorArea : Number;
private var waveInc : Boolean;
private var waveRate : Number;
private var waveLineRate : Number;
private var waveMax : Number;
private var waveSizeBase:Number;
private var lineArray:Array;
private var rFlag:int;
private var line_mc:MySprite;
private var stageH:Number;
private var stageW:Number;
public var _linepool:ObjectPool
/************************************************************************
* おとす
* ステージサイズを大きくするとかなり重くなる。。。。
************************************************************************/
public function WaveLines()
{
addEventListener(Event.ADDED_TO_STAGE, onStage);
//Create the pool, only 100 lines, if we get to 101 we wait for one to become free
_linepool= new ObjectPool(false);
_linepool.allocate(200, MySprite);
}
private function onStage(e:Event):void
{
rFlag = 0;
pointNum = 20;
lineFallSpeed = 0.2;
pointSpeed = 0.1;
pointSpeedDisorder = 0.01;
waveSizeBase = 80;
colorArea = 40;
stageH = stage.stageHeight;stage.quality = "medium";
stageW = stage.stageWidth;
/************************************************************************
* ステージの設定
************************************************************************/
SWFProfiler.init(this);
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
lmax = 60;
waveRate = 1;
waveLineRate = 1;
lcount = 0;
/************************************************************************
* 曲線
************************************************************************/
point = new Array();
anchor = new Array();
var i1:Number = -1;
var xb:Number = stageW/(pointNum-1);
var len:Number = pointNum;
while (++i1 < len) {
point[i1] = {
x : i1*xb,
angle : Math.random()*Math.PI*2,
speed : Math.random()*pointSpeed,
waveSize : Math.random() * waveSizeBase + 20
};
if(i1>0){
anchor[i1-1] = new Object();
anchor[i1-1] = {
x : Math.floor((point[i1].x + point[i1 - 1].x) / 2)
};
}
}
/************************************************************************
* 色の設定
************************************************************************/
rs = Math.random()*(Math.PI/180)*10;
gs = Math.random()*(Math.PI/180)*10;
bs = Math.random()*(Math.PI/180)*10;
ra = ga = ba =0.1;
i1 = lmax + 1;
lineArray = [];
addEventListener(Event.ENTER_FRAME, main);
}
/************************************************************************
* ループ
************************************************************************/
private function main(e:Event):void {
adjPoint();
drawLine();
}
/************************************************************************
* 線の動き
************************************************************************/
private function adjPoint():void{
var len:Number = pointNum;
var i1:Number = -1;
while (++i1<len)
{
//angleを設定
point[i1].speed += Math.random()*pointSpeedDisorder*2 -pointSpeedDisorder;
if(Math.abs(point[i1].speed)>pointSpeed) {
point[i1].speed *= 0.9;
}
point[i1].angle += point[i1].speed;
//曲線を描くための点の情報を設定
point[i1].y = Math.sin(point[i1].angle) * point[i1].waveSize * waveRate;
if(i1>0){
anchor[i1 - 1].y = Math.floor((point[i1].y + point[i1 - 1].y) >> 1);
}
}
}
/************************************************************************
* 曲線の描画
************************************************************************/
private function drawLine():void
{
line_mc = _linepool.object;
if(line_mc == null) return;
line_mc.graphics.clear();
line_mc.graphics.lineStyle(2, setColor(colorArea), 1);
line_mc.graphics.moveTo(point[0].x, point[0].y);
var i1:Number = -1;
var len:Number = pointNum-1;
while(++i1 < len)
{
line_mc.graphics.curveTo(point[i1].x, point[i1].y, anchor[i1].x, anchor[i1].y);
}
line_mc.graphics.curveTo(anchor[len-1].x, anchor[len-1].y, point[i1].x, point[i1].y);
//線のプロパティを設定
line_mc.sp = 1;
line_mc.y = stageH >> 1;
line_mc.alpha = 0.3;
line_mc.visible = true;
//線に落下させる動きをつける
// line_mc.removeEventListener(Event.ENTER_FRAME, mov);
line_mc.addEventListener(Event.ENTER_FRAME, mov);
//line_mc.addEventListener(Event.ADDED_TO_STAGE, mov);
addChildAt(line_mc,0);
}
/************************************************************************
* 色の変化
************************************************************************/
private function setColor(area:Number):Number{
ra += rs;
ga += gs;
ba += bs;
return (area+Math.cos(ra)*area << 16 | area+Math.cos(ga)*area << 8 | area+Math.cos(ba)*area);
}
/************************************************************************
* 移動
************************************************************************/
private function mov(e:Event):void
{
if(MySprite(e.target).sp < 30)
{
MySprite(e.target).sp += lineFallSpeed*waveLineRate;
MySprite(e.target).y += MySprite(e.target).sp;
MySprite(e.target).alpha += 0.01;
if(MySprite(e.target).y>stageH+100)
{
MySprite(e.target).removeEventListener(Event.ENTER_FRAME, mov);
removeChild(MySprite(e.target));
_linepool.object = MySprite(e.target);
}
}else {
MySprite(e.target).removeEventListener(Event.ENTER_FRAME, mov);
removeChild(MySprite(e.target));
_linepool.object = MySprite(e.target)
}
}
}
}
import flash.display.Sprite;
class MySprite extends Sprite
{
public var sp:Number = 1;
public function MySprite()
{
}
}
internal class ObjectPool
{
private var _factory:ObjectPoolFactory;
private var _initSize:int;
private var _currSize:int;
private var _usageCount:int;
private var _grow:Boolean = true;
private var _head:ObjNode;
private var _tail:ObjNode;
private var _emptyNode:ObjNode;
private var _allocNode:ObjNode;
/**
* Creates a new object pool.
*
* @param grow If true, the pool grows the first time it becomes empty.
*/
public function ObjectPool(grow:Boolean = false)
{
_grow = grow;
}
/**
* Unlock all ressources for the garbage collector.
*/
public function deconstruct():void
{
var node:ObjNode = _head;
var t:ObjNode;
while (node)
{
t = node.next;
node.next = null;
node = t;
}
_head = _tail = _emptyNode = _allocNode = null;
}
/**
* The pool size.
*/
public function get size():int
{
return _currSize;
}
/**
* The total number of 'checked out' objects currently in use.
*/
public function get usageCount():int
{
return _usageCount;
}
/**
* The total number of unused thus wasted objects. Use the purge()
* method to compact the pool.
*
* @see #purge
*/
public function get wasteCount():int
{
return _currSize - _usageCount;
}
/**
* Get the next available object from the pool or put it back for the
* next use. If the pool is empty and resizable, an error is thrown.
*/
public function get object():MySprite
{
if (_usageCount == _currSize)
{
if (_grow)
{
_currSize += _initSize;
var n:ObjNode = _tail;
var t:ObjNode = _tail;
var node:ObjNode;
for (var i:int = 0; i < _initSize; i++)
{
node = new ObjNode();
node.data = _factory.create();
t.next = node;
t = node;
}
_tail = t;
_tail.next = _emptyNode = _head;
_allocNode = n.next;
return object;
}
else
return null;
}
else
{
var o:MySprite = _allocNode.data;
_allocNode.data = null;
_allocNode = _allocNode.next;
_usageCount++;
return o;
}
}
/**
* @private
*/
public function set object(o:MySprite):void
{
if (_usageCount > 0)
{
_usageCount--;
_emptyNode.data = o;
_emptyNode = _emptyNode.next;
}
}
/**
* Define the factory responsible for creating all pool objects.
* If you don't want to use a factory, you must provide a class to the
* allocate method instead.
*
* @see #allocate
*/
public function setFactory(factory:ObjectPoolFactory):void
{
_factory = factory;
}
/**
* Allocate the pool by creating all objects from the factory.
*
* @param size The number of objects to create.
* @param C The class to create for each object node in the pool.
* This overwrites the current factory.
*/
public function allocate(size:uint, C:Class = null):void
{
deconstruct();
if (C)
_factory = new SimpleFactory(C);
else
if (!_factory)
throw new Error("nothing to instantiate.");
_initSize = _currSize = size;
_head = _tail = new ObjNode();
_head.data = _factory.create();
var n:ObjNode;
for (var i:int = 1; i < _initSize; i++)
{
n = new ObjNode();
n.data = _factory.create();
n.next = _head;
_head = n;
}
_emptyNode = _allocNode = _head;
_tail.next = _head;
}
/**
* Helper method for applying a function to all objects in the pool.
*
* @param func The function's name.
* @param args The function's arguments.
*/
public function initialze(func:String, args:Array):void
{
var n:ObjNode = _head;
while (n)
{
n.data[func].apply(n.data, args);
if (n == _tail) break;
n = n.next;
}
}
/**
* Remove all unused objects from the pool. If the number of remaining
* used objects is smaller than the initial capacity defined by the
* allocate() method, new objects are created to refill the pool.
*/
public function purge():void
{
var i:int;
var node:ObjNode;
if (_usageCount == 0)
{
if (_currSize == _initSize)
return;
if (_currSize > _initSize)
{
i = 0;
node = _head;
while (++i < _initSize)
node = node.next;
_tail = node;
_allocNode = _emptyNode = _head;
_currSize = _initSize;
return;
}
}
else
{
var a:Array = [];
node =_head;
while (node)
{
if (!node.data) a[int(i++)] = node;
if (node == _tail) break;
node = node.next;
}
_currSize = a.length;
_usageCount = _currSize;
_head = _tail = a[0];
for (i = 1; i < _currSize; i++)
{
node = a[i];
node.next = _head;
_head = node;
}
_emptyNode = _allocNode = _head;
_tail.next = _head;
if (_usageCount < _initSize)
{
_currSize = _initSize;
var n:ObjNode = _tail;
var t:ObjNode = _tail;
var k:int = _initSize - _usageCount;
for (i = 0; i < k; i++)
{
node = new ObjNode();
node.data = _factory.create();
t.next = node;
t = node;
}
_tail = t;
_tail.next = _emptyNode = _head;
_allocNode = n.next;
}
}
}
}
internal class ObjNode
{
public var next:ObjNode;
public var data:MySprite;
}
internal class SimpleFactory implements ObjectPoolFactory
{
private var _class:Class;
public function SimpleFactory(C:Class)
{
_class = C;
}
public function create():MySprite
{
return new _class();
}
}
interface ObjectPoolFactory
{
function create():MySprite
}