摘要
在一部分游戏开发中,多点触控并不是被期望的。官方在 v2.3.0 版本时提供了单点触控的开关,但是并不能指定触点数量,且旧版本没法使用,那么可不可以实现这一功能呢?
正文
测试版本
CocosCreator 版本 2.0.5
CocosCreator 版本 2.1.2
CocosCreator 版本 2.3.4
CocosCreator 版本 2.4.2
思维过程
控制开关 cc.macro.ENABLE_MULTI_TOUCH
是新版才有的,想兼容旧版本还是要去更根源的地方找,跑到源码里先看看触摸事件最开始在哪里分发的!首先想到的是,既然在浏览器端可以进行点击,必然会走注册事件的方法,去源码里搜一下 window.addEventListener
,看了一下,果然有个翻译过来像输入的脚本 CCInputManager.js
。然后在这个脚本中搜一下 touchstart
果然找到了对应的方法:
/**
* @method handleTouchesBegin
* @param {Array} touches
*/
handleTouchesBegin (touches) {
let selTouch, index, curTouch, touchID,
handleTouches = [], locTouchIntDict = this._touchesIntegerDict,
now = sys.now();
for (let i = 0, len = touches.length; i < len; i ++) {
selTouch = touches[i];
touchID = selTouch.getID();
index = locTouchIntDict[touchID];
if (index == null) {
let unusedIndex = this._getUnUsedIndex();
if (unusedIndex === -1) {
cc.logID(2300, unusedIndex);
continue;
}
//curTouch = this._touches[unusedIndex] = selTouch;
curTouch = this._touches[unusedIndex] = new cc.Touch(selTouch._point.x, selTouch._point.y, selTouch.getID());
curTouch._lastModified = now;
curTouch._setPrevPoint(selTouch._prevPoint);
locTouchIntDict[touchID] = unusedIndex;
handleTouches.push(curTouch);
}
}
if (handleTouches.length > 0) {
this._glView._convertTouchesWithScale(handleTouches);
let touchEvent = new cc.Event.EventTouch(handleTouches);
touchEvent._eventCode = cc.Event.EventTouch.BEGAN;
eventManager.dispatchEvent(touchEvent);
}
}
代码的逻辑是处理传入的多个触点,为每个触点分配一个未使用的 id
,排好序后分发出去,我们想控制触点的数量,那么是不是可以从获取 未分配的 id
入手呢,我最多允许分配固定数量的 ID 是不是就可以控制最大触点数量?看下分配的方法:
_getUnUsedIndex () {
let temp = this._indexBitsUsed;
let now = cc.sys.now();
for (let i = 0; i < this._maxTouches; i++) {
if (!(temp & 0x00000001)) {
this._indexBitsUsed |= (1 << i);
return i;
}
else {
let touch = this._touches[i];
if (now - touch._lastModified > TOUCH_TIMEOUT) {
this._removeUsedIndexBit(i);
delete this._touchesIntegerDict[touch.getID()];
return i;
}
}
temp >>= 1;
}
// all bits are used
return -1;
}
分配时有个 this._touches
数组存储这些触点,经过一次 For 循环分配 ID,最多分配 this._maxTouches
个 ID。这样就明白了,干脆改掉 _maxTouches
就能限制分配的数量了,先改成一,然后拿手机扫码试试。成了!再搞成 0 试试,果然触摸失效了!!!完美!
更好的实现
魔改下引擎后,换项目或者引擎版本无法做到复用,有没有更好的办法呢?当然,插件脚本就能实现这个需求,在 CocosCreator 中脚本执行顺序为:Cocos2d 引擎最先执行,然后是插件脚本(有多个的话按项目中的路径字母顺序依次加载),最后才是我们写的普通脚本(打包后只有一个文件,内部按 require 的依赖顺序依次初始化)。
那就将这个修改写进 k-cocos.js
扩展脚本中,声明一个方法挂载到 cc
上吧,CCInputManager.js
脚本最末尾有着导出的逻辑:
module.exports = cc.internal.inputManager = inputManager;
不同的版本还不一样,新版是 cc.internal
,比较旧的版本是 _cc.inputManager
,那就只好做下兼容处理。
// 触点数量控制
cc.kMultTouch = function (count) {
// 2.3.0 版本以上
if (cc.internal && cc.internal.inputManager) {
cc.internal.inputManager._maxTouches = count;
return;
}
// 低版本
if (_cc && _cc.inputManager) {
_cc.inputManager._maxTouches = count;
}
// 低版本兼容 QQ_PLAY 的一段逻辑
if (CC_QQPLAY && BK && BK.inputManager) {
BK.inputManager._maxTouches = count;
}
}
结语
扩展脚本已经开源,实现了游戏速率控制、全局触点数量控制、也扩展了节点的一些属性和方法,还有许多想法没加进去,欢迎大家提建议、给点个星星 Star,欢迎加入讨论 QQ 群:1085201157
GitHub地址: https://github.com/KuoKuo666/k-cocos
个人网站:www.kuokuo666.com
2020!我们一起进步!O(∩_∩)O~~