// forked from clockmaker's 3D Flow Simulation // forked from clockmaker's Interactive Liquid 10000 // forked from clockmaker's Liquid110000 By Vector // forked from munegon's forked from: forked from: forked from: forked from: Liquid10000 // forked from Saqoosha's forked from: forked from: forked from: Liquid10000 // forked from nutsu's forked from: forked from: Liquid10000 // forked from nutsu's forked from: Liquid10000 // forked from zin0086's Liquid10000 package { /** * 3D にしてみました * 10000 パーティクル */ import flash.display.*; import flash.geom.*; import flash.events.*; import flash.utils.*; import flash.geom.*; import net.hires.debug.Stats; public class Liquid3D extends Sprite { private const NUM_PARTICLE:uint = 10000; private var bmpData:BitmapData = new BitmapData( 465, 465, false, 0x000000 ); private var forceMap:BitmapData = new BitmapData( 233, 233, false, 0x000000 ); private var randomSeed:uint = Math.floor( Math.random() * 0xFFFF ); private var rect:Rectangle = new Rectangle( 0, 0, 465, 465 ); private var seed:Number = Math.floor( Math.random() * 0xFFFF ); private var offset:Array = [new Point(), new Point()]; private var colorTransform:ColorTransform = new ColorTransform( .86, .92, .92); private var timer:Timer; private var beginner:Particle; public function Liquid3D() { stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; stage.quality = StageQuality.LOW; stage.frameRate = 60; // 画面に表示用の Bitmap を作ります addChild(new Bitmap( bmpData )) as Bitmap; // フォースマップの初期化をおこないます resetFunc(); // ループ時の参照用 var particle:Particle; var next:Particle; // パーティクルを生成します for (var i:uint = 0; i <= NUM_PARTICLE; i++) { var px:Number = Math.round(Math.random() * 465); var py:Number = Math.round(Math.random() * 465); var pz:Number = Math.round(Math.random() * 465 * 2 - 465); particle = new Particle(px, py, pz); particle.next = next; next = particle; if (i == NUM_PARTICLE) { beginner = particle; } } // ループ処理 addEventListener( Event.ENTER_FRAME, loop ); // 時間差でフォースマップと色変化の具合を変更しています var timer:Timer = new Timer(500) timer.addEventListener(TimerEvent.TIMER, resetFunc); timer.start(); // デバッグ用のスタッツを表示しています addChild(new Stats); } private function loop( e:Event ):void { var p:Particle = beginner; var f:Number; bmpData.lock(); while (p = p.next) { f = forceMap.getPixel( p.x >> 1, p.y >> 1); p.ax += ( (f >> 8 & 0xff) - 128 ) * .0005; p.ay += ( (f >> 4 & 0xff) - 128 ) * .0005; p.az += ( (f >> 16 & 0xff) - 128 ) * .0005; p.vx += p.ax; p.vy += p.ay; p.vz += p.az; p.x += p.vx; p.y += p.vy; p.z += p.vz; bmpData.fillRect(p.rect, 0xFFFFFFFF); p.ax *= .95; p.ay *= .95; p.az *= .95; p.vx *= .90; p.vy *= .90; p.vz *= .90; if (p.x < 0) p.x += 465; else if (p.x > 465) p.x -= 465; if (p.y < 0) p.y += 465; else if (p.y > 465) p.y -= 465; if (p.z < -465) p.z += 930; else if (p.z > 465) p.z -= 930; } bmpData.colorTransform(rect, colorTransform); bmpData.unlock(); } private function resetFunc(e:Event = null):void{ forceMap.perlinNoise(233, 233, 3, seed, false, false, 1|2|4|0, false, offset ); offset[0].x += 1.5; offset[1].y += 1; seed = Math.floor( Math.random() * 0xFFFFFF ); } } } import flash.display.*; import flash.geom.*; class Particle { // スケールの計算はこれで良いや。 public function get rect():Rectangle { var f:Number = 200 / (200 + z); _rect.width = _rect.height = 2 * f; _rect.x = x * f; _rect.y = y * f; return _rect; } // 可能なら整数型(int)にしてあげた方が高速。 // 普段は気にする必要は無いが、ループ処理内部で多くの計算を行う場合は、 // 浮動小数点数(Number)の計算は重いため。 public var x:int = 0; public var y:int = 0; public var z:int = 0; public var vx:Number = 0; public var vy:Number = 0; public var vz:Number = 0; public var ax:Number = 0; public var ay:Number = 0; public var az:Number = 0; public var next:Particle; private var _rect:Rectangle = new Rectangle(); function Particle( x:int, y:int, z:int ) { this.x = x; this.y = y; this.z = z; } } 3D Flow Simulation, Liquid 10000