转自:http://blog.csdn.net/fansongy/article/details/12716671

1、概述


    游戏也好,程序也好,仅仅有能与用户交互才有意义。手机上的交互大致能够分为两部分:点击和输入。当中点击更为重要,差点儿是游戏中所有的交互。在Cocos2d-x 3.0中。更改了dispatch机制。同一时候增加了两种新的交互形式:listener 和touchEvent回调。

加上先前版本号中的点击函数回调,与重写layer层的touch消息响应,构成了一个相对完整的交互模式。

先上一张Demo的图:



2、四种点击


1、函数回调

函数回调是最简单的响应形式。一直以来被用于MenuItem中的点击处理。

在新版本号中,此处发生了些小改变。我们能够看到在生成的程序中相关代码是这种:


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

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

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

此种方式已经被舍弃,能够使用第四种方法做替代。

2、Layer的touch消息响应

     尽管重写了底层的dispatch,但对这层的使用影响并不大。

我们相同须要重写:

  1. //单点响应
  2. virtual bool onTouchBegan(Touch* touch, Event  *event) override;
  3. virtual void onTouchMoved(Touch* touch, Event  *event) override;
  4. virtual void onTouchEnded(Touch* touch, Event  *event) override;
  5. virtual void onTouchCancelled(Touch *touch, Event *event) override;
  6. //多点响应
  7. virtual void onTouchesBegan(const std::vector<Touch*>& touches, Event *unused_event);
  8. virtual void onTouchesMoved(const std::vector<Touch*>& touches, Event *unused_event);
  9. virtual void onTouchesEnded(const std::vector<Touch*>& touches, Event *unused_event);
  10. virtual void onTouchesCancelled(const std::vector<Touch*>& touches, Event *unused_event);

重写这些函数来对layer的点击做处理。当然。我们须要:

  1. setTouchEnabled(true)。

此外有个小修改。对于单点触控响应,能够调用:

  1. //设置为单点响应
  2. setTouchMode(Touch::DispatchMode::ONE_BY_ONE);
  3. //设置为多点响应(默认)
  4. setTouchMode(Touch::DispatchMode::ALL_AT_ONCE);

进行设置,而不须要再用设置Delegate的方式来做了。

3、TouchEvent响应

    这是新增加的响应方式。它主要是使用在UIWidget上的。能够将其看做是函数回调的一个扩展。为很多其它的响应处理提供可能。用法大致是:

  1. //声明
  2. void touchButton(Object* object,TouchEventType type);
  3. //挂接到控件上
  4. uiButton->addTouchEventListener(this,toucheventselector(HelloWorld::touchButton));
  5. //实现
  6. void HelloWorld::touchButton(Object* object,TouchEventType type)
  7. {
  8. LabelTTF* label;
  9. switch (type)
  10. {
  11. case TouchEventType::TOUCH_EVENT_BEGAN:
  12. label = static_cast<LabelTTF*>(getChildByTag(11));
  13. label->setString("按下button");
  14. break;
  15. case TouchEventType::TOUCH_EVENT_MOVED:
  16. label = static_cast<LabelTTF*>(getChildByTag(11));
  17. label->setString("按下button移动");
  18. break;
  19. case TouchEventType::TOUCH_EVENT_ENDED:
  20. label = static_cast<LabelTTF*>(getChildByTag(11));
  21. label->setString("放开button");
  22. break;
  23. case TouchEventType::TOUCH_EVENT_CANCELED:
  24. label = static_cast<LabelTTF*>(getChildByTag(11));
  25. label->setString("取消点击");
  26. break;
  27. default:
  28. break;
  29. }
  30. }

由于全部的UIWidget都要加入到UILayer上。而UILayer通常作为UI的Widget都会在最上层,所以能够“基本上”觉得这样的使用方式会优先于其它方式处理点击消息。由于UILayer也会有层级的改变,比方它和MenuItem之间的关系。所以说“基本上”。

4、Listener消息响应方式

这样的实现也是新增加的。它更像是点击的一个层次过滤器。点击时,在listener队里中进行过滤。每个listener检查自己保存的touch消息响应是否会被触发。

一层一层过滤,最后在到Layer的touch消息响应。

我认为它的设计的初衷是为随意sprite提供一套自己制定的点击响应。但这种实现仍然要写非常多条件推断。没有可以控件化。可能我的理解有些偏差,欢迎讨论。

它被设计成一个全局点击响应控制。详细的使用方法大致是这样:

  1. //auto dispatcher = EventDispatcher::getInstance();
  2. //  auto myListener = EventListenerTouch::create(Touch::DispatchMode::ONE_BY_ONE);
  3. auto dispatcher = Director::getInstance()->getEventDispatcher();
  4. auto myListener = EventListenerTouchOneByOne::create();
  5. //假设不增加此句消息依然会向下传递
  6. myListener->setSwallowTouches(true);
  7. myListener->onTouchBegan = [=](Touch* touch,Event* event)
  8. {
  9. //some check
  10. if (pass)
  11. {
  12. return true;
  13. }
  14. return false;
  15. };
  16. myListener->onTouchMoved = [=](Touch* touch,Event* event)
  17. {
  18. //do something
  19. };
  20. myListener->onTouchEnded = [=](Touch* touch,Event* event)
  21. {
  22. //do something
  23. };
  24. dispatcher->addEventListenerWithSceneGraphPriority(myListener,mySprite1);
  25. dispatcher->addEventListenerWithSceneGraphPriority(myListener,mySprite2);

