http://hi.baidu.com/dabstudio
 
http://www.mt2a.com
 
http://www.mt2a.com/tag.php?name=flash
 
一些经验,写给多点触摸开发刚入门的同志
 
本帖最后由 NICK_LEE 于 2009-6-11 16:05 编辑 
大家好,很高兴看到有这样一个多点触摸论坛的存在
我大概07年开始接触到多点触摸的概念,当然也是通过Jeff Han那段神奇的视频认识到的(什么?你还没看过?赶紧补课吧~)
 
Jeff Han在TED大会上的视频地址:
 
http://www.ted.com/talks/jeff_ha ... gh_touchscreen.html
 
一直到现在,也做了很多多点触摸方面的应用,看到论坛中还是很多新加入的伙伴,不知道怎样开始,我觉得作为一个老鸟(呵呵,总算也混了段时间了),有必要写一篇入门级的文章,让大家尽快可以加入多点触摸的开发行列。
当然以下我主要从软件的角度去谈多点触摸的开发,至于硬件上的DIY,这篇文章暂不涉及,大家上网找找吧,有很多的教程的~
 
第一,touchlib
 
首先,我们先从总体结构上谈谈多点触摸软件。
现在我们自己DIY的触摸屏都是属于OpticalMultitouch,说白了就是用红外灯把你手指照亮,然后用摄像头去捕捉你的手指的位置来实现多点触摸。所以,在最低层要有一个摄像头的检测软件,用于捕捉跟踪你的手指位置,这个属于计算机视觉领域的活,别怕,现在开源世界里面已经有了好几个用于多点触摸捕捉的软件了,其中比较早也比较经典的一个就是touchlib。这个软件我没记错的话
 
大概07年中间的时候发布,后来又修改了好久,现在版本已经基本稳定在ver.401。很久没有变化了。
touchlib是用C++编写,最终是以dll(动态链接库)的形式发布,随着touchlib项目一起的(具体参见touchlib源码)还有几个用C++编的例子,比如smoke,mousedrive,osc等。有的看官读到这里也许会问了,那我要开发多点触摸程序,就必须用C++了?非也。
如果您是位C++程序员,并且也只准备用C++来开发多点触摸的程序,那么您就别往下看了,去好好看看touchlib里面带的例子吧,看会了就可以开发了。如果您想用其他开发语言(如as3),那就请继续往下看。
 
第二,OSC
 
在上面提到的几个例子中,有一个程序要特别注意的就是osc。要理解这个程序,你就不得不了解两个协议:osc和tuio。osc,全名(opensound control),是一个通信协议,定义了一些传输时用的格式,为了方便数据传输用的,比较底层,了解就可以了。
tuio,全名(A Protocol for Table Based Tangible User Interfaces),如果要理解osc.exe机制的话,这个协议可不能放过,它定义了如何在程序中表示触摸界面上出现的实体,如手指。这是touchlib和as3通信的格式。
看到这里有的看官是不是已经开始犯晕了,没事,不想看这些协议也没问题,我画张图您就全明白了~
 
摄像机--〉touchlib --〉osc --〉flosc --〉as3
又有人问了,这个flosc是个什么东西啊?这是个用java写的类似于桥一样的东西,将osc的消息(tuio格式)经过flosc传给as3。
好了消息传过来了,现在就让我们开始解析以下as3的结构(想用as3开发的同志,下面注意看吧)
 
第三,AS3 
 
