cocos2d-x 3.0点击响应

迄今为止,发现cocos2d-x 3.0最让人惊艳的地方就是更改了点击事件机制。(ps:迄今只看了点击事件这块,捂嘴笑~~~)

cocos2d-x 2.0 只有CCLayer有点击事件处理,需要注册,需要实现onTouchBegan等方法,最坑爹的就是按照优先级来传递点击事件,让人诟病不已。每次遇到由于优先级而造成的点击bug,都有一种崩溃之感。

让人高兴的是,从现在开始,这种情况应该就会很少遇到了。闲话不说,开始正文。

3.0版本中,处理点击事件有两种方式:

1、函数回调

函数回调是最简单的响应形式,一直以来被用于MenuItem中的点击处理。在新版本中,此处发生了些小改变,也就是采用了CC_CALLBACK系列,有不明白的可以去看帖子:c++11特性与cocos2d-x 3.0之std::bind与std::function

 1 // a selector callback
 2 void menuCloseCallback(Object* pSender);
 3
 4 auto closeItem = MenuItemImage::create("CloseNormal.png","CloseSelected.png",
 5                         CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
 6
 7 void HelloWorld::menuCloseCallback(Object* pSender)
 8 {
 9     Director::getInstance()->end();
10
11 #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
12     exit(0);
13 #endif
14 }

其中CC_CALLBACK_1宏是将函数与对象绑定在一起,1表示这个函数有一个参数。当点击这个按钮时,会调用这个回调函数。

除了基于c++11的这个形式的改变,使用方法与先前相同。

2、Listener消息响应方式

Listener的加入,使得Sprite可以很方便的就可以拥有处理点击事件的能力。再也不用为了写个能够响应事件的Sprite而让去继承Layer了。总觉得class TestSprite : public CCLayer这种定义Sprite的方式是坑人的一种做法。终于可以将其摒弃了。

3.0版本,只需要为Sprite创建一个Listener,然后将Listener与Sprite绑定,并添加到Listener队列内即可,方便至极。

另,每一个Listener也只能和一个Sprite进行绑定,而Listener的clone方法,可以很方便的将listener复制为其他对象可用的listener。

废话少说,上代码最重要:

 1 #ifndef  __Touchable_Sprite_Test_H__
 2 #define  __Touchable_Sprite_Test_H__
 3
 4 #include "cocos2d.h"
 5 USING_NS_CC;
 6
 7 class TouchableSpriteTest : public Layer
 8 {
 9 public:
10     CREATE_FUNC(TouchableSpriteTest);
11     virtual void onEnter() override;
12     virtual void onExit() override;
13 };
14
15 #endif
 1 #include "TouchableSpriteTest.h"
 2
 3 void TouchableSpriteTest::onEnter()
 4 {
 5     Layer::onEnter();
 6     Point origin = Director::getInstance()->getVisibleOrigin();
 7     Size size = Director::getInstance()->getVisibleSize();
 8
 9     auto containerForSprite1 = Node::create();
10     this->addChild(containerForSprite1, 10);
11     auto sprite1 = Sprite::create( "images/CyanSquare.png" );
12     sprite1->setPosition( origin + Point( size.width * 0.5, size.height * 0.5) + Point( -80, 80 ) );
13     containerForSprite1->addChild(sprite1);
14
15     auto sprite2 = Sprite::create("images/MagentaSquare.png");
16     sprite2->setPosition(origin+Point(size.width/2, size.height/2));
17     addChild(sprite2, 20);
18
19     auto sprite3 = Sprite::create("images/YellowSquare.png");
20     sprite3->setPosition(Point(0, 0));
21     sprite2->addChild(sprite3, 1);
22     // Make sprite1 touchable
23     auto listener1 = EventListenerTouchOneByOne::create();
24
25     listener1->setSwallowTouches(true);
26
27     listener1->onTouchBegan = [](Touch* touch, Event* event){
28         auto target = static_cast<Sprite*>(event->getCurrentTarget());
29
30         Point locationInNode = target->convertToNodeSpace(touch->getLocation());
31         Size s = target->getContentSize();
32         Rect rect = Rect(0, 0, s.width, s.height);
33
34         if (rect.containsPoint(locationInNode))
35         {
36             log("sprite began... x = %f, y = %f", locationInNode.x, locationInNode.y);
37             target->setOpacity(180);
38             return true;
39         }
40         return false;
41     };
42
43     listener1->onTouchMoved = [](Touch* touch, Event* event){
44         auto target = static_cast<Sprite*>(event->getCurrentTarget());
45         target->setPosition(target->getPosition() + touch->getDelta());
46     };
47
48     listener1->onTouchEnded = [=](Touch* touch, Event* event){
49         auto target = static_cast<Sprite*>(event->getCurrentTarget());
50         log("sprite onTouchesEnded.. ");
51         target->setOpacity(255);
52         if (target == sprite2)
53         {
54             containerForSprite1->setLocalZOrder(100);
55         }
56         else if(target == sprite1)
57         {
58             containerForSprite1->setLocalZOrder(0);
59         }
60     };
61
62     _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);
63     _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2);
64     _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite3);
65
66     Rect s_visibleRect = Director::getInstance()->getOpenGLView()->getVisibleRect();
67     Point right = Point(s_visibleRect.origin.x+s_visibleRect.size.width, s_visibleRect.origin.y+s_visibleRect.size.height/2);
68
69     auto removeAllTouchItem = MenuItemFont::create("Remove All Touch Listeners ",[&]( Ref* sender ){
70         auto senderItem = static_cast<MenuItemFont*>(sender);
71         senderItem->setString("Only next item could be clicked ");
72
73         _eventDispatcher->removeEventListenersForType( EventListener::Type::TOUCH_ONE_BY_ONE );
74
75         auto nextItem = MenuItemFont::create("Next", [&](Ref* sender){
76         });
77
78         nextItem->setFontSizeObj(16);
79         nextItem->setPosition(right + Point(-100, -30));
80
81         auto menu2 = Menu::create(nextItem, NULL);
82         menu2->setPosition(Point(0, 0));
83         menu2->setAnchorPoint(Point(0, 0));
84         this->addChild(menu2);
85     });
86     removeAllTouchItem->setFontSizeObj(16);
87     removeAllTouchItem->setPosition(right + Point(-100, 0));
88
89     auto menu = Menu::create(removeAllTouchItem, nullptr);
90     menu->setPosition(Point(0, 0));
91     menu->setAnchorPoint(Point(0, 0));
92     addChild(menu);
93 }
94
95 void TouchableSpriteTest::onExit()
96 {
97     Layer::onExit();
98 }

