【cocos2d-x游戏开发】 从零单排之(三)

本文深入解析Cocos2d-x中的Touch事件机制,包括单点触摸和多点触摸的不同处理方式,以及如何通过事件监听进行交互设计。同时介绍了Cocos2d-x特有的内存回收机制,并对比了其与标准库std::map的不同之处。

这篇文章主要介绍touch事件机制,还会涉及到一些的介绍Cocos2d-x的内存回收相关内容。

一、触摸事件

简单介绍一下Touch事件流程:玩家触摸到设备屏幕后,引擎会把触摸事件派发给注册了事件监听的相应代理,触摸的具体信息会以参数的形式传递给相应回调函数。
GameEngin-> EventDispatcher -> ??->onTouchXXX

TouchEvent(触摸事件)分为2种 :EventListenerTouchAllAtOnce(多点触摸) 和  EventListenerTouchOneByOne (单点触摸)。
以单点触摸为例,创建一个Touch事件后,要给 touch->onTouchBegan   onTouchCancelled onTouchEnded onTouchMoved 赋值相应的回调,这4个回调分别代表了
onTouchBegan   开始接触屏幕
onTouchCancelled  事件被取消(比如程序切到后台)
onTouchEnded 触摸事件结束,手指离开屏幕
onTouchMoved 手指在屏幕上滑动

这4个回调方法里,除了第一个onTouchBegan   的返回值是bool,其他都是void。那么这个bool有什么用呢? 看一下CCEventDispatcher的源码(CCEventDispatcher.cpp),不难发现,当开始触摸事件返回true时,之后的触摸结束、触摸移动等事件才能触发,反之,如果TouchBegan返回false,后面的流程不会被触发。
下面贴出给node添加Touch事件的流程
<span style="white-space:pre">		</span>//添加点击监听(单点触摸)
		EventListenerTouchOneByOne* tevent = EventListenerTouchOneByOne::create();
		tevent->setSwallowTouches(true);
		tevent->onTouchBegan = [&](Touch* touch, Event*){
				for(auto key : m_clickDelegates)
				{
					key.second(touch);
				}
				return false;
			};
		tevent->onTouchCancelled = [&](Touch*, Event*){
				
			};
		tevent->onTouchEnded = [&](Touch*, Event*){
				
			};
		tevent->onTouchMoved = [&](Touch*, Event*){
				
			};
		Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(tevent,this);
setSwallowTouches 代表是否阻止当前事件向下一层级派发。

二、cocos2d::Map std::map (这里用大写的Map代表Cocosd中的,小写的map代表标准库函数中的)

cocos2d::Map和std::map功能基本一样,不同的是,Map沿用了cocos2dx的内存回收机制,当添加一个value到Map中时,value.retain()会被调用,移除后,value.release()会被调用,这样,我们就不用手动的去处理map内部引用计数了,但为了使用这个便利,Map<k,v>中的v 必须是 Ref* 类型 !。 这样,如果想用Ref* 做key,而value是一个 std::function<void(Touch*)>类型,就只能使用标准库函数了,但这样就要自己处理Map内部Ref* 类型的引用计数。
之前一直相当然的认为对std::map遍历的时候,是直接遍历所有的value,但结果遍历的类型是 std::pair<k,v>  。

下面看一下单点触摸层简单实现
class LayerTouch:public cocos2d::Layer
{
public:
	LayerTouch();
	~LayerTouch();
	virtual bool init();
	static LayerTouch* create();
	//添加当前回调事件到点击事件回调map中
	void addClickDelegate(cocos2d::Ref*,std::function);
private:
	//点击事件回调字典
	std::map> m_clickDelegates;
};
#include "LayerTouch.h"
USING_NS_CC;
LayerTouch::LayerTouch():m_clickDelegates(std::map>())
{
}
LayerTouch::~LayerTouch()
{
	for(std::map>::iterator iter = m_clickDelegates.begin();iter != m_clickDelegates.end();iter++)
	{
		iter->first->release();
	}
	m_clickDelegates.clear();
}
void LayerTouch::addClickDelegate(cocos2d::Ref* clickDelegate,std::function callback)
{
	m_clickDelegates[clickDelegate] = callback;
	clickDelegate->retain();
}
bool LayerTouch::init()
{
	if(Layer::init())
	{
		//添加点击监听(单点触摸)
		EventListenerTouchOneByOne* tevent = EventListenerTouchOneByOne::create();
		tevent->setSwallowTouches(true);
		tevent->onTouchBegan = [&](Touch* touch, Event*){
				for(auto key : m_clickDelegates)
				{
					key.second(touch);
				}
				//true 会继续监听后面的touch move,touch end等事件,false则不会
				return false;
			};
		tevent->onTouchCancelled = [&](Touch*, Event*){
				
			};
		tevent->onTouchEnded = [&](Touch*, Event*){
				
			};
		tevent->onTouchMoved = [&](Touch*, Event*){
				
			};
		Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(tevent,this);
		return true;
	}
	return false;
}
LayerTouch* LayerTouch::create()
{
	LayerTouch* tlayer = new LayerTouch();
	if(tlayer && tlayer->init())
	{
		tlayer->autorelease();
		return tlayer;
	}else 
	{
		CC_SAFE_RELEASE(tlayer);
	}
	return nullptr;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值