AS3中将TUIO协议转换到传统触摸事件

TUIO是一个用途广泛,支持厂商众多的多点触摸协议。 其编码采用XML抽象描述,所以任何支持XML的语言都可以使用TUIO协议的触摸设备。另外,TUIO不受windows触摸点上限限制,即设备支持多少个点,你就能使用多少个。

    现在最新的TUIO协议版本是2.0 ,  但是仍然没有普及,现有设备还是以1.0为默认支持。


    希望在设备中使用TUIO,必须要与TUIO服务建立一个连接,TUIO协议的默认端口为 3000,这里跳过连接直接进入主题。

   

    这是一个TUIO协议的一个数据包,其包含至少3个名为MESSAGE子项,每个子项的第一个子项的value属性定义了此子项的数据类型,

    以此例为示,它有3个子项,第1个子项(alive)代表着当前存在的触摸点,这里是指所有在设备上的触摸点,包括那些正在移动的和静止的。第2个子项(set)对应了一个触摸点的详细数据,第3个子项(fseq)定义了包的序列ID。

  1. <OSCPACKET ADDRESS="127.0.0.1" PORT="55448" TIME="-3736546999771946328">  
  2.   <MESSAGE NAME="/tuio/2Dcur">  
  3.     <ARGUMENT TYPE="s" VALUE="alive"/>  
  4.     <ARGUMENT TYPE="i" VALUE="4"/>  
  5.   </MESSAGE>  
  6.   <MESSAGE NAME="/tuio/2Dcur">  
  7.     <ARGUMENT TYPE="s" VALUE="set"/>  
  8.     <ARGUMENT TYPE="i" VALUE="4"/>  
  9.     <ARGUMENT TYPE="f" VALUE="0.014778325123152709"/>  
  10.     <ARGUMENT TYPE="f" VALUE="0.03414634146341464"/>  
  11.     <ARGUMENT TYPE="f" VALUE="0"/>  
  12.     <ARGUMENT TYPE="f" VALUE="0"/>  
  13.     <ARGUMENT TYPE="f" VALUE="0"/>  
  14.   </MESSAGE>  
  15.   <MESSAGE NAME="/tuio/2Dcur">  
  16.     <ARGUMENT TYPE="s" VALUE="fseq"/>  
  17.     <ARGUMENT TYPE="i" VALUE="3"/>  
  18.   </MESSAGE>  
  19. </OSCPACKET>  
<OSCPACKET ADDRESS="127.0.0.1" PORT="55448" TIME="-3736546999771946328">
  <MESSAGE NAME="/tuio/2Dcur">
    <ARGUMENT TYPE="s" VALUE="alive"/>
    <ARGUMENT TYPE="i" VALUE="4"/>
  </MESSAGE>
  <MESSAGE NAME="/tuio/2Dcur">
    <ARGUMENT TYPE="s" VALUE="set"/>
    <ARGUMENT TYPE="i" VALUE="4"/>
    <ARGUMENT TYPE="f" VALUE="0.014778325123152709"/>
    <ARGUMENT TYPE="f" VALUE="0.03414634146341464"/>
    <ARGUMENT TYPE="f" VALUE="0"/>
    <ARGUMENT TYPE="f" VALUE="0"/>
    <ARGUMENT TYPE="f" VALUE="0"/>
  </MESSAGE>
  <MESSAGE NAME="/tuio/2Dcur">
    <ARGUMENT TYPE="s" VALUE="fseq"/>
    <ARGUMENT TYPE="i" VALUE="3"/>
  </MESSAGE>
</OSCPACKET>

    事实上,我们只需要使用alive和set消息,其他的消息都不在我们的考虑之内,

    set消息传过来的参数只是TUIO设备上的坐标比例,从0-1,将其与本地舞台大小相乘才能得到舞台坐标。


   alive消息描述了当前存在的点,根据这个参数我们可以排除那些已经消失的点。首先,我们先创建一个触摸点类