千里之行始于足下,一切才刚刚开始,想要理解cocos2dx 3.0的点击事件,还是需要深入理解其底层实现的。

大家可以去看  Cocos2d-X3.0 刨根问底(七)----- 事件机制Event源码分析   这应该是一篇好文。

另,本博文参考自:http://blog.csdn.net/fansongy/article/details/12716671

本博主对一切都将不负任何法律责任。

cocos2d-x 3.0点击响应

时间: 2024-10-29 00:49:05

cocos2d-x 3.0点击响应的相关文章

Cocos2d-x 3.0 点击交互的四种处理

1.概述 游戏也好,程序也好,只有能与用户交互才有意义.手机上的交互大致可以分为两部分:点击和输入.其中点击更为重要,几乎是游戏中全部的交互.在Cocos2d-x 3.0中,更改了dispatch机制.同时加入了两种新的交互形式:listener 和touchEvent回调.加上先前版本中的点击函数回调,与重写layer层的touch消息响应,构成了一个相对完整的交互模式.先上一张Demo的图: 2.四种点击 1.函数回调 函数回调是最简单的响应形式,一直以来被用于MenuItem中的点击处理.

高屋建瓴 cocos2d-x-3.0架构设计 Cocos2d (v.3.0) rendering pipeline roadmap(原文)

Cocos2d (v.3.0) rendering pipeline roadmap Why (the vision) The way currently Cocos2d does rendering is good but it is beginning to feel somehow antiquate and moreover it doesn't actually leverage modern multi core CPUs so popular nowadays on most mo