先从AS3这个文件夹上看(什么?AS3文件夹在哪里?请上http://code.google.com/p/touchlib/自己下载先),里面一共有三个文件夹ext,int,src。其中ext是外部一些as3库,像pv3d之类的,就甭管它了。src文件夹中是各个flash例子的fla文件也暂时不管了。
 
最重要的就是int这个文件夹中的东西。
int文件夹中又有三个文件夹(靠,耍我们啊~),其中com_old就别去管它了,过时了(人家标明了old嘛)。app文件夹咱们一会儿再去看它。现在先来看flash这个文件夹中的东西。flash文件夹里面只有一个event文件夹,再下去就是五个文件了,这五个就是AS3中实现多点触摸功能最核心的五个类了,咱们一个个看下来:
 
TUIO
.as -- 这个是最主要的类,有两个功能,1.与osc(不会已经忘了它是干什么的吧?看看上面那张图)进行通信,接收osc传来的tuio格式的消息。2.将tuio格式的消息转化为TUIOObject,并且dispatch多点触摸事件。重点去看processMessage这个函数,基本功能都在里面了。
 
TUIOObject.as -- 这个是类说的白话一点就表示了触摸屏上的触摸点。
 
TouchEvent.as -- AS3多点触摸事件的定义都在里面了。因为现在AS3 api没有文档,所以要好好看这里面定义的事件类型。
 
TUIOCursor.as -- 不是很重要的一个类,只是用于调试用的光标。
 
TUIOSimulator.as -- 看名字就知道了,一个模拟器。其实现在好得模拟器很多,也用不到这个功能了。
 
好了,最重要的五个文件已经解析完了,当然如果你要理解其中机制的话,还是要你自己去阅读源码,毕竟我不能替代你去读。
下面回到app文件夹,里面又有两个文件夹core和demo。demo从名字上就知道了,是flash实例的源文件,这个先放放。先来看core文件夹,哎哟,这个里面的东西太多了,还是先挑重要的看吧,action文件夹是最重要的一个,因为所有多点的动作(如,放大,缩小,旋转)都是这个里面的类实现的。说句老实话,因为这个里面的类不是一个人写的,所以比较混乱,一共有两个分支:
 
RotatableScalable.as,这个是最早的一个现实旋转和缩放的类,用起来也比较简单,但代码有点混乱。另一个分支是
 
Multitouchable.as,其他开发者觉得老的类结构不好,想写个更清楚的,就出现了这个类,由这个类又衍生了好多其他的类。
 
所以,该文件夹下面的类都是继承或者是由这两个类改编而来的。具体的大家就自己看吧。好了,解析的部分先写那么多吧(好累啊~)。以上的部分是给想要研究多点触摸机制的同志看的,如果您觉得我不想知道这些,我就想立刻开始开发多点触摸程序,该从哪里开始呢?
我的建议是,看src文件夹底下的例子吧,这是最快的方法。再下载一个TUIO模拟器和flosc网桥就可以了立刻进行开发了!
 
模拟器的下载地址:
 
http://nuigroup.com/forums/viewthread/1495/
 
这个帖子中的附件都有了。好了,各位看官努力吧
也欢迎到我的博客看看(虽然更新不够快~):
 
http://hi.baidu.com/summer150
 
 
 
创建你的第一个Flash多点触摸程序(图文详尽教程)
 
多点触摸, Flash
本帖最后由 Thons 于 2009-8-7 23:06 编辑 
 
//-------------------------------------------------------------------
 
 
//原文地址:
 
http://wiki.nuigroup.com/Building_Your_First_Application
//Translator:Thons
 
 
//感谢panther的投递
 
 
//-------------------------------------------------------------------
 
//首先,必须使用SVN文件,否则可能无法正常工作  
 
如何使用SVN?
 
1.创建一个新的
 
Flash
文件(ActionScript 3);
 
=============================================================================
 
2.点击一下画布(舞台),这个时候文件属性面板就应该被激活了;
 
=============================================================================
 
3.点击“尺寸”按钮;
 
4.改变尺寸至1024*768,帧率大于30FPS;
 
=============================================================================
 
5.点击“设置”按钮(在“尺寸”按钮下面);
 
6.在“ActionScript 版本”一栏中,选择“ActionScript 3”,并点击右面的“设置”按钮;
 
=============================================================================
 
7.在下面的“类路径(classpath)”一栏中,点击 + 按钮并输入
 
 
        1.../ext
 
 
        2.以此类推
 
 
        3.../int
 
=============================================================================
 
8.保存这个Flash文件到
 
touchlib
文件夹中的AS3/src文件夹下,并起一个名字,比如touch.fla ;
 
=============================================================================
 
9.在AS3/int/app/demo文件夹下,创建一个新的文件夹,命名为MyTouchApp(这个可以不同,但是考虑到类路径和package。这个名字必须准确);
 
=============================================================================
 
10.创建一个新的ActionScript文件;
 
=============================================================================
 
11.保存为MyTouchApp.as,在AS3/int/app/demo/MyTouchApp文件夹里;
 
=============================================================================
 
12.返回至Flash文件里,也就是上面说的touch.fla ;
 
=============================================================================
 
13.在文档类(Document Class)里填入app.demo.MyTouchApp.MyTouchApp ;
 
=============================================================================
 
14.选择“矩形”按钮,在画布(舞台)上画一个矩形,要求尺寸漫过并大于整个舞台;
 
=============================================================================
 
15.右击刚刚画的矩形,选择“转换为元件”;
 
=============================================================================
 
16.确保矩形为MovieClip,然后点击确定
 
=============================================================================
 
17.保存文件。返回至MyTouchApp.as中;
 
=============================================================================
 
18.从例子中拷贝并粘贴代码(确保在此之前,代码区域里没有任何字符);
 
=============================================================================
 
19.保存文件,返回至touch.fla文件中;
 
=============================================================================
 
20.发布文件,现在应该可以工作了。
 
*****************************************************
 
代码示例
 
//这段代码用来显示每个触点下面的小红圈
=============================================================================
 
package app.demo.MyTouchApp{ //adds a circle where you touch (no resize)
 
    import flash.display.*;        
    import flash.events.*;
    import flash.net.*;
    import flash.geom.*;        
 
    public class MyTouchApp extends Sprite {
 
        public function MyTouchApp() {
 
            //--------connect to TUIO-----------------
            TUIO.init(this,'localhost',3000,'',true);
            trace("MyTouchApp Initialized");
            //----------------------------------------        
 
            addEventListener(TouchEvent.MOUSE_DOWN, touchDown); //run touchdown, when touched
        }
 
        public function touchDown(e:TouchEvent):void{        
 
            var curPt:Point = parent.globalToLocal(new Point(e.stageX, e.stageY)); //convert touch points to x,y               
 
            var circle:Sprite = new Sprite(); //create a new sprite
 
            circle.graphics.lineStyle(10, 0xff0000); //set line width to 10px and red
            circle.graphics.drawCircle(0,0,40); // draw a 40px circle
            circle.x = curPt.x; //put it where touch is (x cord)
            circle.y = curPt.y; //put it where touch is (y cord)
 
            addChild(circle); //add the circle where touch happened
 
        }
    }
}
 
=============================================================================
 
 
//这段代码允许你缩放舞台以及让触点下面出现小红圈
//下面的代码只是继承自RotatableScalable类。里面的内容只针对上述讲的东西,因为每个App构造函数不同。
 
 
=============================================================================
 
package app.demo.MyTouchApp{
 
        import flash.display.*;
        import flash.events.*;
        import flash.net.*;
        import flash.geom.*;
        import app.core.action.RotatableScalable;
 
        public class MyTouchApp extends RotatableScalable {//allows it to be scaled around
                public function MyTouchApp() {
 
                        //--------connect to TUIO-----------------
                        TUIO.init(this,'localhost',3000,'',true);
                        trace("MyTouchApp Initialized");
                        //----------------------------------------        
                        addEventListener(TouchEvent.MOUSE_DOWN, touchDown);//run touchdown, when touched
                }
 
                public function touchDown(e:TouchEvent):void {
 
                        var curPt:Point=parent.globalToLocal(new Point(e.stageX,e.stageY));//convert touch points to x,y               
                        var circle:Sprite = new Sprite();//create a new sprite
 
                        circle.graphics.lineStyle(10, 0xff0000);//set line width to 10px and red
                        circle.graphics.drawCircle(0,0,40);// draw a 40px circle
                        circle.x=curPt.x;//put it where touch is (x cord)
                        circle.y=curPt.y;//put it where touch is (y cord)
                        addChild(circle);//add the circle where touch happened
 
                }
        }
}
 
=============================================================================
 
//这段代码的作用是使你在触摸的时候,手指下面出现红色的涟漪(不支持选择和缩放的时候出现这个效果)
 
=============================================================================
 
package app.demo.MyTouchApp{
 
        import flash.events.TUIO; // allows to connect to touchlib/tbeta
        import flash.display.*;
        import flash.events.*;
        import flash.geom.*; // needed for curPt;
 
        public class MyTouchApp extends Sprite {
 
                var ripple:Ring; //ring class at end of code
                var ripples:Array = new Array(); // holds the list of rings to be animated
 
                var color:uint = 0xff0000;
                var radius:Number = 10;
                var thickness:Number = 5;
 
                public function MyTouchApp() {
 
                        //--------connect to TUIO-----------------
                        TUIO.init(this,'localhost',3000,'',true);
                        trace("MyTouchApp Initialized");
                        //----------------------------------------
 
                        stage.addEventListener(TouchEvent.MOUSE_DOWN, onTouchDown);
                        addEventListener(Event.ENTER_FRAME, rippler);
 
                }
 
                private function onTouchDown(e:TouchEvent):void { // makes a ripple, puts it in the array and starts the rippler
 
                        var curPt:Point=parent.globalToLocal(new Point(e.stageX,e.stageY));
 
                        ripple = new Ring(thickness, radius, color); // all defined above
                        ripple.x=curPt.x; // x pos of touch
                        ripple.y=curPt.y; // y pos of touch
                        addChild(ripple); // adds the ripple to the stange
                        ripples.push(ripple); // adds it to the ripples array so it can be animated
                }
 
                private function rippler(e:Event):void {
 
                        for (var i:uint = 0; i < ripples.length; i++) { // cycle through the ripples on stage and animate them
                                ripples.width *= 1.15;
                                ripples.height *= 1.15;
                                ripples.alpha -= .05;
 
                                if (ripples.alpha < .01) { // when the ripple's alpha is below 1% remove it from the stage, and the array
                                        removeChild(ripples);
                                        ripples.splice(i, 1);
                                }
                        }
                }
        }
}
 
import flash.display.Sprite; // ring class
 
class Ring extends Sprite {
 
        public function Ring(thickness:Number = 10, radius:Number = 40, color:uint = 0xff0000) {
                graphics.lineStyle(thickness, color);
                graphics.drawCircle(0,0,radius);
                graphics.endFill();
        }
}
 
=============================================================================
 
//这段代码联合了触摸和鼠标操作。
//当你用鼠标点击的时候,会出现一个小红圈,同时也允许用鼠标来模拟手指进行选择和缩放。
 
=============================================================================
 
package app.demo.MyTouchApp{
 
    import flash.display.*;
    import flash.events.*;
    import app.core.action.RotatableScalable;
 
    public class MyTouchApp extends RotatableScalable {
 
        public function MyTouchApp() {
 
            //--------connect to TUIO-----------------
            TUIO.init(this,'localhost',3000,'',true);
            trace("MyTouchApp Initialized");
            //----------------------------------------        
 
            addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); // adds an event listener looking for a mouse click - runs "onMouseDown"
        }
 
 
        private function onMouseDown(event:MouseEvent):void { //creats a circle when the mouse is clicked
 
            var circle:Sprite = new Sprite();
 
            circle.graphics.lineStyle(10, 0xff0000); //set line width to 10px and red
            circle.graphics.drawCircle(0,0,40); // draw a 40px circle
            circle.x = mouseX; //put it where the mouse clicked
            circle.y = mouseY;
 
            addChild(circle); //add the circle to the plane
        }
    }
}
 
