cocos2dx 不要直接在 onEnter 里面 addTargetedDelegate (或 addStandardDelegate)
2014-04-09 18:53
776 查看
原文链接:http://blog.csdn.net/zhangxaochen/article/details/8064010
今天看别人 cocos2d 代码的时候发现个怪现象, 整个工程里面 没有 setTouchEnabled(true) 这样的代码, 但是程序跑起来的时候却可以响应 触屏事件。于是下断点跟踪啊跟踪,发现 m_bIsTouchEnabled 这个变量确实是 false。。 那么这个layer 到底是怎么响应触摸事件的呢?
存在即合理,空穴不来风。经过别人提醒, 意识到原因在这里:
[cpp]
view plaincopyprint?
virtual void onEnter(){
CCLayer::onEnter();
d->getTouchDispatcher()->addTargetedDelegate(this, 0, false);
}
类内覆写了 onEnter 函数,并且 addTargetedDelegate , 居然就可以不用 setTouchEnabled 了。 很有意思的样子, 那么不得不看一下 setTouchEnabled 是怎么工作的了。转到 CCLayer.cpp line:151,看到函数实现:
[cpp]
view plaincopyprint?
/// isTouchEnabled setter
void CCLayer::setTouchEnabled(bool enabled)
{
if (m_bIsTouchEnabled != enabled)
{
m_bIsTouchEnabled = enabled;
if (m_bIsRunning)
{
if (enabled)
{
this->registerWithTouchDispatcher();
}
else
{
// have problems?
CCDirector* pDirector = CCDirector::sharedDirector();
pDirector->getTouchDispatcher()->removeDelegate(this);
}
}
}
}
这个setTouchEnabled 函数做两件事情:
1. 赋值 m_bIsTouchEnabled = enabled
2. if(m_bIsRunning){ if (enabled) this->registerWithTouchDispatcher(); else removeDelegate(this); }
注意: 这里首先判断 if( m_bIsRunning),就是说,如果在初始化 函数init 里面设定 setTouchEnabled(true), 这时候还没 run起来,所以并不会执行这一段。否则这里 register一次, onEnter 里面默认再 register一次程序就会出问题了
那么 registerWithTouchDispatcher() 干什么事情呢?
跳转到定义可以看到:
[cpp]
view plaincopyprint?
void CCLayer::registerWithTouchDispatcher()
{
CCDirector* pDirector = CCDirector::sharedDirector();
if (m_pScriptHandlerEntry)
{
if (m_pScriptHandlerEntry->isMultiTouches())
{
pDirector->getTouchDispatcher()->addStandardDelegate(this, 0);
LUALOG("[LUA] Add multi-touches event handler: %d", m_pScriptHandlerEntry->getHandler());
}
else
{
pDirector->getTouchDispatcher()->addTargetedDelegate(this,
m_pScriptHandlerEntry->getPriority(),
m_pScriptHandlerEntry->getSwallowsTouches());
LUALOG("[LUA] Add touch event handler: %d", m_pScriptHandlerEntry->getHandler());
}
return;
}
pDirector->getTouchDispatcher()->addStandardDelegate(this,0);
}
除去if (m_pScriptHandlerEntry) 那一段不管(似乎是用来控制 script 代码的行为,我也不大懂), 函数主要做的事情就是一句话:
[cpp]
view plaincopyprint?
pDirector->getTouchDispatcher()->addStandardDelegate(this,0);
就是说,默认情况下, CCLayer 注册的是 standardDelegate。
理顺一下, 我们的代码应该:
1. init 函数里面设置 setTouchEnabled(true);
2. 类内覆写函数 registerWithTouchDispatcher, 设置 addStandardDelegate 或者 targetedDelegate,
这样,当初始化时调用 setTouchEnabled(true) 的时候,首先会设置 m_bIsTouchEnabled 为 true, 由于 m_bIsRunning==false, 这时还不会 registerWithTouchDispatcher。 然后程序run起来, 调用 onEnter 函数的时候,这里会(见 CCLayer.cpp line:233):
[cpp]
view plaincopyprint?
if (m_bIsTouchEnabled)
{
this->registerWithTouchDispatcher();
}
如果没有 setTouchEnabled, 没有覆写 registerWithTouchDispatcher,而是直接覆写的 onEnter函数,像本文一开始提到的:
[cpp]
view plaincopyprint?
virtual void onEnter(){
CCLayer::onEnter();
d->getTouchDispatcher()->addTargetedDelegate(this, 0, false);
}
会怎样?会节省代码吗?不会。因为 m_bIsTouchEnabled==false, 所以 onExit 的时候, CCLayer::onExit() 并不会 removeDelegate, 所以我们还需要手动再覆写 onExit 函数,像这样:
[cpp]
view plaincopyprint?
void TestLayer::onExit()
{
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
CCLayer::onExit();
}
同时, 因为 m_bIsTouchEnabled==false, 当你注意到这里的时候你总会陷入逻辑混乱: 没有 enable touch 这个类居然也可以响应触摸!! 就像我看人家代码一样郁闷。什么事嘛。。
今天看别人 cocos2d 代码的时候发现个怪现象, 整个工程里面 没有 setTouchEnabled(true) 这样的代码, 但是程序跑起来的时候却可以响应 触屏事件。于是下断点跟踪啊跟踪,发现 m_bIsTouchEnabled 这个变量确实是 false。。 那么这个layer 到底是怎么响应触摸事件的呢?
存在即合理,空穴不来风。经过别人提醒, 意识到原因在这里:
[cpp]
view plaincopyprint?
virtual void onEnter(){
CCLayer::onEnter();
d->getTouchDispatcher()->addTargetedDelegate(this, 0, false);
}
virtual void onEnter(){ CCLayer::onEnter(); d->getTouchDispatcher()->addTargetedDelegate(this, 0, false); }
类内覆写了 onEnter 函数,并且 addTargetedDelegate , 居然就可以不用 setTouchEnabled 了。 很有意思的样子, 那么不得不看一下 setTouchEnabled 是怎么工作的了。转到 CCLayer.cpp line:151,看到函数实现:
[cpp]
view plaincopyprint?
/// isTouchEnabled setter
void CCLayer::setTouchEnabled(bool enabled)
{
if (m_bIsTouchEnabled != enabled)
{
m_bIsTouchEnabled = enabled;
if (m_bIsRunning)
{
if (enabled)
{
this->registerWithTouchDispatcher();
}
else
{
// have problems?
CCDirector* pDirector = CCDirector::sharedDirector();
pDirector->getTouchDispatcher()->removeDelegate(this);
}
}
}
}
/// isTouchEnabled setter void CCLayer::setTouchEnabled(bool enabled) { if (m_bIsTouchEnabled != enabled) { m_bIsTouchEnabled = enabled; if (m_bIsRunning) { if (enabled) { this->registerWithTouchDispatcher(); } else { // have problems? CCDirector* pDirector = CCDirector::sharedDirector(); pDirector->getTouchDispatcher()->removeDelegate(this); } } } }
这个setTouchEnabled 函数做两件事情:
1. 赋值 m_bIsTouchEnabled = enabled
2. if(m_bIsRunning){ if (enabled) this->registerWithTouchDispatcher(); else removeDelegate(this); }
注意: 这里首先判断 if( m_bIsRunning),就是说,如果在初始化 函数init 里面设定 setTouchEnabled(true), 这时候还没 run起来,所以并不会执行这一段。否则这里 register一次, onEnter 里面默认再 register一次程序就会出问题了
那么 registerWithTouchDispatcher() 干什么事情呢?
跳转到定义可以看到:
[cpp]
view plaincopyprint?
void CCLayer::registerWithTouchDispatcher()
{
CCDirector* pDirector = CCDirector::sharedDirector();
if (m_pScriptHandlerEntry)
{
if (m_pScriptHandlerEntry->isMultiTouches())
{
pDirector->getTouchDispatcher()->addStandardDelegate(this, 0);
LUALOG("[LUA] Add multi-touches event handler: %d", m_pScriptHandlerEntry->getHandler());
}
else
{
pDirector->getTouchDispatcher()->addTargetedDelegate(this,
m_pScriptHandlerEntry->getPriority(),
m_pScriptHandlerEntry->getSwallowsTouches());
LUALOG("[LUA] Add touch event handler: %d", m_pScriptHandlerEntry->getHandler());
}
return;
}
pDirector->getTouchDispatcher()->addStandardDelegate(this,0);
}
void CCLayer::registerWithTouchDispatcher() { CCDirector* pDirector = CCDirector::sharedDirector(); if (m_pScriptHandlerEntry) { if (m_pScriptHandlerEntry->isMultiTouches()) { pDirector->getTouchDispatcher()->addStandardDelegate(this, 0); LUALOG("[LUA] Add multi-touches event handler: %d", m_pScriptHandlerEntry->getHandler()); } else { pDirector->getTouchDispatcher()->addTargetedDelegate(this, m_pScriptHandlerEntry->getPriority(), m_pScriptHandlerEntry->getSwallowsTouches()); LUALOG("[LUA] Add touch event handler: %d", m_pScriptHandlerEntry->getHandler()); } return; } pDirector->getTouchDispatcher()->addStandardDelegate(this,0); }
除去if (m_pScriptHandlerEntry) 那一段不管(似乎是用来控制 script 代码的行为,我也不大懂), 函数主要做的事情就是一句话:
[cpp]
view plaincopyprint?
pDirector->getTouchDispatcher()->addStandardDelegate(this,0);
pDirector->getTouchDispatcher()->addStandardDelegate(this,0);
就是说,默认情况下, CCLayer 注册的是 standardDelegate。
理顺一下, 我们的代码应该:
1. init 函数里面设置 setTouchEnabled(true);
2. 类内覆写函数 registerWithTouchDispatcher, 设置 addStandardDelegate 或者 targetedDelegate,
这样,当初始化时调用 setTouchEnabled(true) 的时候,首先会设置 m_bIsTouchEnabled 为 true, 由于 m_bIsRunning==false, 这时还不会 registerWithTouchDispatcher。 然后程序run起来, 调用 onEnter 函数的时候,这里会(见 CCLayer.cpp line:233):
[cpp]
view plaincopyprint?
if (m_bIsTouchEnabled)
{
this->registerWithTouchDispatcher();
}
if (m_bIsTouchEnabled) { this->registerWithTouchDispatcher(); }
如果没有 setTouchEnabled, 没有覆写 registerWithTouchDispatcher,而是直接覆写的 onEnter函数,像本文一开始提到的:
[cpp]
view plaincopyprint?
virtual void onEnter(){
CCLayer::onEnter();
d->getTouchDispatcher()->addTargetedDelegate(this, 0, false);
}
virtual void onEnter(){ CCLayer::onEnter(); d->getTouchDispatcher()->addTargetedDelegate(this, 0, false); }
会怎样?会节省代码吗?不会。因为 m_bIsTouchEnabled==false, 所以 onExit 的时候, CCLayer::onExit() 并不会 removeDelegate, 所以我们还需要手动再覆写 onExit 函数,像这样:
[cpp]
view plaincopyprint?
void TestLayer::onExit()
{
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
CCLayer::onExit();
}
void TestLayer::onExit() { CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this); CCLayer::onExit(); }
同时, 因为 m_bIsTouchEnabled==false, 当你注意到这里的时候你总会陷入逻辑混乱: 没有 enable touch 这个类居然也可以响应触摸!! 就像我看人家代码一样郁闷。什么事嘛。。
相关文章推荐
- cocos2dx 不要直接在 onEnter 里面 addTargetedDelegate (或 addStandardDelegate)
- cocos2d 学习笔记 - 【转载】cocos2dx 不要直接在 onEnter 里面 addTargetedDelegate (或 addStandardDelegate)
- cocos2dx 不用直接在 onEnter 里面 addTargetedDelegate (或 addStandardDelegate)
- 一篇好文章关于onEnter与addTargetedDelegate
- Cocos2dx的addTargetedDelegate方法的参数
- CCLayer中Touch事件(Standard Touch Delegate和Targeted Touch Delegate)
- addTargetedDelegate:self中的swallowsTouches
- Cocos2d-x不要随便在onEnter里面addChild
- cocos2d-x touches事件中使用 addTargetedDelegate 的潜在bug
- Cocos2d-x不要随便在onEnter里面addChild
- cocos2dx 直接修改 Texture 里面的数据 mark一下 updateWithData
- addTargetedDelegate:self中的swallowsTouches
- addTargetedDelegate:self中的swallowsTouches
- 开发技巧,为了避免拖拽文件出现无法到达工程中,应该是件文件直接拷贝的工程中,不要在xcode里面操作
- Cocos2d-x不要随便在onEnter里面addChild
- CCTouchDelegateProtocol(CCTouchDelegate触摸事件委托 两子类:1CCTargetedTouchDelegate,2CCStandardTouchDelegate)
- (Standard Touch Delegate 和 Targeted Touch Delegate)CCLayer中的两种Touch类型
- CCLayer在Touch事件(Standard Touch Delegate和Targeted Touch Delegate)
- cocos2d-x-2.*关于addTargetedDelegate的两个坑
- addTargetedDelegate:self 中的 swallowsTouches