Bounce
package {
import flash.display.*;
import flash.events.Event;
[SWF(width="350", height="350", backgroundColor="#222222")]
public class Program extends Sprite {
private var demo:Demo;
public function Program() {
addEventListener(Event.ENTER_FRAME, onEnterFrame);
demo = new Demo(this);
}
public function onEnterFrame(ev:Event):void { demo.frame(); }
}
}
import flash.display.*;
import flash.filters.*;
class Demo {
private var screen:Sprite;
private var shape:Shape = new Shape();
private const NPOINTS:int = 32;
private var pack:Array = new Array();
private var packp:Array = new Array();
private var force:Array = new Array();
private var ph:Number = 0;
public function Demo(screen:Sprite) {
var i:int;
this.screen = screen;
screen.addChild(shape);
for (i = 0; i < NPOINTS; i++) {
pack[i] = new Vec2(00, 80.0 + (300 - 80) * i / NPOINTS);
packp[i] = pack[i].copy();
force[i] = new Vec2();
}
screen.filters = [new GlowFilter(0xffbb55, 1.0, 40, 40)];
}
public function frame():void {
var i:int;
var g:Graphics = shape.graphics;
g.clear();
g.beginFill(0x00ffe594);
g.moveTo(pack[0].x, 0);
for (i = 0; i < NPOINTS; i++)
g.lineTo(pack[i].x, pack[i].y);
g.endFill();
var packtmp:Array;
var c:Vec2 = new Vec2();
var vv1:Vec2 = new Vec2();
var vv2:Vec2 = new Vec2();
var v:Vec2 = new Vec2();
var n:Vec2 = new Vec2();
const nl:Number = 1.0 * Math.PI * 23 / NPOINTS;
for (var ss:int = 0; ss < 5; ss++) {
ph += 0.020 + Math.random() * 0.01 + 0.015 * Math.sin(ph / 5);
pack[0].y = 60 - 80 * Math.pow(Math.sin(ph), 2);
pack[NPOINTS - 1].y = 320 - 80 * Math.pow(Math.sin(ph), 2);
for (i = 0; i < NPOINTS; i++)
force[i].zero();
// caluculate volume
var area:Number = 0;
c = pack[0];
for (i = 0; i < NPOINTS - 1; i++) {
pack[i].copyTo(vv1); vv1.sub(c);
pack[i + 1].copyTo(vv2); vv2.sub(c);
area += vv1.x * vv2.y - vv1.y * vv2.x;
}
area = (area - 90000) * -0.001;
// force
const aaa:Vec2 = new Vec2(-2, 0);
for (i = 0; i < NPOINTS - 1; i++) {
pack[i + 1].copyTo(v);
v.sub(pack[i]);
v.copyTo(n);
v.mul(350 * (v.length() - nl) / v.length());
force[i].add(v);
force[i].add(new Vec2(0, Math.abs(n.x * 11)));
force[i].x += n.y * area;
force[i].y -= n.x * area;
force[i + 1].sub(v);
force[i+1].add(new Vec2(0, Math.abs(n.x * 11)));
force[i+1].x += n.y * area;
force[i+1].y -= n.x * area;
}
// boundary
force[0].zero();
force[NPOINTS - 1].zero();
// update
for (i = 0; i < NPOINTS; i++) {
force[i].mul(0.001);
pack[i].copyTo(n);
n.sub(packp[i]);
n.mul(0.04);
packp[i].add(n);
packp[i].mul(-1.000);
packp[i].add(pack[i]);
packp[i].add(pack[i]);
packp[i].add(force[i]);
}
packtmp = pack; pack = packp; packp = packtmp;
}
}
}
// shit
class Vec2 {
public var x:Number;
public var y:Number;
public function Vec2(x:Number = 0, y:Number = 0) {
this.x = x;
this.y = y;
}
public function copy():Vec2 {
return new Vec2(this.x, this.y);
}
public function zero():void {
x = y = 0.0;
}
public function copyTo(v:Vec2):void {
v.x = x;
v.y = y;
}
public function add(v:Vec2):void {
this.x += v.x;
this.y += v.y;
}
public function sub(v:Vec2):void {
this.x -= v.x;
this.y -= v.y;
}
public function mul(a:Number):void {
this.x *= a;
this.y *= a;
}
public function dot(v:Vec2):Number {
return this.x * v.x; + this.y * y;
}
public function length():Number {
return Math.sqrt(x * x + y * y);
}
public function lengthSq():Number {
return x * x + y * y;
}
}