=============================================================================
 
//这个小程序在舞台上以x轴的随机值分布一些圆环。每个圆环都可以移动和缩放。这个效果可以通过对RotatableScalable类的继承很简单的实现
 
=============================================================================
 
package app.demo.MyTouchApp{
 
    import flash.events.TUIO;// allows to connect to touchlib/tbeta
    import flash.display.Sprite;
 
    public class MyTouchApp extends Sprite {
 
 
        private var num:Number=5; // number of rings to put
        var ring:Ring; //ring class (at bottom)
 
        public function MyTouchApp():void {
 
            //--------connect to TUIO-----------------
            TUIO.init(this,'localhost',3000,'',true);
            trace("MyTouchApp Initialized");
            //----------------------------------------
 
 
            // put "num" rings randomly on the stage
            for (var i:int = 0; i < num; i++) {
                ring = new Ring();
                ring.x = Math.random() * stage.stageWidth;
                ring.y = Math.random() * stage.stageHeight;
                addChild(ring);
            }
        }
 
    }
}
 
import flash.display.Sprite; // ring class
import app.core.action.RotatableScalable;
 
class Ring extends RotatableScalable {
 
    public function Ring(thickness:Number = 10, radius:Number = 40, color:uint = 0xff0000) {
 
        //---RotatableScalable options------------
            //noScale = true;
            noRotate = true;   
            //noMove = true;
        //----------------------------------------
 
        graphics.lineStyle(thickness, color);
        graphics.drawCircle(0,0,radius);
 
        graphics.beginFill(0xffffff);
        graphics.drawCircle(0,0,radius);
        graphics.endFill();
    }
}
 
