触控管理器(TypeScript实现)

【主要功能】

1.实时访问每个触摸手指的状态(手指顺序,touch位置,按钮状态,Touch类)

2.使鼠标与触摸的API兼容访问

3.实时访问键盘按钮状态

4.增加基础数据结构 List Dictionary Statck Queue

开头说一下我也是最近才开始接触CocosCreator,所以有哪些错误望指出。

完成版我会放到GitHub.

CocosCreator在使用的过程中对事件的监听事件方式我用着很别扭所以才特意的早了个轮子,起始就是简单的对其内部API进行了加工而已,大佬就不用看了-_-。

CocosCreator的触摸互交监听事件需要先绑定到指定的Node上,所以想由单例调用的话就必须绑定到一个合适的Node上。而且这个Node的触摸面积必须是最大的!

那显而易见的就是Canvas了或者Camera,Camera我没试过你感兴趣的话可以试试。首先Canva符合我们的需要啊,真是刚需。

先看下最终效果20多秒的Gif:包括了TouchFinger的 手指顺序记录、点击、滑动、弹起、失效( | 与 1 不一样哦在图里, | 代表无触摸)

接下来就开始制定实现策略,不过你必须先了解一下CocosCreator的内置触摸API,才能进行加工啊!!!

对了顺便一提键盘的实现策略我会顺便一提的。

1.EventType

cc.Node.EventType
包含着触控与鼠标的事件,至于为什么没有键盘的呢?因为触摸与鼠标的监听事件需要实体(Node)啊!
而键盘并不需要特定实体,Cocos早已在内部留有了一个系统事件单例,来方便全局使用,所以键盘就
不要绑定特定了实体了直接绑这个全局的就行(systemEvent)向深入理解的看官方的“节点系统事件”就好。
看看源码你就清楚了,在这暂不详述,存在即合理^_^。

【看源码理解一下吧】

cocos2d/core/event/system-event.js:198

2.枚举对象定义

枚举对象定义 对应的事件名 事件触发的时机
cc.Node.EventType.TOUCH_START 自定义 当手指触点落在目标节点区域内时
cc.Node.EventType.TOUCH_MOVE 自定义 当手指在屏幕上目标节点区域内移动时
cc.Node.EventType.TOUCH_END 自定义 当手指在目标节点区域内离开屏幕时
cc.Node.EventType.TOUCH_CANCEL 自定义 当手指在目标节点区域外离开屏幕时

3.Touch 类型

Touch类封装了触摸手指的具体信息

  • getLocation 获取当前触点位置。
  • getLocationX 获取当前触点 X 轴位置。
  • getLocationY 获取当前触点 Y 轴位置。
  • getPreviousLocation 获取触点在上一次事件时的位置对象,对象包含 x 和 y 属性。
  • getStartLocation 获获取触点落下时的位置对象,对象包含 x 和 y 属性。
  • getDelta 获取触点距离上一次事件移动的距离对象,对象包含 x 和 y 属性。
  • getLocationInView 获取当前事件在游戏窗口内的坐标位置对象,对象包含 x 和 y 属性。
  • getPreviousLocationInView 获取触点在上一次事件时在游戏窗口中的位置对象,对象包含 x 和 y 属性。
  • getStartLocationInView 获取触点落下时在游戏窗口中的位置对象,对象包含 x 和 y 属性。
  • getID 触点的标识 ID,可以用来在多点触摸中跟踪触点。
  • setTouchInfo 设置触摸相关的信息。

4. cc.Event.EventTouch

触摸事件绑定的回调参数类型,里面包含着触摸事件的当前触摸状态的所有信息

cocos2d/core/event/event.js:202
[Tip]Cocos的触摸事件的touch信息是以栈形式存储

【主体策略】

1.为主Canvas绑定枚举对象,的回调方法

        this.node.on(cc.Node.EventType.TOUCH_START, this.touchBtnDownMonitor);this.node.on(cc.Node.EventType.TOUCH_END, this.touchBtnUpMonitor);this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.touchBtnDisMonitor);this.node.on(cc.Node.EventType.TOUCH_MOVE, this.touchMoveMonitor);

2.静态访问触摸手指的Touch信息,以及触摸的状态:按下、移动、弹起(失效)

const ButtonStatu= cc.Enum({ Up: 0 , Down: 1, Dis:2,Move:3})

