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

DivideLine

マウスで囲った線が独立して動くよ!
双方向リスト自作久しぶりでちゃんと出来てるかなぁ
Get Adobe Flash player
by okoi 02 Apr 2010
    Embed
/**
 * Copyright okoi ( http://wonderfl.net/user/okoi )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/pH5b
 */

//
//	マウスで囲った線が独立して動くよ!
//
//	双方向リスト自作久しぶりでちゃんと出来てるかなぁ
//
package 
{
	import flash.display.Sprite;
	import flash.events.Event;
	
	/**
	 * @author okoi
	 */
	public class Main extends Sprite 
	{
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point
			graphics.beginFill(0x000000);
			graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
			graphics.endFill();
			
			
			addChild( new Canvas() );
		}
	}
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.GlowFilter;
import flash.geom.Matrix;
class Canvas extends Sprite {
	
	private	var drawFlag:Boolean = false;
	private var lineObj:PathObject;
	private	var floatObj:Array = new Array();
	private var floatMC:Sprite = new Sprite();
	private var lineMC:Sprite = new Sprite();
	
	private	var prevMX:int;
	private var prevMY:int;
	
	public	function Canvas()
	{
		super();
		if (stage) Init();
		else addEventListener(Event.ADDED_TO_STAGE, Init);
	}
	
	public	function Init(e:Event=null):void 
	{
		removeEventListener(Event.ADDED_TO_STAGE, Init);
	//	this.filters = [new GlowFilter(0xFFFFFF, 0.5, 10, 10, 4, 10, false )];
		
		addChild( floatMC );
		addChild( lineMC );
		
		drawFlag = false;
		lineObj = new PathObject();
		
		this.mouseEnabled = false;
		this.mouseChildren = false;
		
		addEventListener(Event.ENTER_FRAME, Update);
		stage.addEventListener(MouseEvent.MOUSE_DOWN, MouseDown);
		stage.addEventListener(MouseEvent.MOUSE_UP, MouseUp);
		stage.addEventListener(MouseEvent.MOUSE_OUT, MouseUp);
		
		prevMX = stage.mouseX;
		prevMY = stage.mouseY;
	}
	
	private function Update(e:Event):void
	{
		var p:PathList;
		
		if ( drawFlag )
		{
			if ( stage.mouseX != prevMX || stage.mouseY != prevMY )
			{		
				var path:PathList = new PathList( stage.mouseX, stage.mouseY );
				lineObj.Push( path );
								
				//	ライン交差判定。重なったラインの部分でリストを切り離す
				//	最後に引いた線を基準に考える
				//	直前のラインとは判定しない
				var v1E:PathList = lineObj.last;
				var v1S:PathList = v1E.prev;
				if ( v1S != lineObj.end && v1S != v1E )
				{
					for ( p = lineObj.first; p != lineObj.end && p.next != lineObj.end && p.next != v1S; p = p.next )
					{
						var v2S:PathList = p;
						var v2E:PathList = p.next;
						if ( ChkHitLineToLine( v1S, v1E, v2S, v2E ) )
						{
							var obj:FloatObject = FloatObject.Create( lineObj.Cut( v2E, v1S ) );
							if ( obj != null )
							{
							//	floatObj.push( obj );
								floatMC.addChild( obj );
							}
							break;
						}
					}
				}
				prevMX = stage.mouseX;
				prevMY = stage.mouseY;
			}
		}
		
		//	パスリストの中身を描画
		lineMC.graphics.clear();
		lineMC.graphics.lineStyle(2, 0xFFFFFF);
		for ( p = lineObj.first; p != lineObj.end; p = p.next )
		{
			if ( p == lineObj.first )	lineMC.graphics.moveTo( p.x, p.y );
			else						lineMC.graphics.lineTo( p.x, p.y );
		}
	}
	private	function MouseDown(e:MouseEvent):void 
	{
		drawFlag = true;
	}
	private	function MouseUp(e:MouseEvent):void 
	{
		drawFlag = false;
		//	離したらライン削除
		lineObj = new PathObject();
	}
}

/**
 * 浮遊物オブジェクトクラス
 * とりあえずでSpriteクラス継承パターンで
 */
class FloatObject extends Sprite {
	
