AS3中将TUIO协议转换到传统触摸事件
来源:互联网 发布:eclipse 改变端口号 编辑:程序博客网 时间:2024/06/11 02:29
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。
<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消息描述了当前存在的点,根据这个参数我们可以排除那些已经消失的点。首先,我们先创建一个触摸点类
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,如果没有找到则判断为新的触摸事件。
//根据ID查找TOUCHprivate function searchByRemoteName(remoteID:int):TuioObject{for each(var touch:TuioObject in _touchList){if(touch.remoteID == remoteID){return touch;}}return null;}
当有一个新点出现时,我们必须为它指定一个指向显示对象,以便从其向舞台冒泡事件,如果从这个点没有找到显示对象,则直接对舞台抛事件。注意,只有InteractiveObject才能抛出触摸事件,而Bitmap或Shape则不能接受鼠标事件
//搜索舞台元素 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的默认值
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; }
为了让程序更清晰一点,我们将 触摸点生效、触摸点移动、触摸点消失 三个状态的处理函数分开来写。
//应用新的触摸点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消息的函数
//解析消息 private function processMessage(msg:XML):void{ //点是否存在 不存在则从列表中移除 var node:XML; var touch:TuioObject; for each(node in msg.MESSAGE) { if(node.ARGUMENT[0].@VALUE == "alive") { for each (touch in _touchList)touch.isExist=false; for each(var aliveItem:XML in node.ARGUMENT.(@VALUE != "alive")) { touch = searchByRemoteName(int(aliveItem.@VALUE)); if(touch){ touch.isExist=true; } } } } //处理事件 var remoteID:int; var x:Number; var y:Number; var touchObj:TuioObject; for each(node in msg.MESSAGE) { if(node.ARGUMENT[0] && node.@NAME == "/tuio/2Dcur") { if(node.ARGUMENT[0].@VALUE == "set") { remoteID = int(node.ARGUMENT[1].@VALUE); x = Number(node.ARGUMENT[2].@VALUE) * _stageWidth; y = Number(node.ARGUMENT[3].@VALUE) * _stageHeight; touchObj=searchByRemoteName(remoteID); if(!touchObj){ var id:int = getFreeID(); if(id == -1)return; touchObj = new TuioObject(id,x,y); touchObj.remoteID = remoteID; _touchList.push(touchObj); addTouch(touchObj); }else{ touchObj.x = x ;touchObj.y = y; moveTouch(touchObj); } } } } //处理不存在的点 for(var i:int=_touchList.length-1;i>=0;i--){ if(!_touchList[i].isExist){ removeTouch(_touchList[i]); _touchList.splice(i,1); } } }
- AS3中将TUIO协议转换到传统触摸事件
- AS3中将文本直接保存到本地
- ios中将事件添加到系统日历
- ios中将事件添加到系统日历
- webservice 中将soap1.1协议转换soap1.2协议
- TUIO学习笔记1-TUIO 1.1 Protocol Specification协议规范/标准
- 触摸事件
- 触摸事件
- 触摸事件
- 触摸事件
- 触摸事件
- 触摸事件
- 触摸事件
- 触摸事件
- 触摸事件
- 触摸事件
- 触摸事件
- 触摸事件
- label or lable 哪个正确?
- 2013-Proxy代理的使用
- 127 - "Accordian" Patience C++中栈,STL的模拟
- 网络编程
- Android中listview的一些调用
- AS3中将TUIO协议转换到传统触摸事件
- win for VirtualBox 下ubuntu 安装增强功能【失败】
- 发送邮件
- Interleaving String 交叉的字符串
- Iterator vs. Enumeration
- Python中random模块
- Hadoop实战-初级部分 之 Hadoop MapReduce JAVA API
- linux下添加用户的命令--useradd
- 【Android】关于执行adb shell的错误解决