cocos2d-x 实现交互功能之单点触摸

1.新建项目,用VS打开.sln文件,在HelloWorldScene.cpp中写入自己代码,这一步主要是添加背景图,以及添加4个精灵图

素材:https://pan.baidu.com/s/1GXwgb7u3RsUBD9ajY06zGg

bool HelloWorld::init()
{
    if ( !Layer::init() )
    {
        return false;
    }
	Size visibleSize = Director::getInstance()->getVisibleSize();
	Vec2 origin = Director::getInstance()->getVisibleOrigin();
	//加入背景
	auto *background = Sprite::create("bg.jpg");
	background->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 2));
	this->addChild(background);
	//加入卡牌精灵
	Sprite *myCard[4];
	for (int i = 0; i < 4; i++)
	{
		char imageName[15] = { 0 };
		//Sprite myCard[4];
		sprintf(imageName, "mycard0%d.png", i + 1);
		myCard[i] = Sprite::create(imageName);
		myCard[i]->setScale(0.5f);
		myCard[i]->setPosition(visibleSize.width*(i + 1) / 5, visibleSize.height / 2);
		this->addChild(myCard[i]);
	}
    return true;
}

实现效果

cocos2d-x 实现交互功能之单点触摸_第1张图片

2.建立事件监听

第一步

// 创建一个事件监听器 OneByOne 为单点触摸 
	auto myListener = EventListenerTouchOneByOne::create();
	//设置是否吞没事件,在 onTouchBegan 方法返回 true 时吞没
	myListener->setSwallowTouches(true);

	//C++11中的Lambda表达式
	//[=]	以值的形式捕获所有外部变量
	//[]	不捕获任何外部变量
	//onTouchBegan 事件回调函数
	myListener->onTouchBegan = [=](Touch* touch, Event* event)
	{
		//获取事件所绑定的target
		auto target = static_cast(event->getCurrentTarget());
		//获取当前单击点所在相对按钮位置的坐标
		Point locationInNode = target->convertToNodeSpace(touch->getLocation());
		Size s = target->getContentSize();
		Rect rect = Rect(0, 0, s.width, s.height);
		//单击范围判断检测,判断所传递的坐标是否包含被单击的物体
		if (rect.containsPoint(locationInNode))
		{
			//显示当前卡牌精灵的坐标位置
			log("x = %f, y = %f", locationInNode.x, locationInNode.y);
			target->setOpacity(180);
			return true;
		}
		return false;
	};

提示   为了能够在onTouchBegan 方法中引用来自外部的局部变量,需要[=],这样设置,否则会报错

第二步

//onTouchMoved 事件回调函数
	myListener->onTouchMoved = [](Touch* touch, Event* event)
	{
		auto target = static_cast(event->getCurrentTarget());
		//显示当前卡牌精灵的坐标位置
		log("x = %f, y = %f", touch->getLocation().x, touch->getLocation().y);
		//移动当前卡牌的精灵坐标位置
		target->setPosition(target->getPosition() + touch->getDelta());
	};
	//onTouchEnded 事件回调函数
	myListener->onTouchEnded = [](Touch* touch, Event* event)
	{
		auto target = static_cast(event->getCurrentTarget());
		target->setOpacity(255);
	};

可以在VS的输出栏看到下图所示


3.为事件监听器绑定事件

//为事件监听器绑定事件,用来判断是对哪个卡牌进行事件响应
	_eventDispatcher->addEventListenerWithSceneGraphPriority(myListener, myCard[0]);
	//再次绑定是要用clone方法
	_eventDispatcher->addEventListenerWithSceneGraphPriority(myListener->clone(), myCard[1]);
	_eventDispatcher->addEventListenerWithSceneGraphPriority(myListener->clone(), myCard[2]);
	_eventDispatcher->addEventListenerWithSceneGraphPriority(myListener->clone(), myCard[3]);

点击运行,效果图

cocos2d-x 实现交互功能之单点触摸_第2张图片

新知识,了解一下:

    单词:touch触摸    opcacity不透明度    node节点    location位置    convert转换    current当前的 

               target对象     event事件    graph图    priority优先级    swallow吞没

listener->setSwallowTouches(true),不向下触摸

简单点来说,比如有两个sprite ,A 和 B,A在上B在下(位置重叠),触摸A的时候,B不会受到影响


我们可以看到,通过EventListenerTouchOneByOne定义了单点触控的监听器。 
然后对其响应类型进行了定义: 
onTouchBegan对用户的触摸到屏幕的操作进行处理,首先获取了事件绑定的target,即用户的滑动、拖曳行为针对哪一个对象进行操作,这里的操作对象是卡牌。然后判断单击的坐标是否包含于操作对象范围中,如果包含在里面,则返回true,才能执行onTouchMoved;否则返回false,不执行onTouchMoved。 
onTouchMoved对用户在操作对象上的拖动操作进行处理,根据用户的触摸位置来改变操作对象的位置。其中存在一个问题,如果对两个操作对象重叠部分进行操作,应该移动哪一个触摸对象呢?这里通过setSwallowTouches()设置是否允许触摸事件向下传递,true则不传递,即只对上层对象进行操作,而false则会传递,当触摸重叠区域时,重叠的所有对象都会被操作。 

onTouchEnded对用户触摸结束时进行处理,这个例子中,只是调整了精灵的透明度。在最后一部分也是十分重要的一部分,可以看到,通过_eventDispatcher->addEventListenerWithSceneGraphPriority将对象与监听器进行了绑定,其中的_eventDispatcher是Node对象中自带的属性,用于统一管理各个节点的分发情况。需要注意的是对不同对象进行绑定时,要对触发器对象使用clone方法来保证程序的正常运行。

拓展:

如果在4张卡牌都被绑定了事件监听的情况下,怎么保证只有第一张牌能被拖动呢?

只要将if (rect.containsPoint(locationInNode))改为if (rect.containsPoint(locationInNode)&&target==myCard[0]),皆可


你可能感兴趣的:(cocos2d-x,交互功能,c++)