	private var speed:Number = 1;
	private var rot:Number = 0;
	private var mX:Number = 0;
	private var mY:Number = 0;
	public var posX:Number = 0;
	public var posY:Number = 0;
	
	public	function FloatObject():void 
	{
		super();
		addEventListener(Event.ADDED_TO_STAGE, Init );
	}
	
	/**
	 * FloatObjectを生成する、引数のデータ的に不整合がある場合nullを返す
	 * @param	list
	 * @return
	 */
	public	static	function Create(list:PathObject) : FloatObject 
	{
		var p:PathList;
		
		//	中心点位置計算
		var	minX:Number;
		var maxX:Number;
		var minY:Number;
		var maxY:Number;
		var ct:int = 0;
		for ( p = list.first; p != list.end; p = p.next )
		{
			if ( ct == 0 )
			{
				minX = maxX = p.x;
				minY = maxY = p.y;
			}else
			{
				if ( p.x > maxX )	maxX = p.x;
				if ( p.x < minX )	minX = p.x;
				if ( p.y > maxY )	maxY = p.y;
				if ( p.y < minY )	minY = p.y;
			}
			ct++;
		}
		if ( (maxX - minX) == 0 || (maxY - minY) == 0 )	return	null;
		
		var cX:Number = (minX + maxX) / 2;
		var cY:Number = (minY + maxY) / 2;
		
		//----------------------------------------------------------
		//	描いてしまう
		var shape:Shape = new Shape();
		var g:Graphics = shape.graphics;
		
		var r:int = int(Math.random() * 3);
		if( r == 0 ){	g.beginFill(0xAAAAAA);	shape.filters = [new GlowFilter(0xFFFFFF, 0.7, 10, 10, 4, 10, true )];	}
		if( r == 1 ){	g.beginFill(0xFFAAAA);	shape.filters = [new GlowFilter(0xFF5555, 0.7, 10, 10, 4, 10, true )];	}
		if( r == 2 ){	g.beginFill(0xAAAAFF);	shape.filters = [new GlowFilter(0x5555FF, 0.7, 10, 10, 4, 10, true )];	}
		
		for ( p = list.first; p != list.end; p = p.next )
		{
			var xx:Number = p.x - minX;
			var yy:Number = p.y - minY;
			if ( p == list.first )	g.moveTo( xx, yy );
			else					g.lineTo( xx, yy );
		}
		g.endFill();
		
		//trace("■Object width = " + (maxX - minX) + ", height = " + (maxY - minY));
		
		var buf:BitmapData = new BitmapData(maxX - minX, maxY - minY, true, 0x00000000);
		buf.draw(shape);
		var bmp:Bitmap = new Bitmap(buf);
		bmp.x -= (maxX - minX) / 2;
		bmp.y -= (maxY - minY) / 2;
		
		//	FloatObject作成
		var obj:FloatObject = new FloatObject();
		obj.addChild( bmp );
		obj.x = cX;
		obj.y = cY;
		obj.posX = cX;
		obj.posY = cY;
		
		return	obj;
	}
	
	private function Init(e:Event):void {
		removeEventListener(Event.ADDED_TO_STAGE, Init );
		//	移動パラメータ等
		var len:Number = Math.sqrt( (stage.mouseX - posX) *  (stage.mouseX - posX) +  (stage.mouseY - posY) *  (stage.mouseY - posY) );
		mX = (stage.mouseX - posX) / len;
		mY = (stage.mouseY - posY) / len;
		
		rot = Math.random() * 10 - 5;
		
		addEventListener(Event.ENTER_FRAME, EnterFrame);
		addEventListener(Event.REMOVED_FROM_STAGE, Term );
	}
	
	private function Term(e:Event):void {
		removeEventListener(Event.REMOVED_FROM_STAGE, Term );
		removeEventListener(Event.ENTER_FRAME, EnterFrame );
	}
	
	private function EnterFrame(e:Event):void 
	{
		rotation += rot;
		
		posX += mX * speed;
		posY += mY * speed;
		
		if ( speed < 3 )	speed += 0.2;
		
		this.x = posX;
		this.y = posY;
		
		if ( posX + width / 2 < 0 || posX - width/2 > stage.stageWidth 
		||	posY + height / 2 < 0 || posY - height/2 > stage.stageHeight )
		{
			parent.removeChild( this );
		}
	}
	
}
/*******************************************************************
 * リスト管理クラス
 */
