In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

FollowConstraint

いつのまにかライブラリっぽくなってしまった。
もう少し高機能になったら Spark に投稿しようかな。

WOW Engine を使うような感じでパーティクルとパーティクルとの間に制約効果を適用するライブラリ

参考

WOW Engine
http://seraf.mediabox.fr/wow-engine/as3-3d-physics-engine-wow-engine/

JigLibFlash
http://www.jiglibflash.com/blog/

...
@author tkinjo
Get Adobe Flash player
by tkinjo 12 Jun 2009
/**
 * Copyright tkinjo ( http://wonderfl.net/user/tkinjo )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/3uZm
 */

// forked from tkinjo's Dot
package  
{
	/**
	 * いつのまにかライブラリっぽくなってしまった。
	 * もう少し高機能になったら Spark に投稿しようかな。
	 * 
	 * WOW Engine を使うような感じでパーティクルとパーティクルとの間に制約効果を適用するライブラリ
	 * 
	 * 参考
	 * 
	 * WOW Engine
	 * http://seraf.mediabox.fr/wow-engine/as3-3d-physics-engine-wow-engine/
	 * 
	 * JigLibFlash
	 * http://www.jiglibflash.com/blog/
	 */
	
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Vector3D;
	
	[SWF(width="465", height="465", frameRate="60", backgroundColor="0xffffff")]
	/**
	 * ...
	 * @author tkinjo
	 */
	public class Main extends Sprite
	{
		private var constraintWorld:ConstraintWorld;
		private var mousePointer:Particle;
		
		/**
		 * 
		 */
		public function Main() 
		{
			constraintWorld = new ConstraintWorld( 0.9 );
			
			mousePointer = new Particle( mouseX, mouseY );
			
			//*
			var preCircle:Circle;
			for ( var i:Number = 0; i < 5; i++ ) {
				
				var circle:Circle = new Circle();
				circle.friction = 0.5;
				constraintWorld.addParticle( circle );
				
				if( i == 0 )
					constraintWorld.addConstraint( new FollowConstraint( mousePointer, circle, 20 ) );
				
				else 
					constraintWorld.addConstraint( new FollowConstraint( preCircle, circle, 20 ) );
				
				addChild( circle );
				
				preCircle = circle;
			}
			//*/
			
			addEventListener( Event.ENTER_FRAME, enterFrameHandler );
		}
		
		/**
		 * 
		 * @param	event
		 */
		private function enterFrameHandler( event:Event ):void {
			
			mousePointer.x = mouseX;
			mousePointer.y = mouseY;
			
			constraintWorld.step();
		}
	}
}


/**
 * 
 */
//class FollowConstraint extends Constraint implements IConstraint {	// 拡張しようとするとエラーでる…
class FollowConstraint implements IConstraint {
	
	private var constraint:Constraint;
	
	public function get particle1():IParticle { return constraint.particle1 };
	public function set particle1(value:IParticle):void { constraint.particle1 = value };
	public function get particle2():IParticle { return constraint.particle2 };
	public function set particle2(value:IParticle):void { constraint.particle2 = value; };
	public function get allowedDistance():Number { return constraint.allowedDistance; }
	public function set allowedDistance(value:Number):void { constraint.allowedDistance = value; }
	public function get minDistance():Number { return constraint.minDistance; }
	public function set minDistance(value:Number):void { constraint.minDistance = value; }
	public function get maxDistance():Number { return constraint.maxDistance; }
	public function set maxDistance(value:Number):void { constraint.maxDistance = value; }
	
	/**
	 * 
	 * @param	particle1
	 * @param	particle2
	 * @param	stiffness
	 */
	public function FollowConstraint( particle1:IParticle, particle2:IParticle, allowedDistance:Number = 0, minDistance:Number = -1, maxDistance:Number = -1 ) {
		
		//super( particle1, particle2 );
		constraint = new Constraint( particle1, particle2, allowedDistance, minDistance, maxDistance );
	}
	
	/**
	 * 解析
	 */
	//override public function resolve():void {
	public function preApply( threeD:Boolean ):void {
		
		constraint.particle2.vx = ( constraint.distance - allowedDistance ) * -Math.cos( constraint.angle ) * constraint.particle2.friction;
		constraint.particle2.vy = ( constraint.distance - allowedDistance ) * -Math.sin( constraint.angle ) * constraint.particle2.friction;
	}
	
	/**
	 * 
	 * @param	threeD
	 */
	public function apply( threeD:Boolean ):void {
		
		// super.apply( threeD );
		constraint.apply( threeD );
	}
}


import flash.display.Sprite;

/**
 * 
 */
class Circle extends Sprite implements IParticle {
	
	/** --------------------------------------------------
	 * 半径
	 */
	public function get radius():Number { return _radius; }
	
	/**
	 * @private
	 */
	public function set radius(value:Number):void 
	{
		_radius = value;
		draw();
	}
	
	private var _radius:Number;
	
	
	
	/** --------------------------------------------------
	 * 色
	 */
	public function get color():uint { return _color; }
	
