DivideLine
マウスで囲った線が独立して動くよ!
双方向リスト自作久しぶりでちゃんと出来てるかなぁ
/**
* 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;
}