Magnetic
Ported from http://jsdo.it/hakim/magnetic-02
/**
* Copyright bradsedito ( http://wonderfl.net/user/bradsedito )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/7b46
*/
// Magnetic
// Brad Sedito 2012
// Ported from http://jsdo.it/hakim/magnetic-02
package
{
import flash.display.*;
import flash.events.*;
import flash.utils.getTimer;
public class Magnetic extends Sprite
{
private var MAGNETS_AT_START:int = 4;
private var PARTICLES_PER_MAGNET:int = 20;
private var MAGNETIC_FORCE_THRESHOLD:int = 300;
private var particles:Array = new Array();
private var magnets:Array = new Array();
private var mouseIsDown:Boolean = false;
private var mouseDownTime:int = 0;
private var particle:Particle;
private var magnet:Magnet;
private var i:int;
private var j:int;
private var ilen:int;
private var jlen:int;
private var len:int;
public function Magnetic():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
stage.addEventListener(MouseEvent.MOUSE_DOWN, documentMouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, documentMouseUpHandler);
createMagnets();
addEventListener(Event.ENTER_FRAME, loop);
}
private function createMagnets():void {
var w:int = 300;
var h:int = 300;
for (var i:int = 0; i < MAGNETS_AT_START; i++) {
var position:Object = {
x: (stage.stageWidth - w) * 0.5 + (Math.random() * w),
y: (stage.stageHeight - h) * 0.5 + (Math.random() * h)
};
createMagnet(position);
}
}
private function createMagnet(position:Object):void {
var m:Magnet = new Magnet();
m.position.x = position.x;
m.position.y = position.y;
magnets.push(m);
createParticles(m.position);
}
private function createParticles( position:Object ):void {
for (i = 0; i < PARTICLES_PER_MAGNET; i++) {
var p:Particle = new Particle();
p.position.x = position.x;
p.position.y = position.y;
p.shift.x = position.x;
p.shift.y = position.y;
particles.push(p);
}
}
private function documentMouseDownHandler(event:MouseEvent):void {
event.preventDefault();
mouseIsDown = true;
if (getTimer() - mouseDownTime < 300) {
// The mouse was pressed down twice with a < 300 ms interval: add a magnet
createMagnet( {x:mouseX, y:mouseY} );
mouseDownTime = 0;
}
mouseDownTime = getTimer();
len = magnets.length
for (i = 0; i < len; i++) {
magnet = magnets[i];
if (distanceBetween(magnet.position, { x: mouseX, y: mouseY }) < magnet.orbit * .5) {
magnet.dragging = true;
break;
}
}
}
private function documentMouseUpHandler(event:MouseEvent):void {
mouseIsDown = false;
len = magnets.length
for (i = 0; i < len; i++) {
magnet = magnets[i];
magnet.dragging = false;
}
}
private function loop(e:Event):void {
graphics.clear();
// Render the magnets
for (j = 0, jlen = magnets.length; j < jlen; j++) {
magnet = magnets[j];
if (magnet.dragging) {
magnet.position.x += (mouseX - magnet.position.x) * 0.2;
magnet.position.y += (mouseY - magnet.position.y) * 0.2;
}
// Increase the size of the magnet center point depending on # of connections
magnet.size += ((magnet.connections/3) - magnet.size) * 0.05;
magnet.size = Math.max(magnet.size, 2);
graphics.lineStyle(0, 0xFF00FF, 0);
graphics.beginFill(0xFF00FF, 0.4);
graphics.drawCircle(magnet.position.x, magnet.position.y, magnet.size * 10);
graphics.endFill();
graphics.lineStyle(0, 0x0000FF, 0);
graphics.beginFill(0x0000FF, 0.4);
graphics.drawCircle(magnet.position.x, magnet.position.y, magnet.size);
graphics.endFill();
magnet.connections = 0;
}
// Render the particles
for (i = 0, ilen = particles.length; i < ilen; i++) {
particle = particles[i];
var currentDistance:Number = -1;
var closestDistance:Number = -1;
var closestMagnet:Magnet = null;
var force:Object = {x:0, y:0};
// For each particle, we check what the closes magnet is
for (j = 0, jlen = magnets.length; j < jlen; j++) {
magnet = magnets[j];
currentDistance = distanceBetween(particle.position, magnet.position) - (magnet.orbit * 0.5);
if (particle.magnet != magnet) {
var fx:Number = magnet.position.x - particle.position.x;
if (fx > -MAGNETIC_FORCE_THRESHOLD && fx < MAGNETIC_FORCE_THRESHOLD) {
force.x += fx / MAGNETIC_FORCE_THRESHOLD;
}
var fy:Number = magnet.position.y - particle.position.y;
if (fy > -MAGNETIC_FORCE_THRESHOLD && fy < MAGNETIC_FORCE_THRESHOLD) {
force.y += fy / MAGNETIC_FORCE_THRESHOLD;
}
}
if (closestMagnet == null || currentDistance < closestDistance) {
closestDistance = currentDistance;
closestMagnet = magnet;
}
}
if (particle.magnet == null || particle.magnet != closestMagnet) {
particle.magnet = closestMagnet;
}
closestMagnet.connections += 1;
// Rotation
particle.angle += particle.speed;
// Translate towards the magnet position
particle.shift.x += ( (closestMagnet.position.x+(force.x*8)) - particle.shift.x) * particle.speed;
particle.shift.y += ( (closestMagnet.position.y+(force.y*8)) - particle.shift.y) * particle.speed;
// Appy the combined position including shift, angle and orbit
particle.position.x = particle.shift.x + Math.cos(i+particle.angle) * (particle.orbit*particle.force);
particle.position.y = particle.shift.y + Math.sin(i+particle.angle) * (particle.orbit*particle.force);
// Limit to screen bounds
particle.position.x = Math.max( Math.min( particle.position.x, stage.stageWidth-particle.size/2 ), particle.size/2 );
particle.position.y = Math.max( Math.min( particle.position.y, stage.stageHeight-particle.size/2 ), particle.size/2 );
// Slowly inherit the cloest magnets orbit
particle.orbit += ( closestMagnet.orbit - particle.orbit ) * 0.1;
graphics.lineStyle(0, 0xFF0000, 1);
graphics.beginFill(0xFF0000, 0.4);
graphics.drawCircle(particle.position.x, particle.position.y, particle.size);
graphics.endFill();
}
}
private function distanceBetween(p1:Object, p2:Object):Number {
var dx:Number = p2.x - p1.x;
var dy:Number = p2.y - p1.y;
return Math.sqrt(dx * dx + dy * dy);
}
}
}
internal class Particle {
public var size:Number = 0.5 + Math.random() * 3.5;
public var position:Object = { x: 0, y: 0 };
public var shift:Object = { x: 0, y: 0 };
public var angle:Number = 0;
public var speed:Number = 0.01 + (size / 4) * 0.03;
public var force:Number = 1 - (Math.random()*0.15);
public var color:int = 0xffffff;
public var orbit:Number = 1;
public var magnet:Magnet = null;
}
internal class Magnet {
public var orbit:Number = 100;
public var position:Object = { x: 0, y: 0 };
public var dragging:Boolean = false;
public var connections:Number = 0;
public var size:Number = 1;
}