一、基本使用
addTouchEventListener
是属于Widget
下的触摸事件相关的操作,基本使用规则如下:
var button = new ccui.Button()
button.addTouchEventListener(this.touchEvent, this)
touchEvent: function (sender, type) {
switch (type) {
case ccui.Widget.TOUCH_BEGAN:
this._topDisplayLabel.setString("Touch Down");
break;
case ccui.Widget.TOUCH_MOVED:
this._topDisplayLabel.setString("Touch Move");
break;
case ccui.Widget.TOUCH_ENDED:
this._topDisplayLabel.setString("Touch Up");
break;
case ccui.Widget.TOUCH_CANCELED:
this._topDisplayLabel.setString("Touch Cancelled");
break;
default:
break;
}
}
二、为何改善
现在的触摸事件只做监听,并没有相关逻辑上的判断,我们游戏在开发的过程中遇到一些不正常点击而导致的问题。例如:在场景跳转的时候,连续点击两次后,会push两场同样的场景,正常逻辑应该是只push一次。
三、如何改善
先看我在基于原事件基础上添加的一些类型:
ccui.Widget.TOUCH_TYPE_TIMELY = 1 //及时:随时点击,随时响应
ccui.Widget.TOUCH_TYPE_DELAY_AFTER = 2 //延时:随时点击,点击后马上响应,延时一段时间后,响应下次点击
ccui.Widget.TOUCH_TYPE_DELAY_FRONT = 3 //延时:每次onEnter时,延时一段时间后,才能响应点击
ccui.Widget.TOUCH_TYPE_ONCE = 4 //一次:只有一次点击机会,点击后对象触摸禁止,当onExit后恢复
ccui.Widget.TOUCH_TYPE_ALL_BAN = 5 //所有:只有一次点击机会,点击后全屏触摸禁止,当onExit后恢复
ccui.Widget.TOUCH_TYPE_DELAY_FRONT_AND_ALL_BAN = 11 //兼具:DELAY_FRONT和ALL_BAN
代码如下:
ccui.Widget.prototype.addTouch = function(_func,_type,_time){
var __type = _type || ccui.Widget.TOUCH_TYPE_TIMELY
var __time = _time || 1
switch (__type){
case ccui.Widget.TOUCH_TYPE_TIMELY:
this.addTouchEventListener(_func)
break
case ccui.Widget.TOUCH_TYPE_DELAY_AFTER:
//当触发点击事件时,将按钮的可触性设置为false,用delayTime延迟1秒后再设置为true
var that = this
var __func = function(_sender,_type){
switch(_type){
case ccui.Widget.TOUCH_ENDED:
that.setTouchEnabled(false)
_func(_sender,_type)
that.runAction(cc.sequence(cc.delayTime(__time),cc.callFunc(function(){
that.setTouchEnabled(true)
}.bind(that))))
break
}
}
this.addTouchEventListener(__func)
break
case ccui.Widget.TOUCH_TYPE_DELAY_FRONT:
//在onEnter事件中,将按钮的可触性设置为false,然后delayTime延迟1秒后再设置为true
this.setOnEnterCallback(function(){
this.setTouchEnabled(false)
this.runAction(cc.sequence(cc.delayTime(__time),cc.callFunc(function(){
this.setTouchEnabled(true)
}.bind(this))))
}.bind(this))
if (_func == null){
return
}
var __func = function(_sender,_type){
switch(_type){
case ccui.Widget.TOUCH_ENDED:
_func(_sender,_type)
break
}
}
this.addTouchEventListener(__func)
break
case ccui.Widget.TOUCH_TYPE_ONCE:
//当触发点击事件时,将按钮的可触性设置为false,在onExit事件中设置为true
var that = this
var __func = function(_sender,_type){
switch(_type){
case ccui.Widget.TOUCH_ENDED:
that.setTouchEnabled(false)
_func(_sender,_type)
that.setOnExitCallback(function(){
that.setTouchEnabled(true)
}.bind(that))
break
}
}
this.addTouchEventListener(__func)
break
case ccui.Widget.TOUCH_TYPE_ALL_BAN:
//当触发点击事件时,在最上层添加一层遮罩,吞噬掉所有触摸,在onExit事件中移除遮罩
var that = this
var __func = function(_sender,_type){
switch(_type){
case ccui.Widget.TOUCH_ENDED:
gAddMask()
_func(_sender,_type)
that.setOnExitCallback(function(){
gRemoveMask()
}.bind(that))
break
}
}
this.addTouchEventListener(__func)
break
case ccui.Widget.TOUCH_TYPE_ALL_BAN_AND_DELAY_FRONT:
//组合,DELAY_FRONT和ALL_BAN
this.setOnEnterCallback(function(){
this.setTouchEnabled(false)
this.runAction(cc.sequence(cc.delayTime(__time),cc.callFunc(function(){
this.setTouchEnabled(true)
}.bind(this))))
}.bind(this))
var that = this
var __func = function(_sender,_type){
switch(_type){
case ccui.Widget.TOUCH_ENDED:
gAddMask()
_func(_sender,_type)
that.setOnExitCallback(function(){
gRemoveMask()
}.bind(that))
break
}
}
this.addTouchEventListener(__func)
break
default:
this.addTouchEventListener(_func)
break
}
}
遮罩层的实现:
function gAddMask(){
var __scene = cc.director.getRunningScene()
var __mask_layer = __scene.getChildByName("MaskLayer")
if(!__mask_layer){
__mask_layer = new MaskLayer()
__scene.addChild(__mask_layer,99999)
__mask_layer.setName("MaskLayer")
}else{
__mask_layer.setSwallowTouches(true)
}
}
function gRemoveMask(){
var __scene = cc.director.getRunningScene()
var __mask_layer = __scene.getChildByName("MaskLayer")
if(__mask_layer){
__mask_layer.setSwallowTouches(false)
}
}
var MaskLayer = cc.Layer.extend({
ctor:function(){
this._super()
cc.log("wade MaskLayer ctor")
this.listener = cc.EventListener.create({
event: cc.EventListener.TOUCH_ONE_BY_ONE,
swallowTouches: true,
onTouchBegan: function (touch, event) {
cc.log("wade MaskLayer onTouchBegan")
return true
},
onTouchMoved:function (touch, event){
cc.log("wade MaskLayer onTouchMoved")
},
onTouchEnded:function (touch, event){
cc.log("wade MaskLayer onTouchEnded")
},
})
cc.eventManager.addListener(this.listener, this);
},
setSwallowTouches:function(_bool){
this.listener.setSwallowTouches(_bool)
}
})
有了以上方法,当我们想创建一个场景跳转并且入场延时响应的按键时:
this.btn_challenge.addTouch(this.startChallenge.bind(this),ccui.Widget.TOUCH_TYPE_DELAY_FRONT_AND_ALL_BAN)
这时候,当连续多次点击这个挑战按钮时,只会进入战斗一次,而原方法会多次进入战斗,并且在onEnter后1秒之后才会响应触摸。