	/**
	 * @private
	 */
	public function set color(value:uint):void 
	{
		_color = value;
		draw();
	}
	
	
	private var _color:uint;
	
	/**
	 * x 方向の速度
	 */
	public function get vx():Number { return _vx; }
	public function set vx(value:Number):void { _vx = value; }
	private var _vx:Number = 0;
	
	
	/**
	 * y 方向の速度
	 */
	public function get vy():Number { return _vy; }
	public function set vy(value:Number):void { _vy = value; }
	private var _vy:Number = 0;
	
	
	/**
	 * z 方向の速度
	 */
	public function get vz():Number { return _vz; }
	public function set vz(value:Number):void { _vz = value; }
	private var _vz:Number = 0;
	
	
	/**
	 * z 方向の速度
	 */
	public function get friction():Number { return _friction; }
	public function set friction(value:Number):void { _friction = value; }
	private var _friction:Number = 1;
	
	/**
	 * 
	 * @param	radius
	 * @param	color
	 */
	public function Circle( radius:Number = 5, color:uint = 0 ) {
		
		this.radius = radius;
		this.color = color;
	}
	
	/**
	 * 
	 */
	public function draw():void {
		
		graphics.clear();
		graphics.beginFill( color );
		graphics.drawCircle( 0, 0, _radius );
	}
}



/**
 * 
 */
interface IConstraint {
	
	function get particle1():IParticle;
	function set particle1(value:IParticle):void;
	
	function get particle2():IParticle;
	function set particle2(value:IParticle):void;
	
	function get allowedDistance():Number;
	function set allowedDistance(value:Number):void;
	
	function get minDistance():Number;
	function set minDistance(value:Number):void;
	
	function get maxDistance():Number;
	function set maxDistance(value:Number):void;
	
	function preApply( threeD:Boolean ):void;
	function apply( threeD:Boolean ):void;
}

/**
 * 
 */
class Constraint implements IConstraint {
	
	/**
	 * 
	 */
	public function get particle1():IParticle { return _particle1; }
	public function set particle1(value:IParticle):void { _particle1 = value; }
	protected var _particle1:IParticle;
	
	/**
	 * 
	 */
	public function get particle2():IParticle { return _particle2; }
	public function set particle2(value:IParticle):void { _particle2 = value; }
	protected var _particle2:IParticle;
	
	/**
	 * 
	 */
	public function get allowedDistance():Number { return _allowedDistance; }
	public function set allowedDistance(value:Number):void { _allowedDistance = value; }
	private var _allowedDistance:Number;
	
	/**
	 * 
	 */
	public function get minDistance():Number { return _minDistance; }
	public function set minDistance(value:Number):void { _minDistance = value; }
	private var _minDistance:Number;
	
	/**
	 * 
	 */
	public function get maxDistance():Number { return _maxDistance; }
	public function set maxDistance(value:Number):void { _maxDistance = value; }
	private var _maxDistance:Number;
	
	/**
	 * 
	 * @param	particle1
	 * @param	particle2
	 */
	public function Constraint( particle1:IParticle, particle2:IParticle, allowedDistance:Number = 0, minDistance:Number = -1, maxDistance:Number = -1 ) {
		
		_particle1 = particle1;
		_particle2 = particle2;
		_allowedDistance = allowedDistance;
		_minDistance = minDistance;
		_maxDistance = maxDistance;
	}
	
	/**
	 * 
	 */
	//protected function get dx():Number {
	public function get dx():Number {
		return _particle2.x - _particle1.x;
	}
	
	/**
	 * 
	 */
	//protected function get dy():Number {
	public function get dy():Number {
		return _particle2.y - _particle1.y;
	}
	
	/**
	 * 
	 */
	public function get distance():Number {
		return Math.sqrt( dx * dx + dy * dy );
	}
	
	/**
	 * 
	 */
	public function get angle():Number {
		return Math.atan2(dy, dx);
	}
	
	/**
	 * 解析
	 */
	public function preApply( threeD:Boolean ):void {
		
		
	}
	
	/**
	 * 解析
	 */
	public function apply( threeD:Boolean ):void {
		
		// 一定の距離をあける
		if( 0 <= minDistance && distance < minDistance ) {
			
			particle2.x = particle1.x + minDistance * Math.cos( angle );
			particle2.y = particle1.y + minDistance * Math.sin( angle );
			
		// 一定の距離以上離れさせない
		} else if ( 0 <= maxDistance && distance > maxDistance ) {
			
			particle2.x = particle1.x + maxDistance * Math.cos( angle );
			particle2.y = particle1.y + maxDistance * Math.sin( angle );
		}
	}
}



/**
 * 
 */
interface IParticle {
	
	
	function get x():Number;
	function set x(value:Number):void;
	
	function get y():Number;
	function set y(value:Number):void
	
	function get z():Number;
	function set z(value:Number):void;	
	
	function get vx():Number;
	function set vx(value:Number):void;
	
	function get vy():Number;
	function set vy(value:Number):void;
	
