forked from: tornado
左上の数字はfpsと, パーティクル処理時間の最近60フレームの合計(ms)です.
(60fpsを維持しているなら, 1秒の内この合計値の分だけ, パーティクル処理に時間が割かれています)
/**
* Copyright matacat ( http://wonderfl.net/user/matacat )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/rTdd
*/
// forked from okoi's tornado
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.ColorTransform;
import flash.geom.Rectangle;
[SWF(frameRate=60)]
public class Main extends Sprite
{
private const W:int = stage.stageWidth;
private const H:int = stage.stageHeight;
private const S:Number = 4 / H;
private var head:Particle;
private var count:int;
private var cvs:BitmapData;
private var rect:Rectangle;
private var ct:ColorTransform;
private var debug:Debug;
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
Particle.initArea = new Rectangle(W / 2, H / 2, W / 4, H / 4);
Particle.initHeight = H;
head = new Particle();
count = 0;
cvs = new BitmapData(W, H, false);
rect = new Rectangle();
ct = new ColorTransform(1.1, 1.1, 1.1);
addChild(new Bitmap(cvs));
debug = new Debug();
stage.addChild(debug);
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
private function enterFrameHandler(e:Event):void
{
debug.startSample();
cvs.lock();
cvs.colorTransform(cvs.rect, ct);
var p:Particle = head,
tx:Number = mouseX,
tz:Number = H / 2,
size:int;
Particle.initArea.x = tx;
while (true) {
if (p.life > 0) {
p.move(tx, tz);
size = p.z * S + 1;
if (size < 2) {
cvs.setPixel(p.x >> 0, p.y >> 0, 0x333333);
} else {
rect.x = p.x * 2 - size >> 1;
rect.y = p.y * 2 - size >> 1;
rect.width = size;
rect.height = size;
cvs.fillRect(rect, 0x333333);
}
} else {
p.init();
}
if (p.next) p = p.next;
else break;
}
if (++count < Particle.LIFE_DEF) p.next = new Particle();
cvs.unlock();
debug.endSample();
}
}
}
import flash.geom.Rectangle;
import flash.text.TextField;
import flash.utils.getTimer;
class Particle
{
public static var initArea:Rectangle;
public static var initHeight:Number;
public static const LIFE_DEF:int = 2000;
private static const ROL_DEF:Number = 6 / 360 * 2 * Math.PI;
private static const ROL_SLOW:Number = 511 / 512;
private static const DIFFUSE:Number = 257 / 256;
private static const UPDRAFT:Number = -7 / 8;
private static const V_SCALE:Number = 8;
public var life:Number;
public var rol:Number;
public var x:Number;
public var y:Number;
public var z:Number;
public var next:Particle;
public function Particle()
{
init();
}
public function init():void
{
life = LIFE_DEF;
rol = ROL_DEF;
x = (Math.random() - 0.5) * initArea.width + initArea.x;
y = initHeight;
z = (Math.random() - 0.5) * initArea.height + initArea.y;
}
public function move(tx:Number, tz:Number):void
{
var sin:Number = Math.sin(rol) * DIFFUSE,
cos:Number = Math.cos(rol) * DIFFUSE,
vx:Number = x * (cos - 1) + z * sin + tx * (1 - cos) + tz * -sin,
vz:Number = x * -sin + z * (cos - 1) + tx * sin + tz * (1 - cos),
vy:Number = UPDRAFT,
v:Number = Math.sqrt(vx * vx + vy * vy + vz * vz) / V_SCALE;
x += vx / v;
y += vy / v;
z += vz / v;
life--;
rol *= ROL_SLOW;
}
}
class Debug extends TextField
{
private static const NUM_SAMPLE:int = 60;
private var cCnt:int;
private var cPre:int;
private var sVec:Vector.<int>;
private var sCnt:int;
private var sPre:int;
private var output:Boolean;
public function Debug()
{
autoSize = "left";
border = true;
background = true;
sVec = new Vector.<int>(NUM_SAMPLE, true);
}
public function startSample():void
{
var cur:int = getTimer();
cCnt++;
if (cur - cPre >= 1000) {
cPre = cur;
output = true;
}
sPre = cur;
}
public function endSample():void
{
var cur:int = getTimer();
sVec[sCnt] = cur - sPre;
sCnt = (sCnt + 1) % NUM_SAMPLE;
if (output) {
for (var i:int, sum:int; i < NUM_SAMPLE; i++) sum += sVec[i];
text = String(cCnt) + "\n" + String(sum);
cCnt = 0;
output = false;
}
}
}