// forked from moyashipan's マルチタッチすきま妖怪 //HOW TO: //add a touch point: CLICK //move sigle point: DRAG the handle //remove single touch point: <SHIFT> + CLICK the handle //clear all touch points: <SPACE> package { import caurina.transitions.Equations; import caurina.transitions.Tweener; import flash.display.Sprite; // import flash.events.TouchEvent; import flash.geom.Point; import flash.text.TextField; // import flash.ui.Multitouch; // import flash.ui.MultitouchInputMode; import flash.utils.Dictionary; import flash.ui.Mouse; /** * For Flash Player 10.1 * For Multitouch Device * * スキマを作って くぱぁ * * 参考 :Adobe Labs - Adobe AIR 2 Beta 2 Sample Applications * labs.adobe.com/technologies/air2/samples/ * @author Shinichiro Sugimoto */ public class Main extends Sprite { private var _downQueue:Vector.<int> = new Vector.<int>; private var tPointList:Dictionary = new Dictionary(); private var lastSlit:Slit; public function Main():void { Wonderfl.capture_delay(10); // Mouse.hide(); // Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT; stage.addEventListener(TouchEvent.TOUCH_BEGIN, tStart, false, 0, true); new SimpleTouchSimulator(stage); } private function tStart(e:TouchEvent):void { if (e.target != e.currentTarget) return; if (tPointList[e.touchPointID] == null) { stage.addEventListener(TouchEvent.TOUCH_MOVE, tMove, false, 0, true); stage.addEventListener(TouchEvent.TOUCH_END, tEnd, false, 0, true); } _downQueue.push(e.touchPointID); tPointList[e.touchPointID] = new Point(e.stageX, e.stageY); } private function tMove(e:TouchEvent):void { tPointList[e.touchPointID] = new Point(e.stageX, e.stageY); if (_downQueue.length >= 2) { this.graphics.clear(); this.graphics.lineStyle(4, 0, 0.2); this.graphics.moveTo(p0.x, p0.y); this.graphics.lineTo(p1.x, p1.y); }else { this.graphics.clear(); } } private function tEnd(e:TouchEvent):void { if (_downQueue.length == 2) { createSlit(p0, p1); }else { this.graphics.clear(); } tPointList[e.touchPointID] = null; var i:int = _downQueue.indexOf(e.touchPointID); if (i < 0) return; _downQueue.splice(i, 1); } private function createSlit(p0:Point, p1:Point):void { var len:Number = Point.distance(p0, p1); // 指が近すぎると誤認識するのでその対策 if (len < 200) return; if (lastSlit != null) { lastSlit.close(); } lastSlit = new Slit(p0, p1); this.addChild(lastSlit); } public function get p0():Point { return tPointList[_downQueue[0]]; } public function get p1():Point { return tPointList[_downQueue[1]]; } } } import caurina.transitions.Tweener; import flash.display.Sprite; import flash.display.BitmapData; import flash.display.Graphics; import flash.display.Sprite; import flash.events.TouchEvent; import flash.filters.BlurFilter; import flash.filters.GlowFilter; import flash.geom.Matrix; import flash.geom.Point; import flash.utils.Dictionary; //スキマ class Slit extends Sprite { // くぱぁ可能領域(線)の太さ private static const kuparableThickness:uint = 96; private var p0:Point; private var p1:Point; private var g:Graphics; private var _downQueue:Vector.<int> = new Vector.<int>; private var tPointList:Dictionary = new Dictionary(); private var controlPoint0:Point; private var controlPoint1:Point; private var anchorPoint0:Point; private var anchorPoint1:Point; private var middlePoint:Point; private var distPoint:Point; private var len:Number; private var texture:BitmapData; public function Slit(p0:Point, p1:Point) { super(); this.p0 = p0; this.p1 = p1; g = graphics; middlePoint = Point.interpolate(p0, p1, .5); distPoint = p1.subtract(p0); len = distPoint.length; var normalVec:Point = Point.polar(1, Math.atan2(distPoint.x, distPoint.y)); normalVec.x *= len * 0.02; normalVec.y *= len * 0.02; controlPoint0 = middlePoint.add(normalVec); controlPoint1 = middlePoint.subtract(normalVec); anchorPoint0 = controlPoint0.clone(); anchorPoint1 = controlPoint1.clone(); filters = [new BlurFilter()]; createTexture(); draw(); this.addEventListener(TouchEvent.TOUCH_BEGIN, tStart, false, 0, true); } private function createTexture():void { texture = new BitmapData(100, 100, false, 0x300020); var eye:Sprite = new Sprite(); var g:Graphics = eye.graphics; g.lineStyle(); g.beginFill(0xffffff, 1); g.moveTo(40, 0); g.curveTo(0, 20, -40, 0); g.curveTo(0, -20, 40, 0); g.endFill(); g.beginFill(0xb00000, 1); g.drawCircle(0, 0, 10); g.endFill(); g.beginFill(0, 1); g.drawCircle(0, 0, 4); g.endFill(); texture.draw(eye, new Matrix(1, 0, 0, 1, 40, 25)); texture.draw(eye, new Matrix(1, 0, 0, 1, 60, 75)); eye = null; } public function close():void { mouseChildren = mouseEnabled = false; Tweener.addTween(this, {delay:6, time: 4, alpha:0, transition:"easeoutquart", onUpdate:shutEye, onComplete:function():void { this.parent.removeChild(this); } } ); } private function shutEye():void { controlPoint0 = Point.interpolate(middlePoint, controlPoint0, 0.1); controlPoint1 = Point.interpolate(middlePoint, controlPoint1, 0.1); draw(); } private function draw():void { g.clear(); var kuparablePoint0:Point = getKuparablePoint(controlPoint0); var kuparablePoint1:Point = getKuparablePoint(controlPoint1); g.lineStyle(4, 0, 0.5); //g.beginFill(0x300020); g.beginBitmapFill(texture, new Matrix(1, 0, 0, 1, middlePoint.x, middlePoint.y)); g.moveTo(p0.x, p0.y); g.curveTo(controlPoint0.x, controlPoint0.y, p1.x, p1.y); g.curveTo(controlPoint1.x, controlPoint1.y, p0.x, p0.y); g.endFill(); g.lineStyle(kuparableThickness, 0xff0000, 0); g.moveTo(p0.x, p0.y); g.curveTo(kuparablePoint0.x, kuparablePoint0.y, p1.x, p1.y); g.curveTo(kuparablePoint1.x, kuparablePoint1.y, p0.x, p0.y); } private function getKuparablePoint(controlPoint:Point):Point { return Point.interpolate(middlePoint, controlPoint, 0); } private function tStart(e:TouchEvent):void { if (tPointList[e.touchPointID] == null) { stage.addEventListener(TouchEvent.TOUCH_MOVE, tMove, false, 0, true); stage.addEventListener(TouchEvent.TOUCH_END, tEnd, false, 0, true); } _downQueue.push(e.touchPointID); tPointList[e.touchPointID] = new Point(e.stageX, e.stageY); } private function tMove(e:TouchEvent):void { var tp:Point = new Point(e.stageX, e.stageY); tPointList[e.touchPointID] = tp.clone(); if (Point.distance(tp, controlPoint0) < Point.distance(tp, controlPoint1)) { controlPoint0 = tp; }else { controlPoint1 = tp; } draw(); } private function tEnd(e:TouchEvent):void { tPointList[e.touchPointID] = null; var i:int = _downQueue.indexOf(e.touchPointID); if (i < 0) return; _downQueue.splice(i, 1); if (_downQueue.length < 1) { stage.removeEventListener(TouchEvent.TOUCH_MOVE, tMove); stage.removeEventListener(TouchEvent.TOUCH_END, tEnd); //ピタリと閉じる //if (Point.distance(controlPoint0, controlPoint1) < 50) { //this.removeEventListener(TouchEvent.TOUCH_BEGIN, tStart); //this.parent.removeChild(this); //} } } public function get tp0():Point { return tPointList[_downQueue[0]]; } public function get tp1():Point { return tPointList[_downQueue[1]]; } } /** * simulate TouchEvent with mouse. */ import flash.display.DisplayObject; import flash.display.InteractiveObject; import flash.display.Stage; import flash.display.Sprite; import flash.events.MouseEvent; import flash.events.KeyboardEvent; import flash.ui.Keyboard; class SimpleTouchSimulator { private var stage:Stage; private var pointID:int = 1; public function SimpleTouchSimulator(stage:Stage) { this.stage = stage; this.stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); this.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); } private function onMouseDown(e:MouseEvent):void { if(e.target is Blob) return; var id:int = pointID++ //TOUCH_BEGIN var target:DisplayObject = e.target as DisplayObject; this.dispatch(target, TouchEvent.TOUCH_BEGIN, id); var blob:Sprite = new Blob(id); blob.x = stage.mouseX; blob.y = stage.mouseY; stage.addChild(blob); blob.addEventListener(MouseEvent.MOUSE_DOWN, onDrag); } private var draggingBlob:Blob; private function onDrag(e:MouseEvent):void { var blob:Blob = e.currentTarget as Blob; if(e.shiftKey) { this.stage.removeChild(blob); //TOUCH_END var target:DisplayObject = this.getTarget(blob.x, blob.y); this.dispatch(target, TouchEvent.TOUCH_END, blob.id); } else { draggingBlob = blob; this.stage.addEventListener(MouseEvent.MOUSE_UP, onDrop); this.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove); } } private function onMove(e:MouseEvent):void { draggingBlob.x = stage.mouseX; draggingBlob.y = stage.mouseY; //TOUCH_MOVE var target:DisplayObject = this.getTarget(draggingBlob.x, draggingBlob.y); this.dispatch(target, TouchEvent.TOUCH_MOVE, draggingBlob.id); } private function onDrop(e:MouseEvent):void { e.currentTarget.removeEventListener(MouseEvent.MOUSE_UP, onDrop); e.currentTarget.removeEventListener(MouseEvent.MOUSE_MOVE, onMove); } private function onKeyDown(e:KeyboardEvent):void { if(e.keyCode == Keyboard.SPACE) { var i:int = this.stage.numChildren; while(i--) { var child:DisplayObject = this.stage.getChildAt(i); if(child is Blob) { var blob:Blob = child as Blob; this.stage.removeChild(blob); //TOUCH_END var target:DisplayObject = this.getTarget(blob.x, blob.y); this.dispatch(target, TouchEvent.TOUCH_END, blob.id); } } } } private function getTarget(x:Number, y:Number):DisplayObject { var target:DisplayObject; var objects:Array = this.stage.getObjectsUnderPoint(new Point(x, y)); var i:int = objects.length; while(i--) { var obj:Object = objects[i]; if(obj is InteractiveObject && !(obj is Blob)) { target = obj as DisplayObject; break; } } if(target == null) target = this.stage; return target; } private function dispatch(target:DisplayObject, eventType:String, pointID:int):void { var evt:TouchEvent = new TouchEvent(eventType, true, false, pointID); var localPoint:Point = new Point(target.mouseX, target.mouseY); var globalPoint:Point = target.localToGlobal(localPoint); evt.localX = localPoint.x; evt.localY = localPoint.y; evt.stageX = globalPoint.x; evt.stageY = globalPoint.y; target.dispatchEvent(evt); } } import flash.display.Sprite; class Blob extends Sprite { public var id:int; public function Blob(id:int) { this.id = id; this.graphics.lineStyle(2, 0x00ff00); this.graphics.beginFill(0xffffff); this.graphics.drawCircle(0, 0, 8); this.graphics.endFill(); } } import flash.events.Event; class TouchEvent extends Event { public static const TOUCH_BEGIN:String = "touchBegin"; public static const TOUCH_MOVE:String = "touchMove"; public static const TOUCH_END:String = "touchEnd"; public var touchPointID:int; public var localX:Number; public var localY:Number; public var stageX:Number; public var stageY:Number; public function TouchEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false, touchPointID:int=0) { this.touchPointID = touchPointID; super(type, bubbles, cancelable); } } マルチタッチすきま妖怪 (Simulator Ver.)