	function get vz():Number;
	function set vz(value:Number):void;
	
	function get friction():Number;
	function set friction(value:Number):void;
}

/**
 * 
 */
class Particle implements IParticle {
	
	private var _x:Number;
	public function get x():Number { return _x; }
	public function set x(value:Number):void { _x = value; }
	
	private var _y:Number;
	public function get y():Number { return _y; }
	public function set y(value:Number):void { _y = value; }
	
	private var _z:Number;
	public function get z():Number { return _z; }
	public function set z(value:Number):void { _z = value; }
	
	private var _vx:Number;
	public function get vx():Number { return _vx; }
	public function set vx(value:Number):void { _vx = value; }
	
	private var _vy:Number;
	public function get vy():Number { return _vy; }
	public function set vy(value:Number):void { _vy = value; }
	
	private var _vz:Number;
	public function get vz():Number { return _vz; }
	public function set vz(value:Number):void { _vz = value; }
	
	private var _friction:Number;
	public function get friction():Number { return _friction; }
	public function set friction(value:Number):void { _friction = value; }
	
	public function Particle( x:Number = 0, y:Number = 0, z:Number = 0, vx:Number = 0, vy:Number = 0, vz:Number = 0, friction:Number = 0 ):void {
		
		_x = x;
		_y = y;
		_z = z;
		_vx = vx;
		_vy = vy;
		_vz = vz;
		_friction = friction;
	}
}



import flash.geom.Vector3D;

/**
 * ワールドクラス
 * 
 * 重力や 3D など設定とパーティクルとそれらに適用される制約効果の管理
 */
class ConstraintWorld {
	
	/**
	 * 摩擦係数
	 */
	public var friction:Number;
	
	/**
	 * パーティクルに常にかかる力
	 */
	public var force:Vector3D;
	
	/**
	 * 3D
	 */
	public var threeD:Boolean;
	
	/**
	 * パーティクルの配列
	 */
	private var particles:Vector.<IParticle>;
	
	/**
	 * 制約効果の配列
	 */
	private var constraints:Vector.<IConstraint>;
	
	/**
	 * コンストラクタ
	 */
	public function ConstraintWorld( friction:Number = 1, force:Vector3D = null, threeD:Boolean = false ):void {
		
		this.friction = friction;
		
		if ( !force )
			this.force = new Vector3D();
		
		else 
			this.force = force;
		
		this.threeD = threeD;
		particles = new Vector.<IParticle>();
		constraints = new Vector.<IConstraint>();
	}
	
	/**
	 * 
	 */
	public function step():void {
		
		// force の適用前の制約効果処理
		constraints.forEach( function(item:IConstraint, index:int, vector:Vector.<IConstraint>):void {
				
				item.preApply( threeD );
			} );
		
		// force の適用
		if ( force ) {
			
			particles.forEach( function(item:IParticle, index:int, vector:Vector.<IParticle>):void {
					
					item.vx += force.x;
					item.vy += force.y;
					item.vz += force.z;
				} );
		}
		
		// force の適用後の制約効果処理
		constraints.forEach( function(item:IConstraint, index:int, vector:Vector.<IConstraint>):void {
				
				item.apply( threeD );
			} );
		
		// 適用
		particles.forEach( function(item:IParticle, index:int, vector:Vector.<IParticle>):void {
				
				item.vx *= friction * item.friction;
				item.vy *= friction * item.friction;
				
				item.x += item.vx;
				item.y += item.vy;
				
				if( threeD )
					item.vz *= friction * item.friction;
					item.z += item.vz;
			} );
	}
	
	/**
	 * 
	 */
	public function addParticle( particle:IParticle ):IParticle {
		
		particles.push( particle );
		
		return particle;
	}
	
	/**
	 * 
	 * @param	particle
	 * @return
	 */
	public function removeParticle( particle:IParticle ):void {
		
		particles.every( function( item:IParticle, index:int, array:Array ):Boolean {
				
				if ( item == particle ) {
					
					particles.splice( index, 1 );
					return false;
				}
				
				return true;
			} );
	}
	
	/**
	 * 
	 */
	public function addConstraint( constraint:IConstraint ):IConstraint {
		
		constraints.push( constraint );
		
		return constraint;
	}
	
	/**
	 * 
	 * @param	constraint
	 * @return
	 */
	public function removeConstraint( constraint:IConstraint ):void {
		
		constraints.every( function( item:IConstraint, index:int, array:Array ):Boolean {
				
				if ( item == constraint ) {
					
					constraints.splice( index, 1 );
					return false;
				}
				
				return true;
			} );
	}
	
	/**
	 * 
	 * @param	constraint
	 * @return
	 */
	public function removeConstraintAtParticle( particle:IParticle ):void {
		
		constraints.every( function( item:IConstraint, index:int, array:Array ):Boolean {
				
				if ( item.particle1 == particle || item.particle2 == particle ) {
					
					constraints.splice( index, 1 );
					return false;
				}
				
				return true;
			} );
	}
}