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

マルチタッチすきま妖怪 (Simulator Ver.)

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>
2010-06-07 15:25:34
/**
 * Copyright civet ( http://wonderfl.net/user/civet )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/wP1H
 */

// 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>
//2010-06-07 15:25:34
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);
    }
}