2019-11-29-WPF-非客户区的触摸和鼠标点击响应

原文:2019-11-29-WPF-非客户区的触摸和鼠标点击响应 title author date CreateTime categories WPF 非客户区的触摸和鼠标点击响应 lindexi 2019-11-29 08:44:11 +0800 2019-07-02 17:15:20 +0800 WPF 默认在 WPF 里面是不响应非客户区的鼠标事件,但响应触摸事件 在没有喝下午茶的时候 lsj 告诉我,在项目里面在一个定制的窗口里面的非客户区用鼠标点击不了一个按钮,但是用触摸可以点击按钮

点击响应之hit-TestView

前言:为什么我的UITextView无法滑动了? “当用户触发某一事件(触摸事件或运动事件)后,UIKit会创建一个事件对象(UIEvent),该对象包含一些处理事件所需要的信息.然后事件对象被放到一个事件队列中.这些事件按照先进先出的顺序来处理.当处理事件时,程序的UIApplication对象会从队列头部取出一个事件对象,将其分发出去.通常首先是将事件分发给程序的主window对象,对于触摸事件来讲,window对象会首先尝试将事件分发给触摸事件发生的那个视图上.这一视图通常被称为hit-t

安卓Dialog关闭空白区域及返回键点击响应

在Android开发中,常常需要调用对话框,但会遇到这样一种情况,在显示对话框的时候,点击对话框以外的屏幕其他区域,会关闭对话框,处理不当还可能引发如下异常. 本文主要针对对话框来说,我们不希望响应空白区域或返回键,则可以进行相应的设置: AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setCanceledOnTouchOutside(false);调用这个方法时,按对话框以外的地方不起作用.按返回

swift3.0 点击UIScrollView中输入框之外的区域关闭键盘

通过点击事件实现关闭键盘 scrollView: UIScrollView! title_textField: UITextField! let hideKeyboardTapGesture = UITapGestureRecognizer(target: self, action: #selector(hideKeyboardTapGesture(sender:))) scrollView.isUserInteractionEnabled = true scrollView.addGestur

最新版本号cocos2d&amp;#173;2.0&amp;#173;x&amp;#173;2.0.2使用新资源载入策略!不再沿用-hd、-

?? 前段时间cocos2dx更新了最新版本号cocos2d-2.0-x-2.0.2.也从这个版本号開始对于资源载入与管理都改变了策略. 在之前的载入方式都是通过沿用与cocos2d-iphone一样的载入资源方式,对于图片名后加入-hd,-ipad,-ipadhd方式,当用户开启项目的高清视网膜后就能够默认寻找相应的资源.可是从cocos2d-2.0-x-2.0.2版本号開始,资源载入策略不在如此了.对跨平台整合不清楚的请看cocos2dx最新2.x版本号跨平台整合NDK+Xcode 最新资源

解决VC6.0点击&quot;Add Files to Folder&quot;用不了问题

不知道从什么时候开始,VC6.0+sp6不听使唤了,表现为:在工程的Source Files(其他如Header Files相同)右键->"Add files to folder" 系统没有反应,同样在File->Open 也是没有任何反应.重新安装VC后现象依旧.通过网上搜索,发现出现这个问题的人还挺多,原因解释为:VC6.0与Offices2007有冲突. 如果想让VC6.0和Offices2007和平共处,则需要为VC6.0添加一个处理文件打开异常的动态链接库File

?重写SimpleAdapter的getView以实现按钮点击响应

SimpleAdapter是四个适配器里最重要的适配器,它不仅实现了数据的绑定,而且可以自定义控件. 在自定义控件时,如果使用了按钮.复选框.单选框等需要点击监听器的控件,就得重写SimpleAdapter的getView函数来实现. getView是用来刷新ListView的函数,每次在ListView里新增(新显示)一条记录时,getView就会被调用一次(在这次调用里,getView里就会对这条记录里的按钮设置监听器). 下面是示例: 这是重写的类:MySimpleAdapter,里面的c