[javascript] view plain copy
print ?
  1.     import flash.display.InteractiveObject;  
  2.   
  3.     public class TuioObject  
  4.     {  
  5.         /** 触摸id */  
  6.         public var id:int;  
  7.           
  8.         /** 远程触摸编号 */  
  9.         public var remoteID:int;  
  10.           
  11.         /** 指针对象 */  
  12.         public var target:InteractiveObject;  
  13.           
  14.         /** 屏幕上的位置 */  
  15.         public var x:int;  
  16.           
  17.         /** 屏幕上的位置 */  
  18.         public var y:int;  
  19.           
  20.         /** 生效时候的位置 */  
  21.         public var startX:Number;  
  22.           
  23.         /** 生效时候的位置 */  
  24.         public var startY:Number;  
  25.           
  26.         /** 是否存在 */  
  27.         public var isExist:Boolean;  
  28.           
  29.         public function TuioObject(touchID:int,x:Number,y:Number)  
  30.         {  
  31.             id = touchID;  
  32.             this.x = startX = x;  
  33.             this.y = startY = y;  
  34.             isExist = true;  
  35.         }  
    import flash.display.InteractiveObject;

    public class TuioObject
    {
        /** 触摸id */
        public var id:int;
        
        /** 远程触摸编号 */
        public var remoteID:int;
        
        /** 指针对象 */
        public var target:InteractiveObject;
        
        /** 屏幕上的位置 */
        public var x:int;
        
        /** 屏幕上的位置 */
        public var y:int;
        
        /** 生效时候的位置 */
        public var startX:Number;
        
        /** 生效时候的位置 */
        public var startY:Number;
        
        /** 是否存在 */
        public var isExist:Boolean;
        
        public function TuioObject(touchID:int,x:Number,y:Number)
        {
            id = touchID;
            this.x = startX = x;
            this.y = startY = y;
            isExist = true;
        }

    这个类描述了一个TUIO触摸点,每次出现新的触摸点时我们实例化一个与其相对应的触摸点。由于传输过来的数据并没有告诉我们某个触摸点是刚出现的,我们必须从现有的触摸点集合中查找ID,如果没有找到则判断为新的触摸事件。

[javascript] view plain copy
print ?
  1. //根据ID查找TOUCH  
  2. private function searchByRemoteName(remoteID:int):TuioObject{  
  3.     for each(var touch:TuioObject in _touchList){  
  4.         if(touch.remoteID == remoteID){  
  5.             return touch;  
  6.         }  
  7.     }  
  8.     return null;  
  9. }  
		//根据ID查找TOUCH
		private function searchByRemoteName(remoteID:int):TuioObject{
			for each(var touch:TuioObject in _touchList){
				if(touch.remoteID == remoteID){
					return touch;
				}
			}
			return null;
		}


    当有一个新点出现时,我们必须为它指定一个指向显示对象,以便从其向舞台冒泡事件,如果从这个点没有找到显示对象,则直接对舞台抛事件。注意,只有InteractiveObject才能抛出触摸事件,而Bitmap或Shape则不能接受鼠标事件

[javascript] view plain copy
print ?
  1. //搜索舞台元素    
  2. private function findDisplayObject(x:Number,y:Number):InteractiveObject{  
  3.     var obj:DisplayObject;  
  4.     var objArray:Array = _stage.getObjectsUnderPoint(new Point(x,y));  
  5.     if(objArray.length>0){  
  6.         obj=objArray[objArray.length-1];  
  7.         if(!(obj is InteractiveObject)){  
  8.             obj = obj.parent;  
  9.         }  
  10.         return obj;  
  11.     }else{  
  12.         return _stage;  
  13.     }  
  14. }  
		//搜索舞台元素  
		private function findDisplayObject(x:Number,y:Number):InteractiveObject{
			var obj:DisplayObject;
			var objArray:Array = _stage.getObjectsUnderPoint(new Point(x,y));
			if(objArray.length>0){
				obj=objArray[objArray.length-1];
				if(!(obj is InteractiveObject)){
					obj = obj.parent;
				}
				return obj;
			}else{
				return _stage;
			}
		}

    而由于从tuio里发送过来的事件都是以TUIO自己习惯进行编号的,为了防止与本地的触摸冲突,我们需要给每个触摸点一个本地的ID,本地的触摸编号从1开始到255结束,我们就从256开始,上限随你设定,尽管你设置的上限足够大,但是必须为其准备一个超出上限了就返回-1的默认值

[javascript] view plain copy
print ?
  1.         private function getFreeID():int{  
  2.             for(var i:int=256;i<1024;i++){  
  3.                 var used:Boolean=false;  
  4.                 for each(var temp:TuioObject in _touchList){  
  5.                     used = i == temp.id;  
  6.                 }  
  7.                 if(!used)return i;  
  8.             }  
  9.             return -1;  
  10.         }  
        private function getFreeID():int{
            for(var i:int=256;i<1024;i++){
                var used:Boolean=false;
                for each(var temp:TuioObject in _touchList){
                    used = i == temp.id;
                }
                if(!used)return i;
            }
            return -1;
        }

    为了让程序更清晰一点,我们将   触摸点生效、触摸点移动、触摸点消失  三个状态的处理函数分开来写。

[javascript] view plain copy
print ?
  1.               //应用新的触摸点  
  2. private function addTouch(touchPoint:TuioObject):void{  
  3.     touchPoint.target = findDisplayObject(touchPoint.x,touchPoint.y);  
  4.     if(touchPoint.target == _stage){  
  5.         _stage.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_BEGIN,  
  6.             true,false,touchPoint.id,false,touchPoint.x,touchPoint.y));  
  7.     }else{  
  8.         var local:Point = touchPoint.target.globalToLocal(new Point(touchPoint.x,touchPoint.y));  
  9.         touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_BEGIN,  
  10.             true,false,touchPoint.id,false,local.x,local.y));  
  11.     }  
  12. }  
  13.   
  14. //触摸点移动  
  15. private function moveTouch(touchPoint:TuioObject):void{  
  16.     var oldTarget:InteractiveObject = touchPoint.target;  
  17.     touchPoint.target = findDisplayObject(touchPoint.x,touchPoint.y);  
  18.     var local:Point = touchPoint.target.globalToLocal(new Point(touchPoint.x,touchPoint.y));  
  19.     if(touchPoint.target == oldTarget){  
  20.         oldTarget.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_MOVE,  
  21.             true,false,touchPoint.id,false,local.x,local.y));  
  22.     }else{  
  23.         var old:Point = oldTarget.globalToLocal(new Point(touchPoint.x,touchPoint.y));  
  24.         oldTarget.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OUT,  
  25.             true,false,touchPoint.id,false,old.x,old.y,NaN,NaN,NaN,touchPoint.target));  
  26.           
  27.         touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OVER,  
  28.             true,false,touchPoint.id,false,local.x,local.y,NaN,NaN,NaN,touchPoint.target));  
  29.         touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_MOVE,  
  30.             true,false,touchPoint.id,false,local.x,local.y));  
  31.     }  
  32. }  
  33.   
  34. //触摸点消失  
  35. private function removeTouch(touchPoint:TuioObject):void{  
  36.     var oldTarget:InteractiveObject = touchPoint.target;  
  37.     touchPoint.target = findDisplayObject(touchPoint.x,touchPoint.y);  
  38.     var local:Point = touchPoint.target.globalToLocal(new Point(touchPoint.x,touchPoint.y));  
  39.     if(touchPoint.target == oldTarget){  
  40.         oldTarget.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_END,  
  41.             true,false,touchPoint.id,false,local.x,local.y));  
  42.     }else{  
  43.         var old:Point = oldTarget.globalToLocal(new Point(touchPoint.x,touchPoint.y));  
  44.         oldTarget.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OUT,  
  45.             true,false,touchPoint.id,false,old.x,old.y,NaN,NaN,NaN,touchPoint.target));  
  46.           
  47.         touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OVER,  
  48.             true,false,touchPoint.id,false,local.x,local.y,NaN,NaN,NaN,touchPoint.target));  
  49.         touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_END,  
  50.             true,false,touchPoint.id,false,local.x,local.y));  
  51.     }  
  52. bsp;               }  
                //应用新的触摸点
		private function addTouch(touchPoint:TuioObject):void{
			touchPoint.target = findDisplayObject(touchPoint.x,touchPoint.y);
			if(touchPoint.target == _stage){
				_stage.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_BEGIN,
					true,false,touchPoint.id,false,touchPoint.x,touchPoint.y));
			}else{
				var local:Point = touchPoint.target.globalToLocal(new Point(touchPoint.x,touchPoint.y));
				touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_BEGIN,
					true,false,touchPoint.id,false,local.x,local.y));
			}
		}
		
		//触摸点移动
		private function moveTouch(touchPoint:TuioObject):void{
			var oldTarget:InteractiveObject = touchPoint.target;
			touchPoint.target = findDisplayObject(touchPoint.x,touchPoint.y);
			var local:Point = touchPoint.target.globalToLocal(new Point(touchPoint.x,touchPoint.y));
			if(touchPoint.target == oldTarget){
				oldTarget.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_MOVE,
					true,false,touchPoint.id,false,local.x,local.y));
			}else{
				var old:Point = oldTarget.globalToLocal(new Point(touchPoint.x,touchPoint.y));
				oldTarget.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OUT,
					true,false,touchPoint.id,false,old.x,old.y,NaN,NaN,NaN,touchPoint.target));
				
				touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OVER,
					true,false,touchPoint.id,false,local.x,local.y,NaN,NaN,NaN,touchPoint.target));
				touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_MOVE,
					true,false,touchPoint.id,false,local.x,local.y));
			}
		}
		
		//触摸点消失
		private function removeTouch(touchPoint:TuioObject):void{
			var oldTarget:InteractiveObject = touchPoint.target;
			touchPoint.target = findDisplayObject(touchPoint.x,touchPoint.y);
			var local:Point = touchPoint.target.globalToLocal(new Point(touchPoint.x,touchPoint.y));
			if(touchPoint.target == oldTarget){
				oldTarget.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_END,
					true,false,touchPoint.id,false,local.x,local.y));
			}else{
				var old:Point = oldTarget.globalToLocal(new Point(touchPoint.x,touchPoint.y));
				oldTarget.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OUT,
					true,false,touchPoint.id,false,old.x,old.y,NaN,NaN,NaN,touchPoint.target));
				
				touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OVER,
					true,false,touchPoint.id,false,local.x,local.y,NaN,NaN,NaN,touchPoint.target));
				touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_END,
					true,false,touchPoint.id,false,local.x,local.y));
			}
                }

    最后  关键的处理TUIO的xml消息的函数

[javascript] view plain copy
print ?
  1.                 //解析消息  
  2.         private function processMessage(msg:XML):void{  
  3.             //点是否存在  不存在则从列表中移除  
  4.             var node:XML;  
  5.             var touch:TuioObject;  
  6.             for each(node in msg.MESSAGE)  
  7.             {  
  8.                 if(node.ARGUMENT[0].@VALUE == "alive")  
  9.                 {  
  10.                     for each (touch in _touchList)touch.isExist=false;  
  11.                       
  12.                     for each(var aliveItem:XML in node.ARGUMENT.(@VALUE != "alive"))  
  13.                     {  
  14.                         touch = searchByRemoteName(int(aliveItem.@VALUE));  
  15.                         if(touch){  
  16.                             touch.isExist=true;  
  17.                         }  
  18.                     }  
  19.                 }  
  20.             }  
  21.             //处理事件  
  22.             var remoteID:int;  
  23.             var x:Number;  
  24.             var y:Number;  
  25.             var touchObj:TuioObject;  
  26.             for each(node in msg.MESSAGE)  
  27.             {  
  28.                 if(node.ARGUMENT[0] && node.@NAME == "/tuio/2Dcur")  
  29.                 {  
  30.                     if(node.ARGUMENT[0].@VALUE == "set")   
  31.                     {  
  32.                         remoteID = int(node.ARGUMENT[1].@VALUE);  
  33.                         x = Number(node.ARGUMENT[2].@VALUE) * _stageWidth;  
  34.                         y = Number(node.ARGUMENT[3].@VALUE) * _stageHeight;  
  35.                           
  36.                         touchObj=searchByRemoteName(remoteID);  
  37.                         if(!touchObj){  
  38.                             var id:int = getFreeID();  
  39.                             if(id == -1)return;  
  40.                             touchObj = new TuioObject(id,x,y);  
  41.                             touchObj.remoteID = remoteID;  
  42.                             _touchList.push(touchObj);  
  43.                             addTouch(touchObj);  
  44.                         }else{  
  45.                             touchObj.x = x ;touchObj.y = y;  
  46.                             moveTouch(touchObj);  
  47.                         }  
  48.                     }  
  49.                 }  
  50.             }  
  51.               
  52.             //处理不存在的点  
  53.             for(var i:int=_touchList.length-1;i>=0;i--){  
  54.                 if(!_touchList[i].isExist){  
  55.                     removeTouch(_touchList[i]);  
  56.                     _touchList.splice(i,1);  
  57.                 }  
  58.             }  
  59.         }  

猜你喜欢

转载自blog.csdn.net/merryken/article/details/80564480