In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Verlet Circle / Sodaplay

A flexible structure constructed with Verlet integration that reminds me of Sodaplay, which was my favorite site when I started to learn visual coding.
http://sodaplay.com/
Get Adobe Flash player
by k__ 05 Jan 2011
/**
 * Copyright k__ ( http://wonderfl.net/user/k__ )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/lxzl
 */

package {
	import flash.display.*;
	import flash.events.*;
	import flash.geom.Rectangle;

	public class Main extends Sprite {
		private var points:Vector.<VerletPoint>;
		private var sticks:Vector.<VerletStick>;
		private var rect:Rectangle;
		private var acc:uint=1;
		private var len:uint=20;
		private var bDrag:Boolean;
		private var dIndex:uint;
		
		public function Main() {
			points=new Vector.<VerletPoint>;
			sticks=new Vector.<VerletStick>;
			rect=new Rectangle(0,0,stage.stageWidth,stage.stageHeight);
			
			for (var i:uint = 0; i < len; i ++) {
				var theta:Number = Math.PI * 2 / len * i;
				points.push(new VerletPoint(Math.cos(theta) * 100 + stage.stageWidth/2, Math.sin(theta) * 100 + stage.stageHeight / 2));
				
				points[i].y += 4;
			}
			
			for (i = 0; i < len; i ++) {
				sticks.push(new VerletStick(points[i], points[(i + 1) % len]));
				sticks.push(new VerletStick(points[i], points[(i + 8) % len]));
			}
			
			addEventListener(Event.ENTER_FRAME, h_enterFrame);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, h_mouseDown);
			stage.addEventListener(MouseEvent.MOUSE_UP, h_mouseUp);
		}

		private function h_enterFrame(evt:Event):void {
			var i:uint,j:uint;
			for (i = 0; i < points.length; i ++) {
				points[i].update();
			}
			for (i = 0; i < points.length; i ++) {
				for (j = 0; j < acc; j ++) {
					points[i].constrain(rect);
				}
			}
			for (i = 0; i < sticks.length; i ++) {
				for (j = 0; j < acc; j ++) {
					sticks[i].update();
				}
			}

			if (bDrag) {
				points[dIndex].x = mouseX;
				points[dIndex].y = mouseY;
			}

			graphics.clear();
			
			for (i = 0; i < points.length; i ++) {
				if (!bDrag) {
					var dx:Number = points[i].x - mouseX;
					var dy:Number = points[i].y - mouseY;
					if (dx * dx + dy * dy < 200) {
						points[i].highlight(graphics);
					}
				}
				points[i].render(graphics);
			}

			for (i = 0; i < sticks.length; i ++) {
				sticks[i].render(graphics);
			}
		}
		
		private function h_mouseDown(evt:MouseEvent):void {
			for (var i:uint = 0; i < points.length; i ++) {
				var dx:Number = points[i].x - mouseX;
				var dy:Number = points[i].y - mouseY;
				if (dx * dx + dy * dy < 200) {
					dIndex = i;
					bDrag = true;
				}
			}
		}
		
		private function h_mouseUp(evt:MouseEvent):void {
			bDrag = false;
		}

	}
}

import flash.display.Graphics;
import flash.geom.Rectangle;

class VerletPoint {
	public var x:Number;
	public var y:Number;
	private var ox:Number;
	private var oy:Number;

	public function VerletPoint(x:Number, y:Number) {
		setPos(x, y);
	}
	public function update():void {
		var tx:Number=x;
		var ty:Number=y;
		x+=vx;
		y+=vy;
		ox=tx;
		oy=ty;
	}
	public function setPos(x:Number, y:Number):void {
		this.x=ox=x;
		this.y=oy=y;
	}
	public function constrain(rect:Rectangle):void {
		x=Math.max(rect.left,Math.min(rect.right,x));
		y=Math.max(rect.top,Math.min(rect.bottom,y));
	}
	public function set vx(n:Number):void {
		ox=x-n;
	}
	public function set vy(n:Number):void {
		oy=y-n;
	}
	public function get vx():Number {
		return x - ox;
	}
	public function get vy():Number {
		return y - oy;
	}
	public function render(g:Graphics):void {
		g.beginFill(0xFF6600, 0.5);
		g.drawCircle(x, y, 3);
		g.endFill();
	}
	public function highlight(g:Graphics):void {
		g.beginFill(0xFF66FF, 0.5);
		g.drawCircle(x, y, 5);
		g.endFill();
	}
}

class VerletStick extends Array {
	private var pa:VerletPoint;
	private var pb:VerletPoint;
	private var len:Number;

	public function VerletStick(pa:VerletPoint, pb:VerletPoint, len:Number = -1) {
		this.pa=pa;
		this.pb=pb;
		if (len==-1) {
			var dx:Number=pa.x-pb.x;
			var dy:Number=pa.y-pb.y;
			this.len=Math.sqrt(dx*dx+dy*dy);
		} else {
			this.len=len;
		}
	}

	public function update():void {
		var dx:Number=pb.x-pa.x;
		var dy:Number=pb.y-pa.y;
		var d:Number=Math.sqrt(dx*dx+dy*dy);
		var diff:Number=len-d;
		var offsetX:Number = (diff * dx / d) / 2;
		var offsetY:Number = (diff * dy / d) / 2;
		pa.x-=offsetX;
		pa.y-=offsetY;
		pb.x+=offsetX;
		pb.y+=offsetY;

	}
	public function render(g:Graphics):void {
		g.lineStyle(0,0xFF6600,0.5);
		g.moveTo(pa.x, pa.y);
		g.lineTo(pb.x, pb.y);
	}
}