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

forked from: CirclesLoveLines Step 6

CirclesLoveLines step 5
* @Revision
*              - Lets keep the circle on the line!
* 		- Lets map the collision normal!
*              - Lets check for collision of circleX on line AB!
*              - Lets project pointX along line AB!
*              - Lets Make a point X that is the mouse!
* 		- Lets project a line segment from lineA to circlaA!
* 
* @author Mario Gonzalez
* @see http://onedayitwillmake.com/
* @note: This series of experiments is being created because.
Get Adobe Flash player
by onedayitwillmake 14 May 2009
/**
 * Copyright onedayitwillmake ( http://wonderfl.net/user/onedayitwillmake )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/slf7
 */

// forked from onedayitwillmake's Step 5
// forked from onedayitwillmake's forked from: forked from: forked from: forked from: forked from: CirclesLoveLines step 1
// forked from onedayitwillmake'sforked from: forked from: forked from: CirclesLoveLines step 1
// forked from onedayitwillmake'sforked from: forked from: forked from: CirclesLoveLines step 1
/**
 * CirclesLoveLines step 5
 * @Revision
 *              - Lets keep the circle on the line!
 * 		- Lets map the collision normal!
 *              - Lets check for collision of circleX on line AB!
 *              - Lets project pointX along line AB!
 *              - Lets Make a point X that is the mouse!
 * 		- Lets project a line segment from lineA to circlaA!
 * 
 * @author Mario Gonzalez
 * @see http://onedayitwillmake.com/
 * @note: This series of experiments is being created because.
 */
package
{
		
    import flash.display.GradientType;
    import flash.display.SpreadMethod;
    import flash.display.Sprite;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.geom.Matrix;
	
	[SWF(frameRate="60", width="465", height="465", backgroundColor="#00ffcc")]
	
    public class CircleLineSegmentTest extends Sprite
    {
    	private var A	:Vector2D; // Point A
    	private var B	:Vector2D; // Point B
    	//private var V	:Vector2D; // Vector AB
    	
    	private var X	:Vector2D; // Point X
    	//private var W	:Vector2D; // Vector AX
    	
    	//Graphical representation of elements above
    	private var lineAB		:Line	// Line segment between points AB
    	
    	private var circleX		:Circle	// Circle at Point X 
    	
    	//Visual display of stuff
    	private var lineAX		:Line	// Line segment between points AX
    	private var circleXCollisionNormal	:Circle // Point X projected along LineAB 
    	
    	public function CircleLineSegmentTest():void
    	{
    		stage.scaleMode = StageScaleMode.NO_SCALE;
    		addChild(createBG(0x500149, 0x000040));
    		
    		A = new Vector2D(Math.random() * stage.stageWidth + 20 - 10, Math.random() * stage.stageHeight + 20 - 10);
    		B = new Vector2D(Math.random() * stage.stageWidth + 20 - 10, Math.random() * stage.stageHeight + 10 - 10);
    		lineAB = new Line(A, B, 0xff0000);
    		addChild(lineAB);
    		
    		lineAX = new Line(new Vector2D(), new Vector2D, 0xffffff);
    		addChild(lineAX);

			// Create circleXonAB
			circleX = new Circle(new Vector2D(), 50);
			addChild(circleX);
			
			circleXCollisionNormal = new Circle(new Vector2D(), 5, 0xEC7553);
			addChild(circleXCollisionNormal);
			
    		addEventListener(Event.ENTER_FRAME, loop);
    	}
    	
    	private function loop(e:Event):void
    	{
    		//Move the circle to where the mouse is
    		var mouseVector:Vector2D = new Vector2D(stage.mouseX, stage.mouseY);
    		var p:Vector2D = findClosestPointOnLineSegment(mouseVector, lineAB);
			
			//Place the circle on the line if it's touching it
			if(p.distanceRough(mouseVector) <= circleX._radius * circleX._radius)
			{
				
				lineAX.A = p;
				lineAX.B = circleX._center;
				lineAX._isDirty = true;
				
				circleX._center = mouseVector;
				
				var angle:Number = Math.atan2(circleX._center.y - p.y, circleX._center.x - p.x);
				var nx:Number = p.x + Math.cos(angle) * (circleX._radius);
				var ny:Number = p.y + Math.sin(angle) * (circleX._radius);
				
				circleXCollisionNormal.visible = true;
				lineAX.visible = true;
				
				circleX._drawPoint.x = circleXCollisionNormal.x = nx;
				circleX._drawPoint.y = circleXCollisionNormal.y = ny;
			}
			else
			{
				circleXCollisionNormal.visible = false;
				lineAX.visible = false;
				circleX._center = circleX._drawPoint = mouseVector;
			}
			
			circleX._isDirty = true;
    	}
    	
    	/**
    	 * Find T.
    	 * T is Point X (the mouse position), projected along Line AB
    	 * T is a number between -Infinity and Infinity where 0.0 and 1.0 represent A and B respectively.
    	 * Being the case, normally you only want T, clamped to 0.0 - 1.0.
    	 */
    	private function findClosestPointOnLineSegment(X:Vector2D, line:Line):Vector2D
    	{
    		X = new Vector2D(stage.mouseX, stage.mouseY);
    		var W:Vector2D = X.minus(line.A);    		
    		var t:Number = W.dot(line.V) / line.V.dot(line.V);
    		
    		return A.plus(line.V.times(clamp(0,1,t)))
    	}
    	
    	/**
    	 * Creates the gradient background used in the experiment
    	 */
    	private function createBG(topColor:uint, bottomColor:uint):Sprite
		{ 
			var matr:Matrix = new Matrix();
				matr.createGradientBox(465, 465, Math.PI / 2, 0, 0);
			
			var bg:Sprite = new Sprite();
			bg.graphics.beginGradientFill
			(
				GradientType.LINEAR, 
				[topColor, bottomColor], //colors
				[1, 1], //alphas
				[0, 255], //ratios
				matr, //matrix
				SpreadMethod.PAD
			);	
			
			bg.graphics.drawRect(0, 0, 465, 465);
			bg.graphics.endFill();
			
			return bg;
		}
    	
    	/**
    	 * Clamps a numerical value between, min and max.
    	 * @param min	Lowest value
    	 * @param max	Highest value
    	 * @param val	Test against
    	 * @return 
    	 * 
    	 */    	
    	public static function clamp(min:Number, max:Number, val:Number):Number
    	{
    		 return Math.max(min, Math.min(max, val))
    	}
    }
}



