您的位置:首页 > 移动开发 > Cocos引擎

cocos2dx学习之路----第八篇(初识触摸机制中的单点触摸)

2016-07-25 22:23 459 查看
上一篇中介绍了坐标转换的问题,这一篇就来浅谈关于cocos2dx中比较重要的一个知识点-------触摸机制。

在游戏中,不仅仅只需要画面的变动,更多的是需要与其中的实体对象进行交互。PC端的游戏可以通过鼠标、键盘,而对于移动端更多的是用触摸。所以,这里所讲的触摸也基本针对移动端的。当然,往往在我们PC端开发过程中,鼠标能够当作一个触摸点来进行交互。但是,这远远不够的,毕竟移动端在触摸的时候肯定有多点的交互。

好了,说的那么多,我们就进入正题吧~

cocos2dx的触摸机制中,有单点触摸及多点触摸。这里先来说说单点的触摸。

我们先来看看我们需要做出什么效果,如下图所示:



通过上图可以看出,场景中有两个颜色方块,我们通过鼠标点击方块后移动鼠标可以拖动方块。移动后的方块可以显示在另外一个方块的上面,即覆盖它。

这是个简单的例子,在解释如何实现之前,我们需要知道要实现触摸大概的步骤,有三步:

1.创建触摸监听器;

2.为监听器分配相关的触摸回调方法;

3.分发监听器

好,现在就直接来看实现的源码吧:

TouchEventTest.h:

#ifndef __TOUCH_EVENT_TEST_H__
#define __TOUCH_EVENT_TEST_H__

#include "cocos2d.h"
USING_NS_CC;

class TouchEventTest : public Layer
{
public:
static Scene* createScene();
virtual bool init();
CREATE_FUNC(TouchEventTest);
};

#endif


TouchEventTest.cpp:

#include "TouchEventTest.h"

Scene* TouchEventTest::createScene()
{
auto scene = Scene::create();
auto layer = TouchEventTest::create();
scene->addChild(layer);

return scene;
}

bool TouchEventTest::init()
{
if ( !Layer::init() )
{
return false;
}
auto visibleSize = Director::getInstance()->getVisibleSize();
//方块一
LayerColor *layer1 = LayerColor::create(Color4B::RED, 100, 100);
this->addChild(layer1);
layer1->ignoreAnchorPointForPosition(false);<span style="white-space:pre">	</span>//不忽略锚点
layer1->setAnchorPoint(Vec2::ANCHOR_MIDDLE);<span style="white-space:pre">	</span>//设置锚点为中心点
layer1->setPosition(visibleSize.width / 2, visibleSize.height / 2);

//方块二
LayerColor *layer2 = LayerColor::create(Color4B::GREEN, 100, 100);
this->addChild(layer2);
layer2->ignoreAnchorPointForPosition(false);
layer2->setAnchorPoint(Vec2::ANCHOR_MIDDLE);
layer2->setPosition(Vec2(layer1->getPositionX() + 200, layer1->getPositionY()));

//创建监听器
auto listener1 = EventListenerTouchOneByOne::create();
listener1->setSwallowTouches(true);
//为监听器分配回调函数
listener1->onTouchBegan = [](Touch *t, Event *e){
CCLOG("listener1 touch begin!!!!");
/*******************************
**获取被点击的对象,
**并获取点击的点是否在对象中,这里点击的点是OpenGL的坐标点,转换为当前对象内的点
**如果在,设置透明度为180,
**并确认对象被点击事件,即return true
************************************/
auto target = dynamic_cast<Node*>(e->getCurrentTarget());
auto pos = target->convertToNodeSpace(t->getLocation());
Rect rect = { 0, 0, target->getContentSize().width, target->getContentSize().height };

if (rect.containsPoint(pos)){
//设置透明度,范围是:0~255,显示程度逐渐递增
target->setOpacity(180);
return true;
}
return false;
};

listener1->onTouchMoved = [](Touch *t, Event *e){
CCLOG("listener1 touch Move!!!!");
/*************************************************
**移动被点击对象,随着鼠标位置的变化进行相对应移动
**************************************************/
auto target = dynamic_cast<Node*>(e->getCurrentTarget());
auto pos = Vec2(target->getPosition() + t->getDelta());
target->setPosition(pos);
};

listener1->onTouchEnded = [=](Touch *t, Event *e){
CCLOG("listener1 touch Ended!!!!");
/****************************
**把被点击对象透明度设置回来,并判断应该覆盖的对象
**************************/
auto target = dynamic_cast<Node*>(e->getCurrentTarget());
target->setOpacity(255);
if (target == layer1){
layer1->setLocalZOrder(10);
layer2->setLocalZOrder(0);
}
else if (target == layer2){
layer1->setLocalZOrder(0);
layer2->setLocalZOrder(10);
}
};
//克隆监听器一
auto listener2 = listener1->clone();

//分发监听事件
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, layer1);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener2, layer2);

return true;
}
以上就是那个例子的实现。可能在分发函数的回调的时候会有点疑虑,就是这个:
var->onTouchBegan = [](Touch *t, Event *e){
//....
}
这是C++11所支持的新特性,lamda表达式,它是一个匿名函数。而这里所分发的就是回调的函数,所以里面所实现的就是回调函数所需要的。

在lamda表达式中,有一个关键的地方,就是[ ]里面的符号问题,我们来看下它的语法:

[capture list] (parameter list) ->return type { function body }

关于方括号里面的所填的内容一般如下:

"this" : 把当前节点作为捕获的值,所以可以捕获当前节点中所有的子类或是变量属性;

"=" : 把该lamda函数外的一层属性变量拷贝一份,所以可以捕获外层的属性变量;

"&" : 把该lamda函数外的一层属性变量引用进来,所以可以捕获外层的属性变量并改变其值。

对于上面的代码,方括号里面填了“=”的来获取外面一层的所有变量并复制一份。这样,外面一层的方块变量layer1和layer2均可获取得到。

好了,以上就是单点触摸的简单介绍,下一篇会更进一步的对触摸相关的进行讲解。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: