/**
* Copyright FLASHMAFIA ( http://wonderfl.net/user/FLASHMAFIA )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/U3I3
*/
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
[SWF(width = '465', height = '465')]
public class WeaveSmoke extends Sprite
{
private var bmd : BitmapData;
private var silkContainer : Shape;
private var sparksContainer : Shape;
private var mx0 : Number;
private var my0 : Number;
private var pid : uint;
private var silks : SilkRenderer;
private var pressed : Boolean;
function WeaveSmoke()
{
stage.stageFocusRect = tabChildren = tabEnabled = mouseChildren = mouseEnabled = false;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.quality = StageQuality.MEDIUM;
stage.frameRate = 32;
opaqueBackground = 0x0;
/* */
bmd = new BitmapData(465, 465, false, 0x0);
var bm : Bitmap = new Bitmap(bmd);
addChild(bm);
sparksContainer = new Shape();
addChild(sparksContainer);
silkContainer = new Shape();
silks = new SilkRenderer(silkContainer, sparksContainer);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
addEventListener(Event.ENTER_FRAME, oef);
}
private function oef(e : Event) : void
{
var mx : Number = (stage.mouseX % 465);
var my : Number = (stage.mouseY % 465);
if (pressed)
{
silks.addPoint(pid, mx, my, mx - mx0, my - my0);
}
sparksContainer.graphics.clear();
silks.render();
mx0 = mx;
my0 = my;
/* copy to bmd */
bmd.draw(silkContainer, null, null, BlendMode.ADD);
silkContainer.graphics.clear();
}
private function onMouseDown(e : MouseEvent) : void {
pressed = true;
pid = silks.add();
}
private function onMouseUp(e : MouseEvent) : void {
pressed = false;
if ((silks.slist[pid] != null) && !silks.slist[pid].completed)
{
silks.slist[pid].completed = true;
}
}
}
}
import flash.display.Shape;
import flash.utils.ByteArray;
internal class SilkRenderer
{
public var sparksContainer : Shape;
public var silkContainer : Shape;
public var slist : Vector.<Silk>;
public var time : int;
public var sparks : Sparks;
public function SilkRenderer(silkContainer : Shape, sparksContainer : Shape)
{
this.silkContainer = silkContainer;
this.sparksContainer = sparksContainer;
slist = new Vector.<Silk>();
sparks = new Sparks(256);
}
public function add() : uint
{
var slk : Silk = new Silk();
slist.push(slk);
return (slist.length - 1);
}
public function addPoint(id : uint, px : Number, py : Number, vx : Number, vy : Number) : void
{
var slk : Silk = this.slist[id];
if (slk != null)
{
slk.add2(px, py, vx, vy);
}
}
public function render() : int
{
for each (var slk : Silk in slist)
{
if (slk.alive) {
sparks.addFromSilk(slk);
var iter : uint = 4;
while (iter-- != 0) {
slk.render(silkContainer);
}
slk.age++;
}
}
sparks.render(sparksContainer);
return time++;
}
}
internal class PField
{
protected var numP : uint;
protected var start : int = 0;
protected var end : int = 0;
protected var plist : Vector.<Particle>;
protected var drawStart : Function;
protected var drawEnd : Function;
public function PField(numP : uint)
{
this.numP = (numP != 0) ? numP : 256;
plist = new Vector.<Particle>(this.numP, true);
}
public function getParticle() : Particle
{
return null;
}
public function render(shp : Shape) : void
{
for (; !(start == end || plist[start].alive);)
{
plist[start] = null;
start = inc(start);
}
var func : Function = function(p : Particle) : void
{
p.px = p.x;
p.py = p.y;
p.age++;
this['update'](p);
};
foreach(func);
drawAll(shp);
}
public function drawAll(shp : Shape) : void
{
if (((drawStart != null) && drawStart(shp), this.foreach(function(p : Particle) : void {
if (p.alive) this['draw'](p, shp);
}))) {
}
}
public function foreach(func : Function) : void
{
var n : int;
for ((n = this.start); (n != this.end);) {
func.call(this, this.plist[n]);
n = this.inc(n);
}
}
public function add(px : Number, py : Number) : Particle
{
var end : int = this.inc(this.end);
this.start == end && (this.start = this.inc(this.start));
var p : Particle = getParticle();
p.x = px;
p.y = py;
this.plist[this.end] = p;
this.end = end;
return p;
}
public function inc(a : int) : int
{
return (a + 1) % this.numP;
}
public function dec(a : int) : int
{
return (a - 1) % this.numP;
}
}
internal class Sparks extends PField {
function Sparks(numP : uint) {
super(numP);
}
override public function getParticle() : Particle {
var p : Particle = new Particle();
p.radius = 0.75;
p.vx = -0.1 + 0.2 * Math.random();
p.vy = -0.1 + 0.2 * Math.random();
p.dieAt = 64;
return p;
}
public function update(p : Particle) : void {
p.x += p.vx;
p.y += p.vy;
var lum : Number = (p.age / p.dieAt);
// p.a = (p.fadeIn == true) ? (p.maxA * Math.sin(3.141592653589793 * lum)) : lum;
p.a = 0.5 + 0.5 * lum;
p.alive = (p.age < p.dieAt);
}
public function draw(p : Particle, shp : Shape) : void {
if (p.alive) {
var col : uint = ((p.r & 0xFF) << 16) + ((p.g & 0xFF) << 8) + (p.b & 0xFF);
shp.graphics.beginFill(col, p.a);
shp.graphics.drawCircle(p.x, p.y, p.radius);
shp.graphics.endFill();
}
}
public function addFromSilk(a : Silk) : void {
var sparks : Sparks = this;
a.foreach(function(p : Particle) : void {
if (0.03 > Math.random()) {
p = sparks.add(p.x, p.y);
p.r = a.sparkR;
p.g = a.sparkG;
p.b = a.sparkB;
}
});
}
}
internal class Silk extends PField {
/* */
public const noiseOctaves : int = 8;
public const noiseFallout : Number = 0.65;
public const noiseScale : Number = 0.01;
public const mouseDamp : Number = 0.2;
/* */
public var colR : uint = 0x80;
public var colG : uint = 0x7E;
public var colB : uint = 0x78;
public var sparkR : uint = 0x80;
public var sparkG : uint = 0x7E;
public var sparkB : uint = 0x78;
public var opacity : Number = 0.07;
/* */
public var age : int = 0;
public var completed : Boolean = false;
public var alive : Boolean = true;
public var seed : Number = -(0.008 / 2) * Math.random();
public var perlin : PerlinNoise = new PerlinNoise(0);
/* */
private var p0 : Particle;
public function Silk() {
super(32);
drawStart = drawStartX;
drawEnd = drawEndX;
Noise.octaves = noiseOctaves;
Noise.fallout = noiseFallout;
}
override public function getParticle() : Particle {
var p : Particle = new Particle();
p.death = 128;
p.x = 0.0;
p.y = 0.0;
p.px = 0.0;
p.py = 0.0;
p.vmx = 0.0;
p.vmy = 0.0;
p.accx = 0.0;
p.accy = 0.0;
p.friction = 0.975;
p.mass = 1.0;
p.springLen = 0.0;
p.rigidity = 0.3;
p.radius = 0.75;
p.r = 0xFF;
p.g = 0xFF;
p.b = 0xFF;
p.vx = -0.1 + 0.2 * Math.random();
p.vy = -0.1 + 0.2 * Math.random();
return p;
}
public function add2(px : Number, py : Number, vx : Number, vy : Number) : Particle {
var f : Boolean = (this.start == this.end);
var p : Particle = super.add(px, py);
if (f == false) this.p0.next = p;
var damp : Number = this.mouseDamp;
p.vmx = vx * damp;
p.vmy = vy * damp;
return (this.p0 = p);
}
override public function render(a : Shape) : void {
super.render(a);
this.opacity -= 0.000005;
if ((this.completed == true) && (this.opacity < 0.0001)) {
this.alive = false;
}
}
public function update(p : Particle) : Boolean {
var ang : Number = 2 * (3.141592653589793 * 2) * Noise.gen(p.x * noiseScale, p.y * noiseScale, seed + 0.008 * age, perlin);
ang *= 2;
if (p.vmx != 0) p.vmx = 0.0001;
if (p.vmy != 0) p.vmy = 0.0001;
ang += (Math.atan2(p.vmx, p.vmy));
addAngleForce(p, ang + (3.141592653589793 / 2), 0.5);
addForce(p, p.vmx, p.vmy);
p.vmx *= 0.99;
p.vmy *= 0.99;
p.rigidity *= 0.999;
if (p.next != null) {
/* move */
p.x += (p.x - p.px) * p.friction + p.accx;
p.y += (p.y - p.py) * p.friction + p.accy;
p.accx = 0.0;
p.accy = 0.0;
/* constrain */
var dx : Number = p.next.x - p.x;
var dy : Number = p.next.y - p.y;
var d : Number = Math.sqrt(dx * dx + dy * dy);
d = 1 - (p.springLen / d);
dx = p.rigidity * dx * d;
dy = p.rigidity * dy * d;
this.addVelo(p, dx, dy);
if ((d > 0.001) && (p.next.next != null)) {
this.addVelo(p.next, -dx, -dy);
}
}
p.alive = (p.age < p.death);
return p.alive;
}
private function addForce(p : Particle, fx : Number, fy : Number) : void {
p.accx += fx / p.mass;
p.accy += fy / p.mass;
}
private function addAngleForce(p : Particle, fx : Number, fy : Number) : void {
fy /= p.mass;
p.accx += fy * Math.cos(fx);
p.accy += fy * Math.sin(fx);
}
private function addVelo(p : Particle, vx : Number, vy : Number) : void {
p.x += vx;
p.y += vy;
}
public function drawStartX(sh : Shape) : void {
sh.graphics.lineStyle(1.0, (((colR & 0xFF) << 16) + ((colG & 0xFF) << 8) + (colB & 0xFF)), opacity, false, 'none', 'none');
var p : Particle = plist[start];
if (p != null) sh.graphics.moveTo(p.x, p.y);
}
public function draw(p : Particle, sh : Shape) : void {
var pnxt : Particle = p.next;
if (pnxt != null) {
sh.graphics.curveTo(p.x, p.y, (p.x + pnxt.x) / 2, (p.y + pnxt.y) / 2);
}
}
public function drawEndX(a : Shape) : void {
}
}
internal class Particle {
public var next : Particle;
public var age : int = 0;
public var death : int = 64;
public var alive : Boolean = true;
public var px : Number = 0.0;
public var py : Number = 0.0;
public var x : Number = 0.0;
public var y : Number = 0.0;
public var vmx : Number = 0.0;
public var vmy : Number = 0.0;
public var accx : Number = 0.0;
public var accy : Number = 0.0;
public var friction : Number = 0.975;
public var mass : Number = 1.0;
public var springLen : Number = 0.0;
public var rigidity : Number = 0.3;
public var a : Number = 0.75;
public var r : uint = 0xFF;
public var g : uint = 0xFF;
public var b : uint = 0xFF;
public var radius : Number = 0.75;
public var vx : Number = -1 + 2 * Math.random();
public var vy : Number = -1 + 1 * Math.random();
public var dieAt : int = 25;
}
internal class PerlinNoise {
private var perm : ByteArray;
function PerlinNoise(seed : Number) {
var rnd : Marsaglia = (!isNaN(seed) ? new Marsaglia(seed, 0) : Marsaglia.createRandomized());
var i : int;
var j : int;
perm = new ByteArray();
perm.length = 512;
for (i = 0; i < 256; ++i) {
perm[i] = i;
}
for (i = 0; i < 256; ++i) {
var t : int = perm[j = rnd.nextInt() & 0xFF];
perm[j] = perm[i];
perm[i] = t;
}
for (i = 0; i < 256; ++i) {
perm[i + 256] = perm[i];
}
}
public function noise3d(x : Number, y : Number, z : Number) : Number {
var X : int = (x | 0) & 255, Y : int = (y | 0) & 255, Z : int = (z | 0) & 255;
x -= (x | 0);
y -= (y | 0);
z -= (z | 0);
var fx : Number = (3 - 2 * x) * x * x, fy : Number = (3 - 2 * y) * y * y, fz : Number = (3 - 2 * z) * z * z;
var p0 : int = perm[X] + Y, p00 : int = perm[p0] + Z, p01 : int = perm[p0 + 1] + Z, p1 : int = perm[X + 1] + Y, p10 : int = perm[p1] + Z, p11 : int = perm[p1 + 1] + Z;
return lerp(fz, lerp(fy, lerp(fx, grad3d(perm[p00], x, y, z), grad3d(perm[p10], x - 1, y, z)), lerp(fx, grad3d(perm[p01], x, y - 1, z), grad3d(perm[p11], x - 1, y - 1, z))), lerp(fy, lerp(fx, grad3d(perm[p00 + 1], x, y, z - 1), grad3d(perm[p10 + 1], x - 1, y, z - 1)), lerp(fx, grad3d(perm[p01 + 1], x, y - 1, z - 1), grad3d(perm[p11 + 1], x - 1, y - 1, z - 1))));
}
public function noise2d(x : Number, y : Number) : Number {
var X : int = Math.floor(x) & 255;
var Y : int = Math.floor(y) & 255;
x -= Math.floor(x);
y -= Math.floor(y);
var fx : Number = (3 - 2 * x) * x * x, fy : Number = (3 - 2 * y) * y * y;
var p0 : Number = perm[X] + Y, p1 : Number = perm[X + 1] + Y;
return lerp(fy, lerp(fx, grad2d(perm[p0], x, y), grad2d(perm[p1], x - 1, y)), lerp(fx, grad2d(perm[p0 + 1], x, y - 1), grad2d(perm[p1 + 1], x - 1, y - 1)));
}
public function noise1d(x : Number) : Number {
var X : int = Math.floor(x) & 255;
x -= Math.floor(x);
var fx : Number = (3 - 2 * x) * x * x;
return lerp(fx, grad1d(perm[X], x), grad1d(perm[X + 1], x - 1));
}
public function grad3d(i : int, x : Number, y : Number, z : Number) : Number {
var h : int = i & 15;
switch (h & 0xF) {
case 0x0:
return x + y;
case 0x1:
return -x + y;
case 0x2:
return x - y;
case 0x3:
return -x - y;
case 0x4:
return x + z;
case 0x5:
return -x + z;
case 0x6:
return x - z;
case 0x7:
return -x - z;
case 0x8:
return y + z;
case 0x9:
return -y + z;
case 0xA:
return y - z;
case 0xB:
return -y - z;
case 0xC:
return y + x;
case 0xD:
return -y + z;
case 0xE:
return y - x;
case 0xF:
return -y - z;
}
return 0;
}
public function grad2d(i : int, x : Number, y : Number) : Number {
var v : Number = (i & 1) == 0 ? x : y;
return (i & 2) == 0 ? -v : v;
}
public function grad1d(i : int, x : Number) : Number {
return (i & 1) == 0 ? -x : x;
}
public function lerp(t : Number, a : Number, b : Number) : Number {
return a + t * (b - a);
}
}
internal class Marsaglia {
private var z : int;
private var w : int;
public function Marsaglia(i1 : Number, i2 : Number) {
z = i1 || 362436069;
w = i2 || 521288629;
}
public function nextInt() : int {
z = (36969 * (z & 65535) + (z >>> 16)) & 0xFFFFFFFF;
w = (18000 * (w & 65535) + (w >>> 16)) & 0xFFFFFFFF;
return (((z & 0xFFFF) << 16) | (w & 0xFFFF)) & 0xFFFFFFFF;
}
public function nextDouble() : Number {
var i : Number = nextInt() / 4294967296.0;
return i < 0 ? 1 + i : i;
}
public static function createRandomized() : Marsaglia {
var now : int = new Date().getTime();
return new Marsaglia((now / 60000) & 0xFFFFFFFF, now & 0xFFFFFFFF);
}
}
internal class Noise {
public static var octaves : int = 4;
public static var fallout : Number = 0.5;
public static var seed : Number = 2222;
public static function gen(x : Number, y : Number, z : Number, generator : PerlinNoise) : Number {
var effect : Number = 1;
var k : Number = 1;
var sum : Number = 0;
for (var i : int = 0; i < octaves; ++i) {
effect *= fallout;
sum += effect * (1 + generator.noise3d(k * x, k * y, k * z)) / 2;
k *= 2;
}
return sum;
}
}