forked from: JOINING
I am just going to play around a bit and see if I can come back to this once in a while and speed things up.
Now, the issue is with clustering... the more it clusters, the more dense a loop it goes through... so I just reduced some operations and checks, gave the particles more velocity, and things sped up drastically. Still needs work though to dense clustering of points that are a larger distance away... if you slow down the initial velocities of each particle when it's instantiated, you will see what I mean.
@Original author SPANVEGA // CHRISTIAN
@Edited by: NME
/**
* Copyright NME ( http://wonderfl.net/user/NME )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/7H94
*/
package
{
import flash.geom.*;
import flash.events.*;
import flash.display.*;
import flash.filters.*;
import com.bit101.components.*;
/**
Modifications in this Fork by NME A.K.A Anthony Pace
...
@Original author SPANVEGA // CHRISTIAN
@Edited by: NME
**/
[ SWF (width = '465', height = '465', backgroundColor = '0x00', frameRate = '60')]
public class JOINING extends Sprite
{
private var bgc:uint = 0;
private var w : uint = 465, h : uint = 465;
private var r : Rectangle = new Rectangle (0, 0, w, h);
private var b : BRESENHAM = new BRESENHAM (w, h, false, bgc);
private var f : BlurFilter = new BlurFilter (1.25, 1.25, 1);
private var m : Matrix = new Matrix (), p : Point = new Point ();
private var t : ColorTransform = new ColorTransform (1, 1, 1, 0.25);
private var connected : Vector.<int> = new Vector.<int>(quantity, true);
private var quantity_slider : HUISlider, distance_slider : HUISlider;
private var pressed : Boolean = false, type : int;
private var distance : int=90, fade : Number, step : Number, ratio : Number;
private var quantity : int = 234, hue : Number = 53;
private var d : Number, dx : int, dy : int;
private var distanceToExp2:int, dx2_x_dy2:int;
private var maxDistance:int = 200;//
private var maxQuantity:int = 1000;
//using distancePool[dx2_x_dy2] we find the stored square root
private var distancePool:Vector.<Number> = new Vector.<Number>(maxDistance*maxDistance,true);
private var pool : POOL, pa : POINT, pb : POINT;
private var lines : Array = [], line : LINE;
private var shape : BitmapData, size : int;
private var negSize_div2:Number;
private var i : int, j : int;
public function JOINING ()
{
stage ? init () : addEventListener (Event.ADDED_TO_STAGE, init);
}
private function init (e : Event = null) : void
{
if (hasEventListener (Event.ADDED_TO_STAGE))
{removeEventListener (Event.ADDED_TO_STAGE, init);}
Wonderfl.disable_capture ();
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.quality = StageQuality.LOW;
var md2:int = maxDistance*maxDistance;
for(var dpos:int = 0; dpos!=md2;++dpos){//
distancePool[dpos] = Math.sqrt(dpos);
}//
graphics.beginFill (bgc, 1);
graphics.drawRect (0, 0, w, h);
//
var c : uint = 0xFFFFFFFF;
shape = new BitmapData (size = 5, size, true, 0);
negSize_div2 = -size*.05;
shape.setVector (new Rectangle (0, 0, size, size), new <uint>
[0, 0, c, 0, 0, 0, c, c, c, 0, c, c, c, c, c, 0, c, c, c, 0, 0, 0, c, 0, 0]);
addChild (new Bitmap (b));
gui();
//storage / methods for pts
pool = new POOL (0, 0, w, h);
for (i = 0; i < quantity; i++)
{
pool.add (point ());
}
_distance ();
//
stage.addEventListener ('mouseDown', press_left);
stage.addEventListener ('mouseUp', press_left);
stage.addEventListener ('rightMouseDown', press_right);
stage.addEventListener ('rightMouseUp', press_right);
render ();
stage.addEventListener ('enterFrame', render);
// var iid:uint= setInterval(render,1000/60);
}
private function point () : POINT
{
var vdr:int = 5;
pa = new POINT ();
pa.px = Math.random () * pool.width;
pa.py = Math.random () * pool.height;
pa.vx = -vdr + Math.random () * vdr*2;
pa.vy = -vdr + Math.random () * vdr*2;
return pa;
}
/*private function storedSquareRoot(n:uint):Number{
var result:Number=distancePool[n];
if(result==0){
//
result = Math.sqrt(n);
distancePool[n]=result;
}
return result;
}*/
private function render (e : Event = null) : void
{
var sDx:Number=0;
var sDy:Number=0;
if (pressed)
{ check (); }
pool.update ();
lines.length = 0;
b.lock ();
b.fillRect (r, bgc);
for (i = 0; i != quantity; i++)
{
pa = pool.num (i);
for (j = quantity-1; j != i ; --j)
{
pb = pool.num (j);
dx = pb.px - pa.px;
dy = pb.py - pa.py;
dx2_x_dy2 = dx * dx + dy * dy;
//no need to call a sqrt function if the lines are too far right?
if(dx2_x_dy2 < distanceToExp2){//
//maybe we should be doing a lookup using the dx and dy?
//d = Math.sqrt(dx2_x_dy2);
//d = storedSquareRoot(dx2_x_dy2);
d = distancePool[dx2_x_dy2];
ratio = 0xFF;
if (d > fade)
{
ratio = 64 + ((distance - d) / step * 190);
}
line = new LINE ();
line.px = pa.px; line.py = pa.py;
line.tx = pb.px; line.ty = pb.py;
line.color = ratio << 24 | hsv2rgb ((d + hue) % 360);
lines.push (line);
connected [i] = connected [j] = 1;
// SPRING
sDx = dx * 0.00025;
sDy = dy * 0.00025;
pa.vx += sDx;
pa.vy += sDy;
pb.vx -= sDx;
pb.vy -= sDy;//
}
}
}
lines.sortOn ('color', Array.NUMERIC);
// RENDER LINES
j = lines.length;
for (i = 0; i < j; i++)
{
line = lines [i];
b.line (line.px, line.py, line.tx, line.ty, line.color);
}
b.applyFilter (b, r, p, f);
// RENDER POINTS
for (i = 0; i < quantity; i++)
{
pa = pool.num (i);
m.tx = ~~ (negSize_div2 + pa.px);
m.ty = ~~ (negSize_div2 + pa.py);
b.draw (shape, m, connected [i] == 0 ? t : null);
// RESET STATUS
connected [i] = 0;
}
b.unlock ();
}
private function check () : void
{
if (type == 0)
{
if (pool.len < quantity_slider.maximum)
{
pa = point ();
pa.px = stage.mouseX;
pa.py = stage.mouseY;
pool.add (pa);
quantity += 1;
}
}
if (type == 1)
{
if (pool.len > quantity_slider.minimum)
{
pool.del (pool.len-1);
quantity -= 1;
}
}
quantity_slider.value = quantity;
connected = new Vector.<int>(quantity, true);
}
private function press_left (e : MouseEvent) : void
{
type = 0;
if (e.type == 'mouseDown' && stage.mouseY < h - 25)
{
pressed = true;
}
if (e.type == 'mouseUp') { pressed = false; }
}
private function press_right (e : MouseEvent) : void
{
type = 1;
if (e.type == 'rightMouseDown' && stage.mouseY < h - 25)
{
pressed = true;
}
if (e.type == 'rightMouseUp'){ pressed = false; }
}
private function gui () : void
{
// oh god... the with keyword.... soooo annoying
with (Style) {
BACKGROUND = LABEL_TEXT = 0xFFFFFF;
DROPSHADOW = BUTTON_FACE = 0x000000;
}
with (addChild (new Sprite ())){
graphics.beginFill (0x404040, 0.25);
graphics.drawRect (0, 440, 465, 25);
}
distance_slider = new HUISlider (this, 10, 445, 'DISTANCE', _distance);
with (distance_slider) {
setSliderParams (0, maxDistance, distance);
width = 160;
labelPrecision = 0;
tick = 1;
}
quantity_slider = new HUISlider (this, 170, 445, 'QUANTITY', _quantity);
with (quantity_slider) {
setSliderParams (0, maxQuantity, quantity);
width = 160;
labelPrecision = 0;
tick = 1;
}
var h : HUISlider = new HUISlider (this, 327, 445, 'HUE', _hue);
h.setSliderParams (0, 360, hue); h.width = 160; h.labelPrecision = 0; h.tick = 1;
}
//
private function _distance (e : Event = null) : void
{
distance = distance_slider.value;
distanceToExp2 = distance*distance;
fade = distance * 0.75;
step = distance - fade;
}
private function _hue (e : Event) : void
{
hue = e.target.value;
}
private function _quantity (e : Event) : void
{
var num : int;
quantity = e.target.value;
if (quantity > pool.len)
{
num = quantity - pool.len;
for (i = 0; i < num; i++)
{
pool.add (point ());
}
}else if (quantity < pool.len)
{
num = pool.len - quantity;
for (i = 0; i < num; i++)
{
pool.del (pool.len-1);
}
}
connected = new Vector.<int>(quantity, true);
}
private function hsv2rgb (h : Number = 0, s : Number = 1, v : Number = 1) : uint
{
var i : int = int (h / 60);
var f : Number = h / 60 - i;
var p : Number = v * (1 - s);
var q : Number = v * (1 - s * f);
var t : Number = v * (1 - s * (1 - f));//
switch (i)
{
case 0: return v * 0xFF << 16 | t * 0xFF << 8 | p * 0xFF << 0;
case 1: return q * 0xFF << 16 | v * 0xFF << 8 | p * 0xFF << 0;
case 2: return p * 0xFF << 16 | v * 0xFF << 8 | t * 0xFF << 0;
case 3: return p * 0xFF << 16 | q * 0xFF << 8 | v * 0xFF << 0;
case 4: return t * 0xFF << 16 | p * 0xFF << 8 | v * 0xFF << 0;
case 5: return v * 0xFF << 16 | p * 0xFF << 8 | q * 0xFF << 0;
}
return 0;
// http://wonderfl.net/c/dtn8
}
}
}
//
final class LINE
{
public var px : Number, py : Number;
public var tx : Number, ty : Number;
public var color : uint;
}
//
import flash.geom.Rectangle;
final class POOL extends Rectangle
{
private var points : Vector.<POINT>;
private var p : POINT;
public function POOL (x : Number, y : Number, width : Number, height : Number)
{
super (x, y, width, height);
points = new <POINT> [];
}
public function update () : void
{
var i : int = len;
while (--i > -1)
{
p = points [i];
p.px += p.vx;
p.py += p.vy;
if (p.px < x) { p.px = x; p.vx = -p.vx; }
if (p.py < y) { p.py = y; p.vy = -p.vy; }
if (p.px > x + width) { p.px = width + x; p.vx = -p.vx; }
if (p.py > y + height) { p.py = height + y; p.vy = -p.vy; }
}
}
public function add (p : POINT) : void
{
points.push (p);
}
public function del (index : uint) : void
{
points.splice (index, 1);
}
public function mod (index : uint, p : POINT) : void
{
points [index] = p;
}
public function num (index : uint) : POINT
{
return points [index];
}
public function get len () : uint
{
return points.length;
}
}
final class POINT
{
public var px : Number, py : Number;
public var vx : Number, vy : Number;
}
//
import flash.display.BitmapData;
final class BRESENHAM extends BitmapData
{
// http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
public function BRESENHAM (width : uint, height : uint, transparent : Boolean = true, color : uint = 0xffffff)
{
super (width, height, transparent, color);
}
public function line (x0 : int, y0 : int, x1 : int, y1 : int, color : uint = 0xffffff) : void
{
var dx : int = x1 - x0;
var dy : int = y1 - y0;
var sx : int = dx >= 0 ? 1 : -1;
var sy : int = dy >= 0 ? 1 : -1;
dx = dx >= 0 ? dx : -dx;
dy = dy >= 0 ? dy : -dy;
var err : int = dx - dy, e2 : int;
while (true)
{
setPixel32 (x0, y0, color);
if (x0 == x1 && y0 == y1) break;
e2 = err << 1;
if (e2 > -dy) { err -= dy; x0 += sx; }
if (e2 < dx) { err += dx; y0 += sy; }
}
}
}