internal class Line extends Shape
{
	public var A:Vector2D, B:Vector2D; //A |----| B
	public var V:Vector2D; // A |-->--| B - V is the direction of line AB
	
	//Draw
	public var _color		:uint = 0x666666;
	public var __isDirty	:Boolean = false;
	public function Line(a:Vector2D, b:Vector2D, color:uint = 0x666666):void
	{
		A = a;
		B = b;
		
		V  = B.minus(A);
		_color = color;
		_isDirty = true;
	}
	
	public function draw():void
	{
		resetGraphics();
		graphics.moveTo(A.x, A.y);
		graphics.lineTo(B.x, B.y);
	}
	
	public function resetGraphics():void
	{
		graphics.clear();
		graphics.lineStyle(2, _color, 0.75);
	}
	
	public function get _isDirty():Boolean { return __isDirty };
	public function set _isDirty(value:Boolean):void
	{
		__isDirty = value;
		draw();
	}
}

internal class Circle extends Sprite
{
	public var _center		:Vector2D; //Where we REALLY are
	public var _drawPoint	:Vector2D; //Where we draw ourselves
	
	public var _radius		:int;
	
	//Draw
	private var __isDirty	:Boolean = false;
	
	public function Circle(center:Vector2D, radius:int, color:uint = 0xB8F1FE):void
	{
		_center = center;
		_drawPoint = center;
		_radius = radius;

		//Draw
		graphics.beginFill(color, 0.5)
			graphics.drawCircle(0, 0, _radius * 0.25);
			graphics.drawCircle(0, 0, _radius * 0.8);
			graphics.drawCircle(0, 0, _radius);
		graphics.endFill();
	}
		
	public function set _isDirty(value:Boolean):void
	{
		if(value == true)
		{
			x  = _drawPoint.x;
			y = _drawPoint.y
		}
	}
}

import flash.geom.Point;
import flash.display.Shape;
import flash.display.Sprite;

internal class Vector2D
{
	public var x:Number, y:Number
	public function Vector2D(x1:Number = 0, y1:Number = 0):void
	{
		x = x1;
		y = y1;
	}
	
	public function minus(from:Vector2D):Vector2D
	{
		return new Vector2D(x - from.x, y - from.y);
	}
	
	public function plus(from:Vector2D):Vector2D
	{
		return new Vector2D(x + from.x, y + from.y);
	}
	
	public function times(z:Number):Vector2D
	{
		return new Vector2D(x * z, y * z);
	}
	
	//proj(w,v) = dot(w,v) / dot(v,v)
	public function project(from:Vector2D):Number
	{
		return dot(from) / from.dot(from);
	}
	
	// w.x * v.x + w.y * v.y
	public function dot(from:Vector2D):Number
	{
		return x * from.x + y * from.y;
	}
	
	public function get length():Number
	{
		return Math.sqrt((x * x) + (y * y));
	}
	
	public function distance(from:Vector2D):Number
	{
		return Math.sqrt((x - from.x) * (x - from.x) + (y - from.y) * (y - from.y))
	}
	
	public function distanceRough(from:Vector2D):Number
	{
		return (x - from.x) * (x - from.x) + (y - from.y) * (y - from.y);
	}

}