Sand Traveler
Sand Traveler
stage click to reset
@see http://www.complexification.net/gallery/machines/sandTraveler/index.php
Special commission for Sónar 2004, Barcelona
sand painter implementation of City Traveler + complexification.net
j.tarbell May, 2004
Albuquerque, New Mexico
complexification.net
Processing 0085 Beta syntax update
j.tarbell April, 2005
@mxmlc -o bin/SandTraveler.swf -load-config+=obj\Alltest3Config.xml
@author jc at bk-zen.com
/**
* Copyright bkzen ( http://wonderfl.net/user/bkzen )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/qqb0
*/
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.events.MouseEvent;
/**
* Sand Traveler
* stage click to reset
*
* @see http://www.complexification.net/gallery/machines/sandTraveler/index.php
* Special commission for Sónar 2004, Barcelona
* sand painter implementation of City Traveler + complexification.net
*
* j.tarbell May, 2004
* Albuquerque, New Mexico
* complexification.net
*
* Processing 0085 Beta syntax update
* j.tarbell April, 2005
*
* @mxmlc -o bin/SandTraveler.swf -load-config+=obj\Alltest3Config.xml
* @author jc at bk-zen.com
*/
[SWF (backgroundColor = "0xFFFFFF", frameRate = "60", width = "465", height = "465")]
public class SandTraveler extends Sprite
{
private var cities:Vector.<City>;
private var bmd: BitmapData;
private var w: int;
private var h: int;
private var size: int;
private var bmp:Bitmap;
private var cnt:int;
public function SandTraveler()
{
Wonderfl.capture_delay( 30 );
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e: Event = null): void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
//
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
cities = new Vector.<City>(LENGTH, true);
addChild(bmp = new Bitmap(null, "auto", true));
resetAll();
addEventListener(Event.ENTER_FRAME, loop);
stage.addEventListener(Event.RESIZE, onResize);
stage.addEventListener(MouseEvent.CLICK, onClick);
}
private function onClick(e: MouseEvent): void
{
resetAll();
}
private function onResize(e: Event): void
{
resetAll();
}
private function loop(e: Event): void
{
var c: City, f: City, i: int, j: int, k: int, t: Number, dx: Number, dy: Number, dst: uint, src: uint, tdx: int, tdy: int;
var rd: int, gd: int, bd: int, rs: int, gs: int, bs: int, s: SandPainter, ww: Number, a: Number;
bmd.lock();
for (i = 0; i < LENGTH; i++)
{
c = cities[i], f = c.friend;
c.x += (c.vx = (c.vx + (f.x - c.x) / size) * 0.936);
c.y += (c.vy = (c.vy + (f.y - c.y) / size) * 0.936);
for (j = 0; j < RLENGTH; j++)
{
t = random(PI2);
dx = tdx = (Math.sin(t) * (c.x - f.x) + (c.x + f.x)) * 0.5;
dy = tdy = (Math.sin(t) * (c.y - f.y) + (c.y + f.y)) * 0.5;
if (random(1000) > 990) dx += random(3) - random(3), dy += random(3) - random(3);
dst = bmd.getPixel(dx, dy);
src = f.color;
rd = (dst >> 16) & 0xFF;
gd = (dst >> 8) & 0xFF;
bd = dst & 0xFF;
rs = (src >> 16) & 0xFF;
gs = (src >> 8) & 0xFF;
bs = src & 0xFF;
bmd.setPixel(dx, dy, ((rd * 0.8125 + rs * 0.1875) << 16) | ((gd * 0.8125 + gs * 0.1875) << 8) | (bd * 0.8125 + bs * 0.1875));
dx = -1 * tdx;
dy = -1 * tdy;
if (random(1000) > 990) dx += random(3) - random(3), dy += random(3) - random(3);
dst = bmd.getPixel(dx, dy);
src = f.color;
rd = (dst >> 16) & 0xFF;
gd = (dst >> 8) & 0xFF;
bd = dst & 0xFF;
rs = (src >> 16) & 0xFF;
gs = (src >> 8) & 0xFF;
bs = src & 0xFF;
bmd.setPixel(dx, dy, ((rd * 0.8125 + rs * 0.1875) << 16) | ((gd * 0.8125 + gs * 0.1875) << 8) | (bd * 0.8125 + bs * 0.1875));
}
for (j = 0; j < SLENGTH; j++)
{
s = c.sands[j];
dx = f.x + (c.x - f.x) * Math.sin(s.p);
dy = f.y + (c.y - f.x) * Math.sin(s.p);
dst = bmd.getPixel(dx, dy);
src = s.c;
rd = (dst >> 16) & 0xFF;
gd = (dst >> 8) & 0xFF;
bd = dst & 0xFF;
rs = (src >> 16) & 0xFF;
gs = (src >> 8) & 0xFF;
bs = src & 0xFF;
bmd.setPixel(dx, dy, ((rd * 0.890625 + rs * 0.109375) << 16) | ((gd * 0.890625 + gs * 0.109375) << 8) | (bd * 0.890625 + bs * 0.109375));
s.g += random( -0.05, 0.05);
if (s.g < -0.22) s.g = -0.22;
if (s.g > 0.22) s.g = 0.22;
s.p += random( -0.05, 0.05);
if (s.p < 0) s.p = 0;
if (s.p > 1) s.p = 1;
ww = s.g * 0.1;
for (k = 0; k < RLENGTH; k++)
{
a = (0.1 - k * 0.009) * 0.00390625;
dx = f.x + (c.x - f.x) * Math.sin(s.p + Math.sin(k * ww));
dy = f.y + (c.y - f.y) * Math.sin(s.p + Math.sin(k * ww));
dst = bmd.getPixel(dx, dy);
rd = (dst >> 16) & 0xFF;
gd = (dst >> 8) & 0xFF;
bd = dst & 0xFF;
bmd.setPixel(dx, dy, ((rd * (1 - a) + rs * a) << 16) | ((gd * (1-a) + gs * a) << 8) | (bd * (1 - a) + bs * a));
dx = f.x + (c.x - f.x) * Math.sin(s.p - Math.sin(k * ww));
dy = f.y + (c.y - f.y) * Math.sin(s.p - Math.sin(k * ww));
dst = bmd.getPixel(dx, dy);
rd = (dst >> 16) & 0xFF;
gd = (dst >> 8) & 0xFF;
bd = dst & 0xFF;
bmd.setPixel(dx, dy, ((rd * (1 - a) + rs * a) << 16) | ((gd * (1-a) + gs * a) << 8) | (bd * (1 - a) + bs * a));
}
}
}
bmd.unlock();
if (cnt++ > 5000) resetAll();
}
private function resetAll():void
{
var vt: Number, vvt: Number = 0.2, ot: Number = random(PI2);
var t: int, tinc: Number, vx: Number, vy: Number, c: City;
cnt = 0;
if (w != stage.stageWidth || h != stage.stageHeight)
{
if (bmd) bmd.dispose();
bmd = new BitmapData(w = stage.stageWidth, h = stage.stageHeight, false);
bmp.bitmapData = bmd;
bmp.smoothing = true;
size = (w + h) / 2;
}
vt = size / 40;
bmd.lock();
bmd.fillRect(bmd.rect, 0xFFFFFF);
bmd.unlock();
for (t = 0; t < LENGTH; t++)
{
tinc = ot + (3.1 - t / LENGTH) * 2 * t * PI2 / LENGTH;
vx = vt * Math.sin(tinc), vy = vt * Math.cos(tinc);
cities[t] = new City(w / 2 + vx * 2, h / 2 + vy * 2, vx, vy, t);
vvt -= 0.00033;
vt += vvt;
}
for (t = 0; t < LENGTH; t++)
{
c = cities[t];
c.friend = cities[(c.idx + int(random(LENGTH / 5))) % LENGTH];
}
}
}
}
class City
{
public var x: Number, y: Number, vx: Number, vy: Number, idx: int, color: uint;
public var friend: City;
public var sands: Vector.<SandPainter>;
function City(x: Number, y: Number, vx: Number, vy: Number, idx: int)
{
this.x = x, this.y = y, this.vx = vx, this.vy = vy, this.idx = idx;
color = goodcolor[int(random(goodcolor.length))];
sands = new Vector.<SandPainter>(SLENGTH, true);
for (var i:int = 0; i < SLENGTH; i++) sands[i] = new SandPainter();
}
}
class SandPainter
{
public var p: Number, c: uint, g: Number;
function SandPainter() { p = random(1), c = goodcolor[int(random(goodcolor.length))], g = random(0.01, 0.1); }
}
const PI2: Number = 6.28318530717958647693;
const LENGTH: int = 100;
const SLENGTH: int = 3;
const RLENGTH: int = 11;
const goodcolor: Array = [
0x3a242b, 0x3b2426, 0x352325, 0x836454, 0x7d5533, 0x8b7352, 0xb1a181, 0xa4632e, 0xbb6b33,
0xb47249, 0xca7239, 0xd29057, 0xe0b87e, 0xd9b166, 0xf5eabe, 0xfcfadf, 0xd9d1b0, 0xfcfadf,
0xd1d1ca, 0xa7b1ac, 0x879a8c, 0x9186ad, 0x776a8e, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF
];
function random(...args: Array): Number
{
switch (args.length)
{
case 1:
return Math.random() * args[0];
break;
case 2:
default:
var min: Number = args[0];
return Math.random() * (args[1] - min) - min;
break;
}
return Math.random();
}