=============================================================================
 
//现在我们稍微整合一下代码,做一个简单的画图程序
 
=============================================================================
 
package app.demo.MyTouchApp{
 
    import flash.events.TUIO; // allows to connect to touchlib/tbeta
 
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*; // needed for curPt;
 
    public class MyTouchApp extends Sprite {
 
        private var color:uint = 0xff0000; // color of lines
        private var thickness:Number = 30; // thickness of lines
 
        private var blobs:Array = new Array(); // blobs we are currently interacting with
        private var lines:Array = new Array(); // array to hold the lines
 
        public function MyTouchApp():void {
 
            //--------connect to TUIO-----------------
            TUIO.init(this,'localhost',3000,'',true);
            trace("MyTouchApp Initialized");
            //----------------------------------------
 
            addEventListener(TouchEvent.MOUSE_DOWN, downEvent, false, 0, true); // run when finger down
            addEventListener(TouchEvent.MOUSE_UP, upEvent, false, 0, true); // run when finger up
            addEventListener(Event.ENTER_FRAME, updater, false, 0, true); // keep running
        }
 
        // updates/draws the drawn lines by:
        // cycling through all existing blobs
        // getting the id of each blob
        // use that id to get the line, as the lines are named after their blobs (eg line1280 )
        // tuioobj is the blob - see how it is called by request using the blob id?
        // if it is not there remove it from the blobs array.
        // draw the next segment of the line using lineTo and current loc (tuioobj.x, tuioobj.y)
        function updater(e:Event):void {
            for (var i:int = 0; i < blobs.length; i++) {
                var tuioobj:TUIOObject=TUIO.getObjectById(blobs.id);
 
                // if not found, then it must have died..
                if (! tuioobj) {
                    removeBlob(blobs.id);
                } else if (parent != null) {
 
                    lines["line"+blobs.id].graphics.lineTo(tuioobj.x, tuioobj.y);
                }
            }
        }
 
        // when touched, this calls addblob with the blob ID and the X/Y of where it started
        public function downEvent(e:TouchEvent):void {
            var curPt:Point=parent.globalToLocal(new Point(e.stageX,e.stageY));
            addBlob(e.ID, curPt.x, curPt.y);
            e.stopPropagation();
        }
 
        // When a finger stops touching, call removeBlob
        public function upEvent(e:TouchEvent):void {
            removeBlob(e.ID);
            e.stopPropagation();
        }
 
        // This takes the sent ID, x,y and puts it all in the blobs array
        // It then creats a new sprite, and sets the starting loc of the line
        // The line is put in an array called lines, so it can be called over and over by name
        // if the lines did not have unique names you could only draw one line at a time
        // so each line is named in the array after the id of the blob (EG line1280)
        function addBlob(id:Number, origX:Number, origY:Number):void {
            blobs.push( {id: id, origX: origX, origY: origY, myOrigX: x, myOrigY:y} );
 
            var line:Sprite = new Sprite();
            lines["line"+id] = line;
            lines["line"+id].graphics.lineStyle(thickness, color); //<-- config above
            lines["line"+id].graphics.moveTo(origX, origY); //starting point of line to be drawn
            addChild(lines["line"+id]); // add line to stage
        }
 
        // when called, this function removes the blobs from the array
        // cycles through the blobs array until the blob is found by its ID, then it is removed.
        function removeBlob(id:Number):void {
            for (var i=0; i < blobs.length; i++) {
                if (blobs.id==id) {
                    blobs.splice(i, 1);
                    return;
                }
            }
        }
 
    }
}
 
