forked from: 重力マウス(重力子パーティクル追加してみた)
Status() 追加
fillRect から setPixel へ
三角関数除外(sin, cos, atn2), 平方根除外(sqrt) ・・・ X, Y の差分情報が有るので必要な処理は関数なで対応可能
BitmapData をロックする。
for ループを for each ループに変更 ・・・ パフォーマンスにはあまり影響は無さそう
パーティクルを2万個に変更
計算域を画面境界+100ピクセルに変更してパーティクルが画面の端から端に移動する空間を広げた。(画面の端からはみ出たパーティクルの回帰を遅らせたてみた)
重力子パーティクルを追加・・・相互に影響しあう。
画面をクリックするとマウスの重力を on / off 切り替え(起動時は off )
/**
* Copyright munku.jp ( http://wonderfl.net/user/munku.jp )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/sGWU
*/
// forked from undo's 重力マウス
// Status() 追加
// fillRect から setPixel へ
// 三角関数除外(sin, cos, atn2), 平方根除外(sqrt) ・・・ X, Y の差分情報が有るので必要な処理は関数なで対応可能
// BitmapData をロックする。
// for ループを for each ループに変更 ・・・ パフォーマンスにはあまり影響は無さそう
// パーティクルを2万個に変更
// 計算域を画面境界+100ピクセルに変更してパーティクルが画面の端から端に移動する空間を広げた。(画面の端からはみ出たパーティクルの回帰を遅らせたてみた)
// 重力子パーティクルを追加・・・相互に影響しあう。
// 画面をリックするとマウスの重力を on / off 切り替え(起動時は off )
// (任意の場所でマウスクリックイベントが拾えなかったがその後 stage プロパティからイベント設定することで可能になる事を知った)
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.geom.ColorTransform;
import flash.geom.Point;
import flash.geom.Rectangle;
import net.hires.debug.Stats;
import flash.events.MouseEvent;
[SWF(frameRate='60', width='465', height='465', backgroundColor='0x0')]
public class ParticleTest1 extends Sprite
{
private var _bmp:Bitmap;
private var _bmd:BitmapData;
private var _bmdRect:Rectangle;
private var _colorTransform:ColorTransform = new ColorTransform(0.5, 0.9, 0.5, 1);
private var _redV:int = 1;
private var _greenV:int = 1;
private var _blueV:int = 1;
private var _nodeArray:Array = [];
private var _maxNum:int = 20000;
private var _gravitonsArray:Array = [];
private const _maxGNum:int = 3;
private const _minBoundary:int = -100;
private const _maxBoundary:int = 465 + 100;
private const _gravity:Number = 10;
private const _gravityMouse:Number = 30;
private const _dampingRate:Number = 0.98;
private var _grvMouse:Number = 0;
public function ParticleTest1()
{
this.stage.align = StageAlign.TOP_LEFT;
this.stage.scaleMode = StageScaleMode.NO_SCALE;
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(evt:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
_bmd = new BitmapData(465, 465, false, 0x000000);
_bmp = new Bitmap(_bmd);
addChild(_bmp);
this._bmdRect = new Rectangle(0, 0, 465, 465);
var i:int;
var n:Node;
for ( i = 0; i < this._maxNum ; i++ )
{
n = new Node();
n.pX = Math.random() * 465;
n.pY = Math.random() * 465;
this._nodeArray.push(n);
}
for ( i = 0 ; i < this._maxGNum ; i++ )
{
n = new Node();
n.pX = Math.random() * 465;
n.pY = Math.random() * 465;
this._gravitonsArray.push(n);
}
addChild(new Stats());
addEventListener(Event.ENTER_FRAME, onEnter);
stage.addEventListener(MouseEvent.CLICK, onClick);
}
private function onEnter(evt:Event):void
{
this._bmd.lock();
MoveGravitons();
MoveParticles();
if( Math.random() < 0.1 )
ModifyColor();
this._bmd.colorTransform(this._bmdRect, this._colorTransform);
this._bmd.unlock();
}
private function onClick(evt:MouseEvent):void
{
this._grvMouse = this._grvMouse ? 0 : _gravityMouse;
}
private function MoveGravitons():void
{
for (var i:int = 0 ; i < this._maxGNum ; i++ )
{
var gv1:Node = this._gravitonsArray[i] as Node;
// 重力マウスの影響を計算
var diffX:Number = mouseX - gv1.pX;
var diffY:Number = mouseY - gv1.pY;
var gravD:Number = this._grvMouse / ( diffX * diffX + diffY * diffY + 0.001 ); // 0割回避のために 0.001 を加算(パフォーマンス低下を避けるため条件回避はしない)
gv1.vX += diffX * gravD;
gv1.vY += diffY * gravD;
for (var j:int = i + 1 ; j < this._maxGNum ; j++ )
{
var gv2:Node = this._gravitonsArray[j] as Node;
diffX = gv2.pX - gv1.pX;
diffY = gv2.pY - gv1.pY;
gravD = _gravity / ( diffX * diffX + diffY * diffY + 0.001 ); // 0割回避のために 0.001 を加算(パフォーマンス低下を避けるため条件回避はしない)
var vx:Number = diffX * gravD;
var vy:Number = diffY * gravD;
gv1.vX += vx;
gv1.vY += vy;
gv2.vX -= vx;
gv2.vY -= vy;
}
// 重力子間の相互作用を計算後に移動
gv1.pX += gv1.vX;
gv1.pY += gv1.vY;
gv1.vX *= _dampingRate;
gv1.vY *= _dampingRate;
if ( gv1.pX > _maxBoundary )
gv1.pX = _minBoundary;
else if ( gv1.pX < _minBoundary)
gv1.pX = _maxBoundary;
if ( gv1.pY > _maxBoundary)
gv1.pY = _minBoundary;
else if ( gv1.pY < _minBoundary)
gv1.pY = _maxBoundary;
this._bmd.fillRect( new Rectangle( gv1.pX - 2, gv1.pY - 2, 5, 5 ), 0xffffff ); // 重力子パーティクルを少し大きめに描画
}
}
private function MoveParticles():void
{
for each( var n:Node in this._nodeArray )
{
// 重力マウスの影響を計算
var diffX:Number = mouseX - n.pX;
var diffY:Number = mouseY - n.pY;
var gravD:Number = this._grvMouse / ( diffX * diffX + diffY * diffY + 0.001 ); // 0割回避のために 0.001 を加算(パフォーマンス低下を避けるため条件回避はしない)
n.vX += diffX * gravD;
n.vY += diffY * gravD;
// 重力子の影響を計算
for each( var gv:Node in this._gravitonsArray )
{
diffX = gv.pX - n.pX;
diffY = gv.pY - n.pY;
gravD = _gravity / ( diffX * diffX + diffY * diffY + 0.001 ); // 0割回避のために 0.001 を加算(パフォーマンス低下を避けるため条件回避はしない)
n.vX += diffX * gravD;
n.vY += diffY * gravD;
}
n.pX += n.vX;
n.pY += n.vY;
n.vX *= _dampingRate;
n.vY *= _dampingRate;
if ( n.pX > _maxBoundary )
n.pX = _minBoundary;
else if (n.pX < _minBoundary )
n.pX = _maxBoundary;
if ( n.pY > _maxBoundary )
n.pY = _minBoundary;
else if ( n.pY < _minBoundary )
n.pY = _maxBoundary;
this._bmd.setPixel(n.pX, n.pY, 0xffff40 );
}
}
private function ModifyColor():void
{
if( Math.random() < 0.03 )
{
this._redV = Math.random() * 3 - 1;
this._greenV = Math.random() * 3 - 1;
this._blueV = Math.random() * 3 - 1;
}
this._colorTransform.redMultiplier += this._redV * 0.01;
if( this._colorTransform.redMultiplier < 0 || this._colorTransform.redMultiplier > 1.0 )
{
this._colorTransform.redMultiplier -= this._redV * 0.01;
this._redV *= -1;
}
this._colorTransform.greenMultiplier += this._greenV * 0.01;
if( this._colorTransform.greenMultiplier < 0 || this._colorTransform.greenMultiplier > 1.0 )
{
this._colorTransform.greenMultiplier -= this._greenV * 0.01;
this._greenV *= -1;
}
this._colorTransform.blueMultiplier += this._blueV * 0.01;
if( this._colorTransform.blueMultiplier < 0 || this._colorTransform.blueMultiplier > 1.0 )
{
this._colorTransform.blueMultiplier -= this._blueV * 0.01;
this._blueV *= -1;
}
}
}
}
class Node
{
public var vX:Number;
public var vY:Number;
public var pX:Number;
public var pY:Number;
public function Node()
{
this.vX = this.vY = 0;
}
}