Quick-x多点触摸

在做格斗类游戏的时候,有摇杆和攻击键两个sprite,我想要的是一只手指按下摇杆的时候另一只手指还能操作攻击键,但实际上第二根手指完全没反应。

local spr1 = display.newSprite(image1)
spr1:addNodeEventListener(cc.NODE_TOUCH_EVENT, function(event)
        if event.name ~= "moved" then
            print("spr1 " .. event.name)
        end

        if event.name == "began" then return true end
   end)
spr1:setTouchEnable(true)

local spr2 = display.newSprite(image2)
spr2:addNodeEventListener(cc.NODE_TOUCH_EVENT, function(event)
        if event.name ~= "moved" then
            print("spr2 " .. event.name)
        end

        if event.name == "began" then 
            return true 
        end
   end)
spr2:setTouchEnable(true)


```



Test1: 先按下spr1,然后按下屏幕任何一处(包括spr1和spr2),输出信息只有一个 "spr1 began"(即第二个手指没有任何输出)
Test2: 设置spr2:setTouchMode(cc.TouchesAllAtOnce), 先按下spr2,然后按下屏幕任何一处,输出信息"spr2 began" "spr2 added" (即第一个对象没有任何输出)

在经过各种折腾、死掉无数脑细胞后终于找到LuaTouchEventManager,在onTouchesBegan函数里找到罪魁祸首:

    // check current in touching
    if (_touchingTargets.size())
    {
        dispatchingTouchEvent(touches, event, CCTOUCHADDED);
        return;
    }


_touchingTargets是记录began返回true的对象
Test1:  _touchingTargets在第一个手指按下后存着spr1,size不为0给
 _touchingTargets中对象派发CCTOUCHADDED,而dispatchingTouchEvent里面有这么一些代码
            if (touchMode == LuaEventNode::modeTouchesAllAtOnce)
            {
                switch (event)
                {
                case CCTOUCHMOVED:
                case CCTOUCHENDED:
                case CCTOUCHCANCELLED:
                case CCTOUCHADDED:
                case CCTOUCHREMOVED:
                }
            }
            else
            {
                switch (event)
                {
                case CCTOUCHMOVED:
                case CCTOUCHENDED:
                case CCTOUCHCANCELLED:
                case CCTOUCHREMOVED:
                }
            }


```

        这次的模式是OneByOne,所以进到else,然后发现没有CCTOUCHADDED的分支,所以不再继续任何派发

Test2: _touchingTargets在第一个手指按下后存着spr2,size不为0给
 _touchingTargets中对象派发CCTOUCHADDED,这次模式为AllAtOnce,所以触摸任何地方都给第二个对象派发CCTOUCHADDED

不知道这算是bug还是quickx特意设置的,反正是感觉很不好用,个人感觉功能应该是这样的
for node in allNodes do
    for touch in allTouches do
        if touch in spr's cascadeBoundingBox then
            if firstTouch in spr or mode is onebyone then
                dispatch("began")
            else
                dispatch("added")
            end
         end
    end
end


```


即无论OneByOne还是AllAtOnce都可以派发added和removed,但是added派发前都要检测cascadeBoundingBox

单点模式下肯定不会出现added消息的,因为added是增加一个触点,只有在多点模式下才可能出现。
从逻辑上来说,第一个精灵设置成单点模式以后,阻止其他精灵的接收是正常的吧。既然要多点工作,为什么不把精灵全部设置成多点的呢?
这个功能从开始的设计上,我觉得应该以一个多点触摸层来放置这两个精灵进行处理才是比较合理的方案吧。

首先Test2是第二个开了多点的阻止了第一个单点模式的触摸接收!
这跟cocos2dx触摸机制完全相反。

其次,事实上我需要的两个精灵互不干扰,两个单点、只接收在它上面的触摸是最好的方式。

local function onTouchBegan(touch, event)
    local target = event.getCurrentTarget()
    local nodepos = target:getParent():convertTouchToNodeSpace(touch)
    local box = target:getBoundingBox()
    if cc.rectContainsPoint(box, nodepos) then
        --suppose visible
        return true
    end
    return false
end
local dispatcher = cc.Director:getInstance():getEventDispatcher()
local listener = cc.EventListenerTouchOneByOne:create()
listener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN)
dispatcher:addEventListenerWithSceneGraphPriority(listener, spr1)
dispatcher:addEventListenerWithSceneGraphPriority(listener:clone(), spr2)


```

如果以一个多点触摸层来处理,感觉回到了最原始的只能由layer来分发触摸。 在拥有大地图缩放、拖动和地图上一堆功能性按钮时,它的触摸逻辑将会复杂得令人崩溃!

现mark着,等到这一步再看。楼主辛苦!