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

上一篇中介绍了坐标转换的问题,这一篇就来浅谈关于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均可获取得到。

好了,以上就是单点触摸的简单介绍,下一篇会更进一步的对触摸相关的进行讲解。





  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值