/**
* Copyright WLAD ( http://wonderfl.net/user/WLAD )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/h415
*/
// forked from Vladik's forked from: Drawing Force Field
package {
import com.bit101.components.HUISlider;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
import flash.utils.getTimer;
public class Temp extends Sprite {
private var field:ForceField;
private var display:DisplayForceField;
public function Temp()
{
initBg();
field = new ForceField();
field.add( 100, 100, -30);
field.add( 0, 0, 10);
display = new DisplayForceField( 70, 70, 0xFF7979, 0x79BCFF);
addChild(display);
addEventListener(Event.ENTER_FRAME, update);
with ( new HUISlider(this, 5, 5, "A", function(e:*= null):void
{
field.forces[0].charge = e.target.value;
})) {
minimum = -50;
maximum = 50;
value = field.forces[0].charge;
}
with ( new HUISlider(this, 200, 5, "B", function(e:*= null):void
{
field.forces[1].charge = e.target.value;
})) {
minimum = -50;
maximum = 50;
value = field.forces[1].charge;
}
}
private function initBg():void
{
var bg:Shape = new Shape();
addChild( bg );
bg.graphics.beginFill( 0 );
bg.graphics.drawRect(00, 0, SW, SH);
bg.graphics.endFill();
}
private function update(e:Event):void
{
field.forces[0].x = display.mouseX;
field.forces[0].y = display.mouseY;
display.draw( field );
}
}
}
import flash.display.Shape;
import flash.geom.Point;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.text.TextField;
var SW:int = 465, SH:int = 465;
class DisplayForceField extends Shape
{
private var w:int;
private var h:int;
private var r:int;
private var color:uint;
private var ah:int;
private var aw:int;
private var colorN:uint;
private var colorP:uint;
public function DisplayForceField( w:int = 30, h:int = 30, colorP:uint = 0xFF0000 , colorN:uint = 0x0000FF)
{
this.colorP = colorP;
this.colorN = colorN;
this.h = h;
this.w = w;
aw = int( SW / w );
ah = int( SH / h );
x = SW / 2;
y = SH / 2;
r = ( aw < ah ? aw : ah ) / 2 ;
}
public function draw( ff:ForceField ):void
{
graphics.clear();
var v:Vec;
var f:Force = new Force( 0, 0, 1);
// remeber - since the FF is shifter to x=Sw/2, y=Sh/2
// the origin is located in X=0, and Y=0
var a:Number; var c:uint;
for (var x:int = -w/2; x < w/2; x++)
{
for (var y:int = -h/2; y < h/2; y++)
{
f.x = aw * x;
f.y = aw * y;
// Find out the force of resolute at force 'f' position
v = ff.f( f.x, f.y , f.charge );
//a = 100 / v.lenght;
a = (ff.forceT * 100) + 0.5;
c = blend( colorP, colorN , (ff.forceT * 100) + 0.5 );
// trace( ff.forceT );
graphics.lineStyle( r , c , a );
if ( ff.forceT < 0 )
{
v.x = -v.x;
v.y = -v.y;
}
drawArrow( f, v );
}
}
for (var i:int = 0; i < ff.forces.length; i++)
{
c = ff.forces[i].charge > 0 ? colorP : colorN;
graphics.lineStyle( r, 0x333333 );
graphics.beginFill( c );
graphics.drawCircle( ff.forces[i].x, ff.forces[i].y, 10 );
graphics.endFill();
}
}
private function drawArrow( f:Force, v:Vec ):void
{
v.lenght = r ;
graphics.moveTo( f.x + v.x , f.y + v.y );
graphics.lineTo( f.x, f.y );
}
}
class ForceField
{
public static var CONST:Number = 1;
public var forces:Vector.<Force>;
public function ForceField( )
{
forces = new Vector.<Force>();
}
public function add( x:Number, y:Number, charge:Number ):void
{
forces.push( new Force( x, y, charge ) );
}
public function f( x:Number, y:Number, q:Number ):Vec
{
var totalForce:Vec = new Vec();
// E = F / q
// E = kQ / r^2
// F = Eq = kQq / r^2
// q = 1
// F = kQ / r^2
// C = F = kQ / r ^ 2
// A^2 + B^2 = C^2
// /|
// C / |
// / | B ( y )
// /a |
// ------
// A ( x )
// cos = x / C
// sin = y / C
// x = cos * C
// y = sin * C
var nx:Number, ny:Number,
sin:Number, cos:Number,
r2:Number, force:Number, f2:Force;
forceT = 0;
for ( var i:int = 0; i < forces.length; i++)
{
f2 = forces[ i ];
nx = ( f2.x - x );
ny = ( f2.y - y );
r2 = nx * nx + ny * ny;
force = ( CONST * f2.charge * q ) / r2;
forceT += force;
// out( force );
r2 = Math.sqrt(r2);
cos = nx / r2;
sin = ny / r2;
totalForce.x += cos * r2;
totalForce.y += sin * r2;
}
return totalForce;
}
/// Read after calling f( ... )
public var forceT:Number = 0;
}
class Force extends Point
{
public var charge:Number;
public function Force( x:Number = 0, y:Number = 0, charge:Number = 0)
{
super( x, y );
this.charge = charge;
}
}
/**
* ...
* @author vladik.voina@gmail.com
*/
class Vec
{
/** rotates one vector around point by x radians and returns a Vec class.
* @param vec [Vec] The vector that beening rotated.
* @param around [Vec] The rotation point that the vector is rotated.
* @param angle [Number] The angle in radians.
**/
public static function rotate(vec:Vec, around:Vec, angle:Number):Vec
{
var v:Vec = vec.vecMinus(around);
v.radians += angle;
v.plus(around);
return v;
}
public static function Polar(lenght:Number, radians:Number):Vec
{
return new Vec(lenght * Math.cos( radians ),lenght * Math.sin( radians ) );
}
public static function Polar2(lenght:Number, degrees:Number):Vec
{
return new Vec(lenght * Math.cos( degrees * Math.PI / 180 ),lenght * Math.sin( degrees * Math.PI / 180 ) );
}
static public function vectorBetween(v1:Vec, v2:Vec):Vec
{
return new Vec(Math.max(v1.x, v2.x) - Math.min(v1.x, v2.x), Math.max(v1.y, v2.y) - Math.min(v1.y, v2.y));
}
public static function fromPoint(p:Point):Vec
{
return new Vec(p.x, p.y);
}
static public function from2Point(start:Point, end:Point):Vec
{
return new Vec(end.x - start.x, end.y - start.y);
}
public var x:Number, y:Number;
public function Vec(x:Number = 0,y:Number = 0)
{
this.x = x;
this.y = y;
}
public function get lenght():Number
{
return Math.sqrt(x * x + y * y);
}
public function set lenght(value:Number):void
{
if (lenght == 0) scale(0);
else scale(value / lenght);
}
public function set degrees(value:Number):void
{
radians = value * Math.PI / 180;
}
public function get degrees():Number
{
return radians * 180 / Math.PI;
}
public function set radians(value:Number):void
{
var f:Number = lenght;
x = Math.cos(value) * f;
y = Math.sin(value) * f;
}
public function get radians():Number
{
return Math.atan2(y, x);
}
public function get sin():Number
{
var f:Number = lenght;
if (f != 0) return y / f;
return 0;
}
public function set sin(value:Number):void
{
radians = Math.asin(value);
}
public function get cos():Number
{
var f:Number = lenght;
if (f != 0) return x / f;
return 0;
}
public function set cos(value:Number):void
{
radians = Math.acos(value);
}
public function dot(v:Vec):Number
{
return this.x * v.x + this.y * v.y;
}
public function plus(vec:Vec):void
{
x += vec.x;
y += vec.y;
}
public function minus(vec:Vec):void
{
x -= vec.x;
y -= vec.y;
}
public function mult(vec:Vec):void
{
x *= vec.x;
y *= vec.y;
}
public function scale(n:Number):void
{
x *= n;
y *= n;
}
//Divisoin.
public function divi(vec:Vec):void
{
if (vec.x != 0 && vec.y != 0)
{
x /= vec.x;
y /= vec.y;
}
}
public function copy(vec:Vec):void
{
x = vec.x;
y = vec.y;
}
public function rotateAroundVector(vec:Vec,radians:Number):Vec
{
this.radians += radians;
plus(vec);
return this;
}
public function vecRotateAroundVector(vec:Vec,radians:Number):Vec
{
return clone().rotateAroundVector(vec,radians);
}
public function vecPlus(vec:Vec):Vec
{
return new Vec(x + vec.x, y + vec.y);
}
public function vecMinus(vec:Vec):Vec
{
return new Vec(x - vec.x, y - vec.y);
}
public function vecMult(vec:Vec):Vec
{
return new Vec(x * vec.x, y * vec.y);
}
public function vecDivi(vec:Vec):Vec
{
return new Vec(x * vec.x, y * vec.y);
}
public function vecForce(force:Number):Vec
{
return new Vec(x * (force / this.lenght), y * (force / this.lenght));
}
public function normR():Vec
{
return new Vec(-y,x);
}
public function normL():Vec
{
return new Vec(y,-x);
}
public function normalize():void
{
var f:Number = lenght;
if (f != 0)
{
x /= f;
y /= f;
}
}
public function normalizedVec():Vec
{
return new Vec(x / lenght,y / lenght);
}
public function clone():Vec
{
return(new Vec(x, y));
}
public function toPoint():Point
{
return new Point(x, y);
}
public function toString():String
{
return "< X: " + x + " >,< Y: " + y + " >.";
}
public function draw(g:Graphics, startPos:Point = null, scale:Number = 5, center:Boolean = false ):void
{
if (startPos == null) startPos = new Point(0, 0);
var hx:Number = x / 2;
var hy:Number = y / 2;
var sx:Number = startPos.x + ( center ? hx : 0 );
var sy:Number = startPos.y + ( center ? hy : 0 );
var ex:Number = sx + ( center ? hx : x );
var ey:Number = sy + ( center ? hy : y );
g.moveTo( sx , sy );
g.lineTo( ex , ey );
var vr:Vec = normR();
var vl:Vec = normL();
// x / l * s = (x/l) * s = s( x/l ) = (s*x) / l = ( s / l ) * x
// ... = s / l * x
var svr:Number = scale / vr.lenght;
g.lineTo
(
ex - svr * ( x - vr.x ),
ey - svr * ( y - vr.y )
);
g.moveTo( ex , ey );
g.lineTo
(
ex - svr * ( x - vl.x ),
ey - svr * ( y - vl.y )
);
}
public function opMultiply(value:Number):void
{
x *= value;
y *= value;
}
public function opSubtract(value:Number):void
{
x -= value;
y -= value;
}
public function opDivide(value:Number):void
{
var v:Number = (value == 0) ? 0.00001 : value;
x /= v;
y /= v;
}
}
/**
* Blends two colours. Percentage should be 0.5 for an equal blend.
*/
function blend(first:uint, second:uint, percent:Number):uint
{
var r:int = ((first & 0xff0000) >> 16) * (1 - percent) + ((second & 0xff0000) >> 16) * percent;
var g:int = ((first & 0x00ff00) >> 8) * (1 - percent) + ((second & 0x00ff00) >> 8) * percent;
var b:int = ((first & 0x0000ff) ) * (1 - percent) + ((second & 0x0000ff) ) * percent;
return r << 16 | g << 8 | b;
}