【cocos2d-js官方文档】十七、事件分发机制
简介游戏开发中一个很重要的功能就是交互,如果没有与用户的交互,那么游戏将变成动画,而处理用户交互就需要使用事件监听器了。 总概:
如何使用呢? 首先需要创建一个事件监听器,事件监听器包含以下几种类型:
在监听器中实现各种事件的处理逻辑,然后将监听器加入到事件管理器中,当事件触发时,事件管理器会根据事件类型分发给相应的事件监听器。下面以一个简单的示例来演示使用的方法。 使用方法现在会在一个场景中添加三个按钮(cc.Sprite),三个按钮将会互相遮挡,并且都需要能够监听和处理触摸事件,以下是具体实现 首先创建三个精灵,作为三个按钮的显示图片 var sprite1 = new cc.Sprite("Images/CyanSquare.png");
sprite1.x = size.width/2 - 80;
sprite1.y height/+ 80;
this.addChild(sprite1,10);
var sprite2 "Images/MagentaSquare.png");
sprite2.2;
sprite2.2;
this.addChild(sprite2,179)">20);
var sprite3 "Images/YellowSquare.png");
sprite3.= 0;
sprite3.0;
sprite2.addChild(sprite3,179)">1);
创建一个单点触摸事件监听器(事件类型:TOUCH_ONE_BY_ONE),并完成逻辑处理内容 // 创建一个事件监听器 OneByOne 为单点触摸
var listener1 = cc.EventListener.create({
event: cc.EventListener.TOUCH_ONE_BY_ONE,swallowTouches: true,// 设置是否吞没事件,在 onTouchBegan 方法返回 true 时吞掉事件,不再向下传递。
onTouchBegan: function (touch,event) { //实现 onTouchBegan 事件处理回调函数
var target = event.getCurrentTarget(); // 获取事件所绑定的 target,通常是cc.Node及其子类
// 获取当前触摸点相对于按钮所在的坐标
var locationInNode = target.convertToNodeSpace(touch.getLocation());
var s = target.getContentSize();
var rect = cc.rect(0,s.width,179)">height);
if (cc.rectContainsPoint(rect,locationInNode)) { // 判断触摸点是否在按钮范围内
cc.log("sprite began... x = " + locationInNode.+ ",y = " y);
target.opacity 180;
return true;
}
false;
},onTouchMoved: event) { //实现onTouchMoved事件处理回调函数,触摸移动时触发
// 移动当前按钮精灵的坐标位置
event.getCurrentTarget();
var delta = touch.getDelta(); //获取事件数据: delta
target.+= delta.x;
target.y;
},163)">onTouchEnded: // 实现onTouchEnded事件处理回调函数
event.getCurrentTarget();
cc"sprite onTouchesEnded.. ");
target.setOpacity(255);
if (target == sprite2) {
sprite1.setLocalZOrder(100); // 重新设置 ZOrder,显示的前后顺序将会改变
} else == sprite1) {
sprite1.setLocalZOrder(0);
}
}
});
引擎提供了cc.EventListener.create统一来创建各类型的事件监听器,可以通过指定不同的 可选
将事件监听器添加到事件管理器中// 添加监听器到管理器
cc.eventManager.addListener(listener1,sprite1);
cc.eventManager.addListener(listener1.clone(),sprite2);
cc.eventManager.addListener(listener1.clone(),sprite3);
这里的cc.eventManager是一个单例对象,可直接拿来使用。通过调用 注意:这里当我们想给不同的节点使用相同的事件监听器时,需要使用 更快速的添加事件监听器到管理器的方式下面提交一种更快捷绑定事件到节点的方式, 不过这样做就不会得到监听器的引用,无法再对监听器进行其他操作,适用于一些简单的事件操作, 代码如下: cc.eventManager.addListener({
: cc.EventListener.TOUCH_ALL_AT_ONCE,163)">onTouchesMoved: function (touches,event) {
var touch = touches[0];
= touch.getDelta();
var node event.getCurrentTarget().getChildByTag(TAG_TILE_MAP);
var diff = cc.pAdd(delta,node.getPosition());
node.setPosition(diff);
}
},this);
cc.eventManager的 新的触摸机制 以上的步骤相对于 2.x 版本触摸机制实现,稍显复杂了点。在老的版本中只需在节点中重载 而新机制将事件处理逻辑独立出来,封装到一个 监听器(listner) 中,使得不同对象可以使用同一份监听器代码(使用 注意:与SceneGraphPriority所不同的是FixedPriority将会依据手动设定的 其它事件派发处理模块除了触摸事件响应之外,还可以使用相同的事件处理方式来处理其他事件。 键盘响应事件除了可以监听键盘按键,还可以是终端设备的各个菜单键,都能使用同一个监听器来进行处理。 //给statusLabel绑定键盘事件
cc.eventManager.addListener({
: cc.EventListener.KEYBOARD,163)">onKeyPressed: function(keyCode,event){
var label event.getCurrentTarget();
//通过判断keyCode来确定用户按下了哪个键
label.setString("Key " + keyCode.toString() " was pressed!");
},163)">onKeyReleased: event.getCurrentTarget();
label.setString(" was released!");
}
},statusLabel);
加速计事件在使用加速计事件监听器之前,需要先启用此硬件设备,代码如下: 然后将相应的事件处理监听器与sprite进行绑定就可以了,如下: cc.eventManager.addListener({
: cc.EventListener.ACCELERATION,163)">callback: function(acc,event){
//这里处理逻辑
}
},sprite);
鼠标响应事件对于PC和超级本,添加鼠标事件的的处理,可以加强用户的体验,其处理逻辑与触摸事件基本一样,多了一些鼠标特有的事件响应,如滚轮事件(onMouseScroll). : cc.EventListener.MOUSE,163)">onMouseMove: function(event){
var str = "MousePosition X: " + event.getLocationX() " Y:" event.getLocationY();
// do something...
},163)">onMouseUp: "Mouse Up detected,Key: " event.getButton();
onMouseDown: "Mouse Down detected,163)">onMouseScroll: "Mouse Scroll detected,X: " // do something...
}
},0)">this);
注意:由于在PC浏览器中,没有触摸事件,而此时强制要求用户写鼠标事件的响应代码,必然会让开发者多写很多代码,事实上触摸响应的逻辑与鼠标相差不大,所以引擎在检测到不支持触摸事件时,会让鼠标事件模拟成触摸事件进行分发,开发者只需编写触摸事件监听器就能完成大部分工作,而对于针对鼠标操作而设计的游戏,需要判断用户按下什么键,响应滚轮等,这就需要开发者编写鼠标事件监听器了。 (开发者反馈,鼠标事件监听器也需要有swallowTouches这个选项,我们将会有v3.1版本中加入这个项.) 自定义事件以上是系统自带的事件类型,这些事件由系统内部自动触发,如 触摸屏幕,键盘响应等,除此之外,还提供了一种 自定义事件,简而言之,它不是由系统自动触发,而是人为的干涉,如下: var _listener1 : cc.EventListener.CUSTOM,eventName: "game_custom_event1",93)">function(event){
// 可以通过getUserData来设置需要传输的用户自定义数据
statusLabel.setString("Custom event 1 received," event.getUserData() " times");
}
});
cc.eventManager.addListener(this._listener1,179)">1);
以上定义了一个 “自定义事件监听器”,实现了一些逻辑,并且添加到事件分发器。那么以上逻辑是在什么情况下响应呢?请看如下: ++this._item1Count;
var event cc.EventCustom("game_custom_event1");
event.setUserData(this._item1Count.toString());
cc.eventManager.dispatchEvent(event);
创建了一个自定义事件( cc.eventManager加入自定义事件的处理,开发者就可以很方便的使用该功能来实现观察者模式。 移除事件监听器我们可以通过以下方法移除一个已经被添加了的监听器。 cc.eventManager.removeListener(listener); //移除一个已添加的监听器
也可以使用 cc.eventManager.removeListeners(cc.EventListener.TOUCH_ONE_BY_ONE); //移除所有单点触摸事件监听器
cc.eventManager.removeListeners(aSprite); //移除所有与aSprite相关的监听器
事件管理器还提供了函数用来移除已注册的所有监听器。 cc.eventManager.removeAllListeners();
当使用 _注意:调用 暂停/恢复 与场景相关(SceneGraph类型)的监听器开发过程中,我们经常会遇到这样的情况:想要让一个Layer中所有的Node对象的事件都停止响应。 在响应用户事件后,又要恢复该Layer的所有事件响应。如: 用户想要显示一个模式对话框,显示对话框后,禁止对话框后所有对象的事件响应。 在用户关闭对话框后,又恢复这些对象的事件响应。 我们只需要暂停根node的事件,就可以让根节点以及其子节点暂停事件响应。 代码如下: cc.eventManager.pauseTarget(aLayer,179)">true); //让aLayer对象暂停响应事件
而恢复对象的事件响应也非常简单: cc.eventManager.resumeTarget(aLayer,179)">true); //让aLayer对象恢复响应事件
注意: 第二个参数为可选参数,默认值为false,表示是否递归调用子节点的暂停/恢复操作. 进阶话题SceneGraphPriority类型与FixedPriority类型详解事件管理器将监听器类型分为两大类:SceneGraphPriority和FixedPriority, 下面将会详细说明它们之间的区别, 并介绍FixedPriority的使用场景与使用方法。 SceneGraphPriority事件类型是指事件的响应优先级与监听器关联对象在场景中显示顺序(zOrder)相关, 比如一个精灵对象在场景的显示在最上层时,它对事件的响应优先级最高。 这样开发者就不需要再像v2.x中那样在场景对象的zOrder变化后,手动再调用 而FixedPriority事件类型则是相对于SceneGraphPriority来定义的,不需要与场景显示顺序相关的事件监听器 也就是优化级固定的(fixed),就可以注册成FixedPriority类型事件。 我们的SceneGraphPriority定义的系统优先级是0,在添加监听器( 那么什么情况下使用FixedPriority类型的监听器呢? 比如,一个冒险类的游戏中,游戏主角应该要最先响应触摸事件,而UI界面的按钮往往会安排在界面的最上层。但是,如果主角移动到了按钮的后面,这时点击游戏主角,如果游戏主角注册的是SceneGraphPriority类型监听器,响应的将会是按钮事件。而如果注册成FixedPriority类型,并把它的优先级设置为负数,将会响应游戏主角的事件。 有开发者反馈想保持他们在v2.x的响应优先级管理机制,因为他们有特殊的需求,那么这部分开发者也可以使用FixedPriority来管理, UI控件的事件处理详解Cocos提供一套UI控件,许多开发者对于控件的事件响应,特别是对于容器类控件(如:ccui.PageView,ccui.ScrollView)的事件响应有些疑惑。这里将详细说明控件的事件处理流程。 首先来看一下 this._touchListener : this.onTouchBegan.bind(this),onTouchMovedthis.onTouchMoved.bind(this.onTouchEnded.bind(this)
});
cc.eventManager.addListener(this._touchListener,sans-serif; font-size:16px; line-height:25.6000003814697px"> 然后看一下它的各事件响应函数,会发现每个函数都会有类似这样的语句: if (widgetParent) widgetParent.interceptTouchEvent(ccui.Widget.TOUCH_XXXXX,this,touch);
这句的意思是,在控件处理完自己的触摸事件之后,都会向父节点(widgetParent)发送事件响应通知。那么,interceptTouchEvent的实现是什么呢? 代码如下: interceptTouchEvent: function(eventType,sender,touch){
var widgetParent = this.getWidgetParent();
if (widgetParent)
widgetParent.interceptTouchEvent(eventType,sender,touch);
}
对于像ccui.Button,ccui.ImageView这样的控件,它只是简单的向父类发送事件通知就行了,而对于像ccui.PageView这样的容器类控件,会对这些通知做出响应,代码如下: function (eventType,touch) {
var touchPoint = touch.getLocation();
switch (eventType) {
case ccui.Widget.TOUCH_BEGAN:
this._touchBeganPosition.= touchPoint.x;
y;
break;
case ccui.Widget.TOUCH_MOVEDthis._touchMovePosition.y;
var offset 0;
offset Math.abs(sender.getTouchBeganPosition().- touchPoint.x);
if (offset > this._childFocusCancelOffset) {
sender.setFocused(false);
this._handleMoveLogic(touch);
}
case ccui.Widget.TOUCH_ENDED:
case ccui.Widget.TOUCH_CANCELEDthis._touchEndPosition.y;
this._handleReleaseLogic(touch);
break;
}
}
这样的处理,就能实现在按钮上滑动时,也能让其父节点的PageView触摸事件。不然,如果不采用这种机制,当一个PageView中填满了子控件时,PageView将无法响应触摸事件。 属性与方法列表cc.Event (事件类)
cc.EventCustom (自定义事件)cc.EventCustom继承自
cc.EventMouse (鼠标事件)cc.EventMouse继承自 |
scrollX, scrollY | 设置滚轮数据 | |||||||||||||||||||||
返回x轴滚轮数据 | |||||||||||||||||||||||
返回y轴滚轮数据 | |||||||||||||||||||||||
x,y | 设置鼠标光标位置 | ||||||||||||||||||||||
cc.Point | 获取鼠标光标位置 | ||||||||||||||||||||||
返回鼠标光标在屏幕上的位置 | |||||||||||||||||||||||
获取当前光标与上一光标的偏移量 | |||||||||||||||||||||||
button | 设置鼠标按键 | ||||||||||||||||||||||
获取鼠标按键 |
cc.EventTouch ()
cc.EventTouch继承自 创建EventListenerTouchOneByOne对象: event: cc.EventListener.TOUCH_ONE_BY_ONE 可选参数: 创建EventListenerTouchAllAtOnce对象: event: cc.EventListener.TOUCH_ALL_AT_ONCE
创建EventListenerKeyboard对象: event: cc.EventListener.KEYBOARD
创建EventListenerMouse对象: event: cc.EventListener.MOUSE
创建EventListenerAcceleration对象: event: cc.EventListener.ACCELERATION
创建EventListenerCustom对象: event: cc.EventListener.CUSTOM cc.eventManager
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!getEventCode
获取触摸事件类型代码: BEGAN,MOVED,ENDED,CANCELLED
getTouches
Array
获取触摸事件中所有点信息
cc.EventListener (事件监听器)
参数说明
checkAvailable
boolean
no
检测监听器是否有效
clone
cc.EventListener
克隆一个监听器,其子类会重写本函数
create
json object
通过json对象创建事件监听器
cc.EventListener.create
函数参数列表:
转载请注明:http://www.cocos2dx.net/post/232 pauseTarget
node,recursive(是否递归调用子类)
暂停传入的node相关的所有监听器的事件响应
resumeTarget
恢复传入的node相关的所有监听器的事件响应
addListener
json对象或cc.EventListener,node对象或优化值
向事件管理器添加一个监听器
addCustomListener
eventName,callback
向事件管理器添加一个自定义事件监听器
removeListener
listener
移除一个事件监听器
removeListeners
listenerType
cc.Node,recursive
removeCustomListeners
customEventName
移除同一事件名的自定义事件监听器
removeAllListeners
移除所有事件监听器
setPriority
listener,fixedPriority
设置FixedPriority类型监听器的优先集
setEnabled
enabled
是否允许分发事件
isEnabled
检测事件管理器是否分发事件
dispatchEvent
event
分发事件
dispatchCustomEvent
分发自定义事件