定义按键状态:ButtonStatu[],并一开始初始化为10(cocos指出8点触控,具体可自行设置)

3.对触摸手指数据进行数组存储(在这里我并不想用List、Dictionary等数据结构(需自行实现))

 touchs : cc.Touch[];    //存储Touch信息touchStatu : ButtonStatu[];    //存储状态信息

根据枚举对象在绑定触摸事件后,访问的绑定枚举对象的回调方法时对数据记录

3.根据CocosCreator API 将触摸手机数据进行保留与更新.

需要两个共用函数,

a.手指加入   --touchFingetMonitor

private touchFingetMonitor(event :cc.Event.EventTouch){//手指数组为空则直接进行保存,否则将进行数据更新if(this.touchs){//初始化变量let temp : cc.Touch[] = [];        //最终的手指数组信息let havThis :Boolean= false;       //当前手指是否已经被保存过let havThisID :number= -1;         //当前手指ID,为-1则当前手指未被保留//检测当前手指是否已经被保存过,未保存则记录其IDfor(let i=0;i<this.touchs.length;i++){temp[i] = this.touchs[i];if(!havThis && temp[i] == event.touch){havThis = true;}//处理getTouches()中不区分,触摸手指的前后信息,即第几根手指触摸其该手指排序就是第次(例如有三手指按顺序触摸A,B,C,B一直按下弹起但其保存位置一直是第二位)if(havThisID == -1 && ((temp[i] == null && event.touch.getID() == i) ||temp[i].getID() == event.touch.getID())){havThisID = i;}}if(!havThis){if(havThisID != -1){temp[havThisID] = event.touch;}else{if(event.touch.getID() < this.touchs.length){for(let i=this.touchs.length;i>event.touch.getID();i--){temp[i] = temp[i-1];}temp[event.touch.getID()] = event.touch;}else{temp[this.touchs.length] = event.touch;}}}this.touchs = temp;}else{this.touchs = [event.touch];}}

b手指减去(CocosCreator默认用的是Stack),我觉得不怎么好使.   --touchFingetOutMonitor

private touchFingetOutMonitor(event :cc.Event.EventTouch){let touchID = event.touch.getID();//只有一根手指就直接清除数据,更新数据if(this.touchs.length == 1){this.touchs = [];}else{let temp : cc.Touch[] = [];let thisindex :number= -1;for(let i=0;i<this.touchs.length;i++){if(this.touchs[i].getID() == event.touch.getID()){thisindex = i;break;}}let i=0;for(i ;i<thisindex;i++){temp[i] = this.touchs[i];}for(i ;i<this.touchs.length-1 ;i++){temp[i] = this.touchs[i+1];}this.touchs = temp;}}

4.数据处理

    private touchBtnDownMonitor(event :cc.Event.EventTouch){this.touchFingetMonitor(event);this.touchStatu[event.touch.getID()] = BtnStatu.Down;}private touchMoveMonitor(event :cc.Event.EventTouch){this.touchFingetMonitor(event);this.touchStatu[event.touch.getID()] = BtnStatu.Move;}private touchBtnUpMonitor(event :cc.Event.EventTouch){this.touchStatu[event.touch.getID()] = BtnStatu.Up;this.touchFingetOutMonitor(event);}private touchBtnDisMonitor(event :cc.Event.EventTouch){this.touchStatu[event.touch.getID()] = BtnStatu.Dis;this.touchFingetOutMonitor(event);}

这四个方法在响应时传入的EventTouch信息,会时刻的进行更新,所以需要时刻的将其中的数据进行记录。

而touchBtnDownMonitor 和 touchBtnUpMonitor 只需要处理 手指加入,touchBtnDisMonitor 和 touchMoveMonitor只需要处理 手指减去即可(所以只能实现三种状态:按下、弹起、移动),可自行设计。

5.测试处理

顺便建个脚本就能用,这里我用到了数据结构比较方便

finger : Dictionary<number,cc.Node>;if(InputMonitor.Instance().Touchs() != null){for(let i=0;i<InputMonitor.Instance().Touchs().length;i++){if(!this.finger.ContainKey(id)){let obj:cc.Node = cc.instantiate(this.fingerPrefab);obj.parent = cc.director.getScene();obj.position = InputMonitor.Instance().Touchs()[i].getLocation();obj.getComponentInChildren(cc.Label).string = id.toString();this.finger.Add(id,obj);}else{this.finger.Item(id).position = InputMonitor.Instance().Touchs()[i].getLocation();}}}let del : List<number> = new List<number>();for(let j=0;j<this.finger.Count();j++){let id : number = this.finger.ItemKeyofIndex(j);if(!InputMonitor.Instance().ContainID(id)){del.Add(id);}}for(let j =0;j<del.Count();j++){this.finger.Item(del.Item(j)).destroy();this.finger.Remove(del.Item(j));}

第二次更新

这次支持了鼠标显示世界位置

提要:

在cocosCreate中的要获取鼠标的世界位置,就必须是在使用两台摄像机的情况下(一台的话你还费什么劲^_^)。

a.一台是UI的相机

b.一台是世界相机

当然这时的世界原点还是以Canvas的(0,0)点为准,鼠标的世界位置也是以此为原点计算。

世界相机有时会跟随玩家而移动(UI相机当然不可能,不然你的UI元素还要不要了)

[Tip]新手可能会将UI相机与世界相机搞混。所以我在这阐述一下,首先Canvas只是画布并不会将UI图像显示出来,所以需要一个特定的相机来获取UI(Canvas中的元素)图像,cocosCreate在你的默认场景的Canvas中的MainCamera相机就是的,但他默认是世界元素与UI元素都会显示。世界元素就是不以Canvas为根节点,UI元素才是(这里只是我的个人区分),这样区分要实现就需要自己定义Group了。所以我们通常用一个或多个世界相机只显示世界元素,一个UI相机只显示UI元素,来实现UI永远显示在世界元素之上.(可能cocosCreate的3D成熟了自然就是了)

【警惕点】

1.屏幕的分辨率变化

2.世界位置的与触点位置的转换

【实现策略】

1.获取触点的屏幕位置

2.获取屏幕的实际尺寸

3.将触点位置通过屏幕实际尺寸转换为实际的屏幕位置(触点的屏幕位置只会根据canvas的大小来计算,子啊屏幕拉伸后回不准确,所以需要再次转换为实际的屏幕位置)

4.根据世界相机将实际的屏幕尺寸转换为世界位置

【实现方法】

1.定义参数

@property(cc.Node)worldCamera : cc.Node= null;    //世界相机MousePosition() :cc.Vec2        //鼠标屏幕位置 --不是实际位置MouseToWorldPosition() :cc.Vec2 //鼠标的世界位置

2.获取屏幕的实际尺寸

cc.view.setResizeCallback(this.initScreenInfo);//初始化屏幕参数    --启动时调用或者屏幕大小改变时调用
initScreenInfo(){InputMonitor.Instance().visibleSize = new cc.Vec2(cc.view.getVisibleSize().width/2 ,cc.view.getVisibleSize().height/2);
}

2.将触点位置通过屏幕实际尺寸转换为世界位置

        if(this.worldCamera != null){this.mouseWorldPosition.x = this.worldCamera.position.x - this.visibleSize.x +                 this.mousePosition.x;this.mouseWorldPosition.y = this.worldCamera.position.y - this.visibleSize.y + this.mousePosition.y;return this.mouseWorldPosition;}else{return this.mousePosition;}

第三次更新

这次支持了实时访问键盘的响应事件

1.调用接口范例

    update(){if(InputMonitor.Instance().GetKeyBeginDown(cc.macro.KEY.a)){if(this.node.width > 0)this.node.width = -this.node.width;this.anim.play("run",0);}if(InputMonitor.Instance().GetKeyBeginDown(cc.macro.KEY.d)){if(this.node.width < 0)this.node.width = -this.node.width;this.anim.play("run",0);}if(InputMonitor.Instance().GetKeyBeginDown(cc.macro.KEY.w)){this.anim.play("jump",0);}if(InputMonitor.Instance().GetKeyBeginDown(cc.macro.KEY.s)){this.anim.play("dying",0);}}

Cocos Creator_实现策略_多点触控之触控管理器监听单例_TypeScript相关推荐

  1. Android系统辅助触控,辅助触控大师软件下载-辅助触控大师 安卓版v5.0.6-PC6安卓网...

    辅助触控大师app是一款好用的系统操作工具,辅助触控大师app可以方便用户快速操控手机,自动按键,还有录屏.截屏.手机加速(内存清理).音乐控制.全局手势操作等强大功能. 软件介绍 辅助触控大师app ...

  2. 【iOS-Cocos2d游戏开发之五】多触点与触屏事件详解(单一监听、事件分发)

    李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/iphone-cocos2d/450.html------- ...

  3. 【iOS-Cocos2d游戏开发之五】【2】多触点与触屏事件详解(单一监听、事件分发)...

    那么大概介绍了监听事件后,那么触屏中最关心的就应该是多触点啦: //-----获取多点触摸 NSSet *allTouches = [event allTouches]; UITouch *touch ...

  4. 【iOS-Cocos2d游戏开发之五】【1】多触点与触屏事件详解(单一监听、事件分发)...

    本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/iphone-cocos2d/450.html ...

  5. Android耳机线控详解,蓝牙耳机按钮监听(仿酷狗线控效果)

    转载请注明出处:http://blog.csdn.net/fengyuzhengfan/article/details/46461253 当耳机的媒体按键被单击后,Android系统会发出一个广播,该 ...

  6. redistemplate 设置失效时间_开发新技能之利用Redis高级用法监听过期键处理失效的订单...

    前言 最近项目区分了不同的订单类型,要求订单的失效时间不一样,比如活动订单的失效时间要短一些.由于之前订单的失效时间都是固定的,现在有些类型的订单过期时间发生变化.因此需要重新处理时效订单. 订单失效 ...

  7. java 鼠标滚轮监听事件_问题记录:JavaFx 鼠标滑轮滚动事件监听!

    setOnMouseDragged(event ->{//设定鼠标长按0.3秒后才可拖拽 防止误操作 isCanDrag =true; //(System.currentTimeMillis() ...

  8. 手机屏幕物理点击器是什么原理_手机屏幕为什么能触控 手机屏幕触控介绍【详解】...

    每天刷手机是我们的日常消闲时光的主要手段,但是手机屏幕为什么能触控及其原理你有没有考虑到?下面就由小编为大家解答一下手机屏幕为什么能触控及触控的原理. 触控屏 手机屏幕能触控由来已久,最早的一些功能性 ...

  9. STM32模拟USB多点触控屏

    STM32模拟USB多点触控屏 开发准备 STM32的USB官方例程库JoyStickMouse STM32F103RC Windows7 代码修改 1.usb_pwr.c RESULT PowerO ...

最新文章

  1. SQL执行过程中的性能负载点
  2. Ext.Ajax.request和formPanel.getForm().submit()两种提交方法的异同:
  3. php多文件上传类源码,PHP单文件上传类或多文件上传类源码
  4. Hibernate保存数据自动生成主键出现奇怪异常Duplicate entry '0' for key 1
  5. composer 更新版本
  6. KeeSoft.DBHelper.DBFactory 数据库访问类
  7. CVPR 2020 《Where Does It Exist: Spatio-Temporal Video Grounding for Multi-Form Sentences》论文笔记
  8. java学习(77):GUL下拉菜单框和滚动条
  9. MySQL 实现树形的遍历(关于多级菜单栏以及多级上下部门的查询问题)
  10. 用户访一个APP或者网页流程示意图
  11. .NET性能优化方面的总结(转)
  12. 站立会议01(冲刺2)
  13. Church's Coupon Performance Test Script
  14. 与你一起学习Microsoft Visio——基础篇
  15. dell n5110 触摸板驱动
  16. psd图层重命名,ps批量修改图层名字的脚本(附批量替换方法)
  17. 最小角回归算法(LARS)
  18. 复合索引的底层数据结构——最左原则
  19. 右键一直转圈圈(右键桌面和右键打开文件夹)的两种解决办法小总结
  20. 1000句最常用英语口语

热门文章

  1. js 验证手机号、密码、短信验证码
  2. 停车场系统无法连接服务器,手动挡停车场 联机版无法连接服务器是什么原因...
  3. Python+Appium移动端自动化测试框架实现
  4. java c rsa解秘_Java的RSA加密,.net如何解密
  5. 贷中篇|信贷监控报表的设计
  6. Excel工具 - 合并多个同类Excel
  7. Docker百度云下载链接
  8. 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】Linux内核抢占实现机制分析
  9. android 5.1 cdd,我似乎发现了一个5分杂志的秘密
  10. mac 查看mysql 端口_Mac下启动和停止Mysql及查看端口