在这里相同会用到CC_CALLBACK_x函数。

其原理是在dispatcher中检查listener列表,比如myListener或加进来的其它listener。然后每一个listener检查自己中的Item看是否能达到检查条件,比如:mySprite1,mySprite2。

然后运行对应的操作。但这种话,当控件非常多的时候,每一次事件都进行这种双链表的检查操作不知会不会影响些性能?

3、实例

光说不练假把式,于是就动手写了一个上面的Demo:

点击背景区域能够移动整个场景。点击蓝色小方块能够半透明移动它,点击蓝色button能够更改文字。显示状态。点击右下角button退出程序。

项目配置可參照:

Cocos2d-x 3.0
开发(十六)cocos2dx-3.0beta版建立新项目并载入CocoStudio导出文件

4、总结

依据不同的交互须要。选择不同的实现方式,会更有利于我们的维护和扩展,对应样例能够在以下下载。

Demo下载:http://download.csdn.net/detail/fansongy/6399291 不要资源分,认为好劳烦点下 “顶” ~

Demo For Beta2 下载:http://download.csdn.net/detail/fansongy/6892047

关于cocos2d-x 3.0的点击交互处理的更多相关文章

  1. 高屋建瓴 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 ...

  2. TextView + Spanned实现图文混排以及图片点击交互

    最近要实现图文混排的需求,webview过大,所以想到了用SpannableStringBuilder来实现. 不过参考了大量国内文章,大多数是教你如何实现图文混排,并没有提及图片点击交互的.有翻阅了 ...

  3. 微信小程序开发--模板(template)使用,数据加载,点击交互

    微信小程序视图层提供了 模板(template),可以在模板中定义代码片段,然后在不同的地方调用.结果在数据渲染那懵逼了.按照官网上对模板的说明和对数据的加载. 1.定义模板 使用name属性,作为模 ...

  4. WPF 3D Cube及点击交互

    在WPF中构建一个简单的立方体比较容易实现,可参考资料也比较众多.比较麻烦的是处理点击交互. 我在WPF中用两种方式实现了3DCube,效果图如下: 方式一: 最常见的3D内容构建模式,结构如下图. ...

  5. IOS 小组件(7):小组件点击交互

    引言   前面我们似乎掌握了实现一个小组件所需要的一切技能,默认情况下桌面点击小组件,也正常跳转到了App中.接下来我们一起来看看,小组件是怎么做到点击跳转到App的. 点击交互方式 点击Widget ...

  6. Cocos2D将v1.0的tileMap游戏转换到v3.4中一例(八)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 回到Xcode中,新建一个EndLayer类,继承于CCNode ...

  7. Cocos2D将v1.0的tileMap游戏转换到v3.4中一例(六)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 在Xcode中打开MainScene.h文件,在接口中添加2个方 ...

  8. Cocos2D将v1.0的tileMap游戏转换到v3.4中一例(四)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 现在打开MainScene.m文件,首先设置实例变量: @imp ...

  9. Cocos2D将v1.0的tileMap游戏转换到v3.4中一例(一)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 首先说一下为什么要转换,这是为了后面的A*寻路算法做准备.由于在 ...

随机推荐

  1. D. Frequent values

    D. Frequent values Time Limit: 3000ms Case Time Limit: 3000ms Memory Limit: 131072KB   64-bit intege ...

  2. 【转】Python3学习笔记(urllib模块的使用)

    原文地址:https://www.cnblogs.com/Lands-ljk/p/5447127.html 1.基本方法 urllib.request.urlopen(url, data=None,  ...

  3. PTA 07-图6 旅游规划 (25分)

    题目地址 https://pta.patest.cn/pta/test/15/exam/4/question/717 5-9 旅游规划   (25分) 有了一张自驾旅游路线图,你会知道城市间的高速公路 ...

  4. Unity3D for iOS初级教程:Part 3/3

    转自Unity 3D for iOS 这篇文章还可以在这里找到 英语 Learn how to use Unity to make a simple 3D iOS game! 这份教程是由教程团队成员 ...

  5. HDU 3001 Travelling ——状压DP

    [题目分析] 赤裸裸的状压DP. 每个点可以经过两次,问经过所有点的最短路径. 然后写了一发四进制(真是好写) 然后就MLE了. 懒得写hash了. 改成三进制,顺利A掉,时间垫底. [代码] #in ...

  6. 路飞学城详细步骤 part2

    一 显示课程列表 需求:当你点击课程,course.vue在 <router-view>渲染,并不需要你进行其他点击,所欲的课程列表直接在前端显示,数据是从数据库拿到的. 补充1:生命周期 ...

  7. centos 7如何配置网络、网卡、ip命令

    Linux网络相关配置文件 Linux网络配置相关的文件根据不同的发行版目录名称有所不同,但大同小异,主要有似下目录或文件. (1)/etc/hostname:主要功能在于修改主机名称. (2)/et ...

  8. python结构语句(while,if)

    一.基础语法 编码: 默认情况下,Python 3 源码文件以 UTF-8 编码,所有字符串都是 unicode 字符串 #!/usr/bin/env python # -*- coding:utf- ...

  9. Scrapy学习-7-数据存储至数据库

    使用MySQL数据库存储 安装mysql模块包 pip install mysqlclient 相关库文件 sudo apt-get install libmysqlclient-devel sudo ...

  10. BZOJ——1610: [Usaco2008 Feb]Line连线游戏

    http://www.lydsy.com/JudgeOnline/problem.php?id=1610 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 2 ...