class PathObject {
	private static var obj_count:int = 0;
	public	var id:int;
	
	public	var dummy:PathList;	
	public	function get first():PathList {	return	dummy.next;	}
	public	function get last():PathList {	return	dummy.prev;	}	
	public	function get end():PathList { return	dummy;	}
	
	public	function PathObject() 
	{
		dummy = new PathList(0,0);
		dummy.next = dummy;
		dummy.prev = dummy;
		
		id = obj_count++;
	}
	/**
	 * 指定したパスをリストから削除
	 * @param	p
	 * @return	削除した要素を返す
	 */
	public	function Erase(p:PathList):PathList
	{
		if ( p == dummy )	return	null;
		p.prev.next = p.next;
		p.next.prev = p.prev;
		return	p;
	}
	/**
	 * リストの末に要素を追加
	 * @param	p
	 */
	public	function Push( p:PathList ):void 
	{
		p.prev = end.prev;
		p.next = end;
		end.prev.next = p;
		end.prev = p;			//	last == p
	}
	
	/**
	 * リスト末にリスト構造を追加する
	 * @param	sp
	 * @param	ep
	 */
	public	function PushList(sp:PathList,ep:PathList):void 
	{
		sp.prev = end.prev;
		ep.next = end;
		end.prev.next = sp;
		end.prev = ep;
	}
	
	/**
	 * リストの末から要素を削除
	 */
	public	function Pop():PathList 
	{
		return	Erase(last);
	}
	/**
	 * リストの先頭に要素を追加する
	 * @param	p
	 */
	public	function UnShift(p:PathList):void
	{
		p.prev = end;
		p.next = end.next;
		end.next.prev = p;
		end.next 	  = p;		//	first == p
	}
	/**
	 * リストの先頭から要素を削除
	 */
	public	function Shift():PathList
	{
		return	Erase(first);
	}
	/**
	 * 引数パスからパスを切り離して別リストとして返す。元のリストも変更される
	 * @param	sp
	 * @param	ep
	 */
	public	function Cut(sp:PathList,ep:PathList):PathObject 
	{
		var obj:PathObject = new PathObject();
		sp.prev.next = ep.next;
		ep.next.prev = sp.prev;
		obj.PushList(sp,ep);
		return	obj;
	}
}

/*****************************************************************
 * 双方向リスト
 */
class PathList {
	private static var path_count:int = 0;
	
	public	var obj_id:int = -1;		//	関連付けられてるオブジェクトへのID (関連付けられてるオブジェクトが複数ある場合は無意味)
	public	var path_id:int = -1;
	public	var prev:PathList = null;
	public	var next:PathList = null;
	public	var x:Number;
	public	var y:Number;
	
	public	function PathList(_x:Number, _y:Number)
	{
		prev = null;
		next = null;
		x = _x;
		y = _y;
		
		path_id = path_count++;
	}
}

/**
 * 二つの線分の交差判定
 * @param	v1S
 * @param	v1E
 * @param	v2S
 * @param	v2E
 */
function ChkHitLineToLine(v1S:PathList, v1E:PathList, v2S:PathList, v2E:PathList):Boolean 
{
	var vec1X:Number = v1E.x - v1S.x;
	var vec1Y:Number = v1E.y - v1S.y;
	var vec2X:Number = v2E.x - v2S.x;
	var vec2Y:Number = v2E.y - v2S.y;
	var vec1_2X:Number = v1S.x - v2S.x;
	var vec1_2Y:Number = v1S.y - v2S.y;
	
	//	並行はあたってないことに
	if ( ((vec1X * vec2Y) - (vec1Y * vec2X)) == 0 )
	{
		return	false;
	}else
	{
		var t:Number = ((vec1_2Y * vec2X) - (vec1_2X * vec2Y)) / ((vec1X * vec2Y) - (vec1Y * vec2X));
		var s:Number = ((vec1_2Y * vec1X) - (vec1_2X * vec1Y)) / ((vec1X * vec2Y) - (vec1Y * vec2X));
		if( t < 0 || t > 1.0 )	return	false;
		if( s < 0 || s > 1.0 )	return	false;
	}
	
	return	true;
}