=============================================================================
 
 
 
 
 
 
[教程]图片的缩放和旋转,初学者进
 
multi-touch, actionscript, 多点触摸, flash
最近MTer初学者问我图片缩放怎么写,就写了个简单例子,高手就不要看了,哈。
先说说思想,就是建立一个支持缩放和旋转的容器,然后,把图片装进这个容器,那么图片也就支持缩放和旋转了。
 
1,建立一个MTimage.fla文件,存储在..\touchlib\AS3\int文件夹下。
2,建立一个MTimage.as文件,存储在..\touchlib\AS3\int文件夹下。
3,输入代码:
 
package
{
        import flash.events.TUIO;
        import flash.events.TouchEvent;
        import flash.net.URLRequest;
        import flash.display.Sprite;
        import app.core.action.*;
        import flash.display.Loader;
        public class MTimage extends Sprite
        {
                private var imageContainer:RotatableScalable=new RotatableScalable();//建一个支持缩放和旋转的容器
                private var imageLoaderoader=new Loader();
                public function MTimage()
                {
                        TUIO.init(this,'localhost',3000,'',true);//和mt服务器建立连接
                        
                        init();
                }
                private function init()
                {
                        addChild(imageContainer);
                        imageLoader.load(new URLRequest("image.jpg"));//加载图片
                        imageContainer.addChild(imageLoader);//把图片装进支持缩放和旋转的容器
                }
        }
        
}
4,在.fla文件的文档类输入:MTimage。
5,运行。