智慧 + 毅力 = 无所不能

正确性、健壮性、可靠性、效率、易用性、可读性、可复用性、兼容性、可移植性...
随笔 - 991, 文章 - 0, 评论 - 27, 阅读 - 341万

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

cocos2d-x触摸事件优先级的探究与实践

Posted on   Bill Yuan  阅读(9727)  评论(0编辑  收藏  举报

如何让自定义Layer触发触摸事件?

复制代码
bool LayerXXX::init()
{
  this->setTouchEnabled(true);

  CCTouchDispatcher* td = CCDirector::sharedDirector()->getTouchDispatcher();
  td->addTargetedDelegate(this, 0, true); //kCCMenuHandlerPriority - 10

  // ...
}
复制代码

CCTouchDispatcher是管理cocos2d-x中所有Touch事件派发的类,

CCTouchDispatcher中包含了两个CCTouchHandler的列表,
分别存储StandardTouchHandler和 TargetedTouchHandler。

属性:
this->mTouchPriporty

Layer 优先级越小越高
越低越先响应事件

实验一:当两个Layer优先级同等的时候会怎么样呢?

实验发现,同等优先级下,后添加的Layer先响应事件。

复制代码
//-------------------------------
//Touch1 100
//Touch2 100
Touch1Layer* touch1layer = Touch1Layer::create( ccc4f(255,0,0,128), 100, 100 );
this->addChild( touch1layer );
touch1layer->setPosition(200, 100);

Touch2Layer* touch2layer = Touch2Layer::create( ccc4f(255,255,0,128), 100, 100 );
this->addChild( touch2layer );
touch2layer->setPosition(250, 100);

//结果:
//Touch2
//Touch1
//-------------------------------
//Touch1 100
//Touch2 100
Touch2Layer* touch2layer = Touch2Layer::create( ccc4f(255,255,0,128), 100, 100 );
this->addChild( touch2layer );
touch2layer->setPosition(250, 100);

Touch1Layer* touch1layer = Touch1Layer::create( ccc4f(255,0,0,128), 100, 100 );
this->addChild( touch1layer );
touch1layer->setPosition(200, 100);

结果:
Touch1
Touch2
-------------------------------
Touch1 100
Touch2 99
Touch2Layer* touch2layer = Touch2Layer::create( ccc4f(255,255,0,128), 100, 100 );
this->addChild( touch2layer );
touch2layer->setPosition(250, 100);

Touch1Layer* touch1layer = Touch1Layer::create( ccc4f(255,0,0,128), 100, 100 );
this->addChild( touch1layer );
touch1layer->setPosition(200, 100);

//结果:
//Touch2
//Touch1
//说明优先级越小越先触发事件
//-------------------------------
复制代码

如何阻塞事件的向后传递?

原理:
mSwallowsTouches = false的时候,该层的touch事件若接受处理后,touch事件穿透,进入下个注册touch事件的layer进行处理

若mSwallowsTouches = true时,当该层处理touch事件的时候,若bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
return true时候,则touch事件被该层接收走,其他优先级较低的,就不会接收到touch事件的处理申请了。

关于ccTouchBegan的返回值
true:
本层的后续Touch事件可以被触发,并阻挡向后层传递
false:
本层的后续Touch事件不能被触发,并向后传递

总结:

如何阻塞事件的向后传递?

主要是利用了TargetedTouchDelegate 的一个叫SwallowTouch的参数 ,如果这个开关打开的话,

比他权限低的handler 是收不到 触摸响应的,这里的权限低的意思是先看priority(priority越低的优先级越高)再看哪个Layer最后addChild进去(越后添加的优先级越高)。

CCMenu 就是开了Swallow 并且权限为-128(权限是越小越好),所以CCMenu的事件不会出现击穿

mSwallowsTouches = true 并且 ccTouchBegan 返回 true

如何让Layer所有触摸同时穿透Begin、Move、End事件?

mSwallowsTouches = false 并且 ccTouchBegan 返回 true

ccTouchBegan 返回 true 表示同层处理后续事件(吞噬)
ccTouchBegan 返回 false 表示同层不处理后续事件(Move End Cancled)  (击穿)

mSwallowsTouches 设为 true 表示触摸不向下层传递(不一定 如mSwallowsTouches为true began返回false还是会向后传递)
mSwallowsTouches 设为 false 表示触摸向下层传递(不知有啥用)

this->mTouchPriporty 越小,越先接收到触摸
this->mTouchPriporty 同等,越后addChild的越先响应

如何管理多个对话框的优先级?

事件的优先级和绘图的优先级的关系和区别?

VertexZ 又是什么?(VertexZ是openGl的z轴)


绘图的优先级叫ZOrder

如何改版绘图的优先级?

如在容器中通过调用
this->reorderChild(CCNode* child, int zOrder);

如何设置触摸事件的优先级?
CCTouchDispatcher::sharedDispatcher()->setPriority(kCCMenuTouchPriority - 1, layer);

如何得到触摸事件的优先级?
this->mTouchPriporty (CCNode类成员 私有变量)

如何遍历容器获取特定的对象??

复制代码
void Touch1Layer::setFocus()
{
  // 将zorder=1;  priority= kCCMenuTouchPriority - 2;

  // 设置zorder
  SceneController::GetInstancePtr()->getCurLayer()->reorderChild(this, 1);
  // 设置优先级
  CCTouchDispatcher::sharedDispatcher()->setPriority(kCCMenuTouchPriority - 2, this);
}

void Touch1Layer::loseAllFocus()
{
  // 获取顶层的所有节点
  CCArray* arrChilds = SceneController::GetInstancePtr()->getCurLayer()->getChildren();

  for(int i=0; i< arrChilds->count(); i++)
  {
    CCLayerColor* layer = dynamic_cast< CCLayerColor* >( arrChilds->objectAtIndex(i) );

    // 跳过自己(不撤销自己的优先级)
    if(layer != NULL && layer != this)
    {
      // 将zorder=0;  priority= kCCMenuTouchPriority - 1;
      SceneController::GetInstancePtr()->getCurLayer()->reorderChild(layer, 0);
      CCTouchDispatcher::sharedDispatcher()->setPriority(kCCMenuTouchPriority - 1, layer);
    }
  }
}
复制代码

如何判断点在矩形内部?

CCPoint pos = this->getPosition();
CCSize size = this->getContentSize();
CCRect rect(pos.x, pos.y, size.width, size.height);

if( CCRect::CCRectContainsPoint(rect, point)  )
{
}


z值大的成员在z值小的成员的上面;

官方解释:

Differences between openGL Z vertex and cocos2d Z order:
   - OpenGL Z modifies the Z vertex, and not the Z order in the relation between parent-children
   - OpenGL Z might require to set 2D projection
   - cocos2d Z order works OK if all the nodes uses the same openGL Z vertex. eg: vertexZ = 0

@warning: Use it at your own risk since it might break the cocos2d parent-children z order

(评论功能已被禁用)
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示