[cocos2d-x 3.6]如何实现“侦听触摸事件和侦听按键事件”,触摸回调函数分别在什么情况下执行
2015-09-21 00:02
1151 查看
在以往的版本中,侦听触摸事件是这样写代码的:
在新版本中,上面这套做法被抛弃了。
在新版本中,有一个进化是,只要是Node的派生类都可以侦听触摸事件,也可以侦听按键事件,不再是只有CCLayer的派生类才能侦听。
在新版本中,侦听触摸事件要这样写:(回调函数不再是覆盖基类的虚函数)
相应的,侦听按键事件也不再是调用 setKeyboardEnabled() 函数了,新的写法是这样:
可以看到,新版本中使用了一系列的EventListener的派生类
class CC_DLL EventListenerAcceleration : public EventListener
class CC_DLL EventListenerCustom : public EventListener
class CC_DLL EventListenerFocus : public EventListener
class CC_DLL EventListenerKeyboard : public EventListener
class CC_DLL EventListenerMouse : public EventListener
class CC_DLL EventListenerTouchOneByOne : public EventListener
class CC_DLL EventListenerTouchAllAtOnce : public EventListener
====================================================================================
触摸回调函数,在什么情况下会触发:
ccTouchBegan:触摸开始,返回true可以使得该触摸点属于该函数的目标对象,该点的变化只会影响该目标对象函数调用,不会影响其他对象。
ccTouchMoved:触摸点移动。
ccTouchEnded:触摸动作结束。
ccTouchCancelled:系统中断通知需要取消触摸事件的时候会调用此函数,这个中断往往是因为应用长时间没有响应或者当前视图从系统的顶层上移除了。
注意1,在ccTouchBegan返回时返回true,可以让这个触点属于这个函数的所属对象,并且其他对象不再接收该触点,这样之后再获得的触摸点肯定是它自己。这样就省去了你对多点触控时的判断。
注意2,有很多人认为手指移出屏幕或者目标对象的范围就会触发ccTouchCancelled,但是这种情况下调用的依然是ccTouchEnded函数。事实上,系统中断通知需要取消触摸事件的时候会调用ccTouchCancelled,这个中断被调用往往是因为出现如下几种情况:
a、应用长时间没有响应或者当前视图从系统的顶层上移除。
b、程序进入后台时,有可能是来点中断、电量低中断和部分机型上的Home键被按下。
c、屏幕关闭和触摸的时候,某种原因导致距离传感器工作,比如:脸靠近。
d、部分触摸权限覆盖了本应用的触摸权限。
注意3,触摸的优先级决定了触摸的分发顺序。触摸分发只和布景层的触摸优先级有关,和布景层的渲染顺序(zOrder)完全没有关系。哪怕是同样的触摸的优先级,也有可能底下一层先收到触摸,上面那层才接收到。所以处理不同层之间的触摸关系时,必须通过确定触摸优先级来实现这些层之间触摸点的处理顺序。优先级相同时数组里是乱序的,非插入顺序。
注意4,“吞噬”触摸点,如果在本布景层吞噬掉相应的触摸点,那么比它权限低的全都收不到触摸分发。
class A : public CCLayer { virtual bool init(); virtual bool onTouchBegan(Touch *touch, Event *unused_event); virtual void onTouchMoved(Touch *touch, Event *unused_event); virtual void onTouchEnded(Touch *touch, Event *unused_event); virtual void onTouchCancelled(Touch *touch, Event *unused_event); };
bool A::init() { setTouchEnabled(true); } bool A::onTouchBegan(Touch *touch, Event *unused_event) { .... } void A::onTouchMoved(Touch *touch, Event *unused_event) { .... } void A::onTouchEnded(Touch *touch, Event *unused_event) { .... } void A::onTouchCancelled(Touch *touch, Event *unused_event) { .... }
在新版本中,上面这套做法被抛弃了。
在新版本中,有一个进化是,只要是Node的派生类都可以侦听触摸事件,也可以侦听按键事件,不再是只有CCLayer的派生类才能侦听。
在新版本中,侦听触摸事件要这样写:(回调函数不再是覆盖基类的虚函数)
class B : public Node { virtual bool init(); bool myTouchBegan(Touch *touch, Event *unused_event); void myTouchMoved(Touch *touch, Event *unused_event); void myTouchEnded(Touch *touch, Event *unused_event); void myTouchCancelled(Touch *touch, Event *unused_event); };
bool B::init() { EventListenerTouchOneByOne* listener = EventListenerTouchOneByOne::create(); listener->setSwallowTouches(true); listener->onTouchBegan = CC_CALLBACK_2(B::myTouchBegan, this); listener->onTouchMoved = CC_CALLBACK_2(B::myTouchMoved, this); listener->onTouchEnded = CC_CALLBACK_2(B::myTouchEnded, this); listener->onTouchCancelled = CC_CALLBACK_2(B::myTouchCancelled, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); } bool B::myTouchBegan(Touch *touch, Event *unused_event) { .... } void B::myTouchMoved(Touch *touch, Event *unused_event) { .... } void B::myTouchEnded(Touch *touch, Event *unused_event) { .... } void B::myTouchCancelled(Touch *touch, Event *unused_event) { .... }
相应的,侦听按键事件也不再是调用 setKeyboardEnabled() 函数了,新的写法是这样:
class C : public Node { virtual bool init(); void myKeyPressed(EventKeyboard::KeyCode keyCode, Event* event); void myKeyReleased(EventKeyboard::KeyCode keyCode, Event* event); };
bool C::init() { EventListenerKeyboard* listener = EventListenerKeyboard::create(); listener->onKeyPressed = CC_CALLBACK_2(UILayerKeyListener::myKeyPressed, this); listener->onKeyReleased = CC_CALLBACK_2(UILayerKeyListener::myKeyReleased, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); } void C::myKeyPressed(EventKeyboard::KeyCode keyCode, Event* event) { .... } void C::myKeyReleased(EventKeyboard::KeyCode keyCode, Event* event) { .... }
可以看到,新版本中使用了一系列的EventListener的派生类
class CC_DLL EventListenerAcceleration : public EventListener
class CC_DLL EventListenerCustom : public EventListener
class CC_DLL EventListenerFocus : public EventListener
class CC_DLL EventListenerKeyboard : public EventListener
class CC_DLL EventListenerMouse : public EventListener
class CC_DLL EventListenerTouchOneByOne : public EventListener
class CC_DLL EventListenerTouchAllAtOnce : public EventListener
====================================================================================
触摸回调函数,在什么情况下会触发:
ccTouchBegan:触摸开始,返回true可以使得该触摸点属于该函数的目标对象,该点的变化只会影响该目标对象函数调用,不会影响其他对象。
ccTouchMoved:触摸点移动。
ccTouchEnded:触摸动作结束。
ccTouchCancelled:系统中断通知需要取消触摸事件的时候会调用此函数,这个中断往往是因为应用长时间没有响应或者当前视图从系统的顶层上移除了。
注意1,在ccTouchBegan返回时返回true,可以让这个触点属于这个函数的所属对象,并且其他对象不再接收该触点,这样之后再获得的触摸点肯定是它自己。这样就省去了你对多点触控时的判断。
注意2,有很多人认为手指移出屏幕或者目标对象的范围就会触发ccTouchCancelled,但是这种情况下调用的依然是ccTouchEnded函数。事实上,系统中断通知需要取消触摸事件的时候会调用ccTouchCancelled,这个中断被调用往往是因为出现如下几种情况:
a、应用长时间没有响应或者当前视图从系统的顶层上移除。
b、程序进入后台时,有可能是来点中断、电量低中断和部分机型上的Home键被按下。
c、屏幕关闭和触摸的时候,某种原因导致距离传感器工作,比如:脸靠近。
d、部分触摸权限覆盖了本应用的触摸权限。
注意3,触摸的优先级决定了触摸的分发顺序。触摸分发只和布景层的触摸优先级有关,和布景层的渲染顺序(zOrder)完全没有关系。哪怕是同样的触摸的优先级,也有可能底下一层先收到触摸,上面那层才接收到。所以处理不同层之间的触摸关系时,必须通过确定触摸优先级来实现这些层之间触摸点的处理顺序。优先级相同时数组里是乱序的,非插入顺序。
注意4,“吞噬”触摸点,如果在本布景层吞噬掉相应的触摸点,那么比它权限低的全都收不到触摸分发。
相关文章推荐
- cocos2d-x Scale9Sprite的使用方法 lua篇
- cocos2d-x 简单实现RPG游戏中的事件触发(C++)
- Cocos2d-x Studio (一) ----- 随机数实现(产生 start 到 end 的随机数)
- cocos3.8屏幕截图
- cocos2dx安卓平台横竖屏设置
- Quick-cocos2d-x3.3 Study (十五)--------- 为小鸟添加一个物理加速度
- Cocos2d-x数据持久-变更数据
- cocos2dX——HelloGame项目的创建
- Quick-cocos2d-x3.3 Study (十四)--------- 遍历 TiledMap 中的对象层,并取得所有坐标
- Cocos2d-x学习笔记之常用的宏
- Cocos2dx使用luaJavaBridge注意事项
- Cocos2dx 3.0rc之单点触屏响应 和 多点触屏响应
- Cocos2dx 3.0 过渡篇(三) 触摸机制
- cocos2d-x 中添加显示文字的三种方式 LabelTTF 、LabelBMFont 和 LabelAtlas
- Cocos2d-x3.0游戏实例《不要救我》三——背景滚动周期
- 【Cocos2d-x】Mac 在 Cocos2d-x 3.X 打包Android
- Cocos2d-x 周边工具 之 BMFont
- Cocos2d-x 3.0 lua规划 真正的现在Android在响应Home密钥和Back纽带
- 利用观察者模式实现Cocos2DX-lua游戏中的消息管理系统
- cocos2d-x触摸事件优先级