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

Jelly Ball

Get Adobe Flash player
by gyuque 17 Jan 2009
package
{
	import flash.display.*;
	import flash.geom.*;
	import flash.events.*;

    [SWF(width="465", height="465", backgroundColor="0xffe0ce", frameRate="31")]
	public class JBall extends Sprite
	{
		private static const N:int = 29;
		private static const R:int = 50;

		private var mNodes:Array = [];
		private var mCenter:Point = new Point();
		private var mGVec:Point = new Point();
		private var mField:Sprite = new Sprite();
		private var mBallLayer:Sprite = new Sprite();

		private var mBoxHW:int = 180;
		private var mBoxHH:int = 180;

		private var mFAngle:Number = 0;


		function JBall()
		{
			generateNodes(N);
			addChild(mField);
			mField.addChild(mBallLayer);
			mField.x = 232;
			mField.y = 232;
			var g:Graphics = mField.graphics;
			g.beginFill(0xffffff);
			g.drawRect(-mBoxHW, -mBoxHH, 2*mBoxHW, 2*mBoxHH);

			mCenter.x = 0;
			mCenter.y = 0;

			var i:int, nd:JNode;

			var pt:Point = new Point();
			for (i = 0;i < N;i++)
			{
				nd = JNode(mNodes[i]);
				generateRoundPos(nd.theta, pt);

				nd.x = pt.x;
				nd.y = pt.y;
			}

			addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}

		private function onEnterFrame(e:Event):void
		{
			var mx:Number = (mouseX - 232) * 0.0003;

			const DPI:Number = Math.PI*2;
			mFAngle += mx;
			if (mFAngle < 0) mFAngle += DPI;
			else if (mFAngle > DPI) mFAngle -= DPI;

			setGVec(mFAngle);

			tick();
			move();
			draw();
		}

		private function setGVec(a:Number):void
		{
			mGVec.y = Math.cos(a) * .4;
			mGVec.x = Math.sin(a) * .4;
			mField.rotation = a * 180 / Math.PI;
		}

		private function generateNodes(n:int):void
		{
			var i:int, a:Number, nd:JNode;

			for (i = 0;i < n;i++)
			{
				nd = new JNode();

				a = Math.PI * 2.0 * Number(i)/Number(n);
				nd.theta = a;
				mField.addChild(nd);
				mNodes.push(nd);
			}
		}

		private function generateRoundPos(a:Number, outpt:Point):void
		{
			outpt.x = mCenter.x + Math.sin(a) * R;
			outpt.y = mCenter.y - Math.cos(a) * R;
		}

		private static const be:Number = 0.4;
		private function tick():void
		{
			var i:int, nd:JNode;
			var nxt:Number;

			calcCenter();

			for (i = 0;i < N;i++)
			{
				nd = mNodes[i];
				nd.v.x *= 0.98;
				nd.v.y *= 0.98;
			}

			for (i = 0;i < N;i++)
			{
				nd = mNodes[i];

				nd.F.x *= -0.2;
				nd.F.y *= -0.2;
				addVec(nd.v, nd.F);

				nd.F.x = 0;
				nd.F.y = 0;

				addVec(nd.v, mGVec);
				applyInternalForce(nd);
				addVec(nd.v, nd.F);

				if (nd.v.y > 0) {
					nxt = nd.y + nd.v.y;
					if (nxt > mBoxHH) {
						nd.nextV.y = -nd.v.y * be;
						nd.v.y = mBoxHH - nd.y;
					}
				} else {
					nxt = nd.y + nd.v.y;
					if (nxt < -mBoxHH) {
						nd.nextV.y = -nd.v.y * be;
						nd.v.y = -mBoxHH - nd.y;
					}
				}

				if (nd.v.x > 0) {
					nxt = nd.x + nd.v.x;
					if (nxt > mBoxHW) {
						nd.nextV.x = -nd.v.x * be;
						nd.v.x = mBoxHW - nd.x;
					}
				} else {
					nxt = nd.x + nd.v.x;
					if (nxt < -mBoxHW) {
						nd.nextV.x = -nd.v.x * be;
						nd.v.x = -mBoxHW - nd.x;
					}
				}
			}
		}

		private function move():void
		{
			var i:int, nd:JNode;

			for (i = 0;i < N;i++)
			{
				nd = mNodes[i];
				nd.x += nd.v.x;
				nd.y += nd.v.y;

				if (!isNaN(nd.nextV.x)) {
					nd.v.x = nd.nextV.x;
					nd.nextV.x = NaN;
				}

				if (!isNaN(nd.nextV.y)) {
					nd.v.y = nd.nextV.y;
					nd.nextV.y = NaN;
				}

				applyInternalForce(nd);
			}
		}

		private function draw():void
		{
			var g:Graphics = mBallLayer.graphics;
			g.clear();

			g.beginFill(0xff7766);
			for (var i:int = 0;i < N;i++)
			{
				var nd:JNode = mNodes[i];
				if (i == 0)
					g.moveTo(nd.x, nd.y);
				else
					g.lineTo(nd.x, nd.y);
			}
			g.endFill();
		}

		private static function addVec(v0:Point, v:Point):void
		{
			v0.x += v.x;
			v0.y += v.y;
		}

		private function applyInternalForce(nd:JNode):void
		{
			var p:Point = new Point();
			generateRoundPos(nd.theta, p);
			var vx:Number = (p.x-(nd.x+nd.v.x*0.1));
			var vy:Number = (p.y-(nd.y+nd.v.y*0.1));

//			var e:Number = 1.0 / (Math.sqrt(vx*vx + vy*vy)*0.01 + 1.0);
//			if (e > 1) e = 1;

			var e:Number = 0.19;

			vx *= e;
			vy *= e;

			var nrm:Number = Math.sqrt(vx*vx + vy*vy);
			if (nrm > 5) {
				vx *= 5 / nrm;
				vy *= 5 / nrm;
			}

			nd.F.x += vx;
			nd.F.y += vy;
		}

		private function calcCenter():void
		{
			var cx:Number = 0;
			var cy:Number = 0;

			var i:int, nd:JNode;

			for (i = 0;i < N;i++)
			{
				nd = mNodes[i];
				cx += nd.x;
				cy += nd.y;
			}

			mCenter.x = cx / Number(N);
			mCenter.y = cy / Number(N);
		}
	}
}

class JNode extends flash.display.Sprite
{
	import flash.display.*;
	import flash.geom.*;

	public var theta:Number;
	public var v:Point = new Point(0, 0);
	public var F:Point = new Point(0, 0);
	public var nextV:Point = new Point(NaN, NaN);

	function JNode()
	{
		var g:Graphics = graphics;
		g.beginFill(0xff7766);
		g.drawCircle(0, 0, 3);
	}
}