zoukankan      html  css  js  c++  java
  • quick-cocos2d-x游戏开发【10】——触摸捕获事件 cc.NODE_TOUCH_CAPTURE_EVENT

    假设看过sample中touch的代码,你会发现演示样例中有一个cc.NODE_TOUCH_CAPTURE_EVENT事件。它和cc.NODE_TOUCH_EVENT触摸事件一样,是引擎级别的事件,我们来看看它和触摸事件的差别。


    首先触摸捕获事件默认是开启的,即setTouchCaptureEnabled(true)


    触摸捕获事件的优先级要比触摸事件要高。换句话说。触摸捕获事件会比触摸事件先响应。而且有权不分发给触摸事件响应。

    对于一个完整的捕获+触摸事件,有这么一个流程:

    1.捕获阶段。一旦有触摸事件发生。那么首先会触发捕获事件。而且捕获顺序是从zOrder高到低,越在屏幕上方越优先捕获。从父节点传到子节点,父节点优先捕获。

    2.目标阶段,该阶段就是各个节点响应自己的触摸事件。began。moved,ended等。

    3传递阶段,仅仅要当前节点没有将触摸吞噬,那么触摸事件将会继续往下层的节点进行传送。


    有了一些理论知识。我们来实际操作一下。写些代码。

    function MyScene:ctor()	
    
        local layer = display.newLayer()
        self:addChild(layer)
        layer:setTouchEnabled(true)
       	layer:setTouchSwallowEnabled(false)
        layer:setTouchMode(cc.TOUCH_MODE_ONE_BY_ONE)
        layer:addNodeEventListener(cc.NODE_TOUCH_EVENT, function (event)
            if event.name == "began" then
                 print("layer began")
            elseif event.name == "moved" then
                print("layer moved")
            elseif event.name == "ended" then
                 print("layer ended")
            end
    
            return true
        end)
    
        layer:addNodeEventListener(cc.NODE_TOUCH_CAPTURE_EVENT, function (event)
        	if event.name == "began" then
                print("layer capture began")
            elseif event.name == "moved" then
                print("layer capture moved")
            elseif event.name == "ended" then
                print("layer capture ended")
            end
    
            return true
        end)
    
        local sp = display.newSprite("HelloWorld.png", display.cx, display.cy)
        layer:addChild(sp)
        --self:addChild(sp)
        sp:setTouchEnabled(true)
        sp:setTouchSwallowEnabled(false)
        sp:setTouchMode(cc.TOUCH_MODE_ONE_BY_ONE)
        sp:addNodeEventListener(cc.NODE_TOUCH_EVENT, function (event)
        	if event.name == "began" then
                print("sp began")
            elseif event.name == "moved" then
                print("sp moved")
            elseif event.name == "ended" then
                print("sp ended")
            end
    
            return true
        end)
    
        sp:addNodeEventListener(cc.NODE_TOUCH_CAPTURE_EVENT, function (event)
        	if event.name == "began" then
                print("sp capture began")
            elseif event.name == "moved" then
                print("sp capture moved")
            elseif event.name == "ended" then
                print("sp capture ended")
            end
    
            return true
        end)
    	
    end

    代码中,加入了两个节点,一个是layer。一个sprite。sprite加入在layer上,他们都开启了触摸,没有吞噬触摸。而且加入了捕获事件和触摸事件,返回值为true。

    简单点击一下窗体。看看print信息,


    由于父节点会优先捕获事件,所以首先是layer捕获到了,其次子节点捕获到。接下来是处理触摸,由于子节点在父节点的上面,所以子节点先响应了触摸事件,处理过后由于没有吞噬触摸,所以会继续将触摸事件向下传递,此时它的以下就是它的父节点laier。所以layer又再一次捕获到了这个事件,最后layer開始响应触摸事件。


    假设我们将子节点sprite设置吞噬触摸。


    能够看到,当sprite响应了触摸事件之后就不再向下传递了,所以父节点就不能再捕获到上方传下来的触摸了。


    我们再改动一下代码,把layer的捕获事件返回为false。sprite还是依旧保持吞噬触摸。也就是在之前的代码上做这种改动,

        layer:addNodeEventListener(cc.NODE_TOUCH_CAPTURE_EVENT, function (event)
        	if event.name == "began" then
                print("layer capture began")
            elseif event.name == "moved" then
                print("layer capture moved")
            elseif event.name == "ended" then
                print("layer capture ended")
            end
    
            return false
        end)
    
        local sp = display.newSprite("HelloWorld.png", display.cx, display.cy)
        layer:addChild(sp)
        --self:addChild(sp)
        sp:setTouchEnabled(true)
        --sp:setTouchSwallowEnabled(false)
        sp:setTouchMode(cc.TOUCH_MODE_ONE_BY_ONE)

    我们执行一下,点击屏幕看下效果,


    这里我是抬起了鼠标后截出来的日志信息,能够看到,layer的捕获開始打印了两次。

    由于我们在父节点layer的捕获事件中,将其设置成返回false,所以其子节点是无法响应后面的触摸事件的,可是关键的是。即便父节点在捕获阶段阻止响应事件,但子对象仍然能够捕获到事件,仅仅是不会触发事件,说白了就是。父节点阻断了捕获,可是我子节点依旧能够捕获到,仅仅是子节点的捕获不响应各个事件,也不会再让后面的触摸事件响应。


    所以我们回过来想一下,第一次触摸屏幕,父节点捕获到了。子节点也捕获到了,可是返回false,所以子节点的捕获事件不触发。所以看不到sprite打出捕获信息。而且sprite也不响应触摸事件。所以吞不吞噬也就没作用了。继续分发着走,那么layer就会再一次捕获到自己的事件,仅仅是这次返回的false,它把它自己的后面的触摸事件也停止了。

    所以ended事件响应我们一个都看不到。


    不知道大家有没有理清思路,这次我们不把sprite加入在layer上,sprite也加入在scene中。我们来看下结果,

    function MyScene:ctor()	
    
        local layer = display.newLayer()
        self:addChild(layer)
        layer:setTouchEnabled(true)
       	layer:setTouchSwallowEnabled(false)
        layer:setTouchMode(cc.TOUCH_MODE_ONE_BY_ONE)
        layer:addNodeEventListener(cc.NODE_TOUCH_EVENT, function (event)
            if event.name == "began" then
                 print("layer began")
            elseif event.name == "moved" then
                print("layer moved")
            elseif event.name == "ended" then
                 print("layer ended")
            end
    
            return true
        end)
    
        layer:addNodeEventListener(cc.NODE_TOUCH_CAPTURE_EVENT, function (event)
        	if event.name == "began" then
                print("layer capture began")
            elseif event.name == "moved" then
                print("layer capture moved")
            elseif event.name == "ended" then
                print("layer capture ended")
            end
    
            return true
        end)
    
        local sp = display.newSprite("HelloWorld.png", display.cx, display.cy)
        --layer:addChild(sp)
        self:addChild(sp)
        sp:setTouchEnabled(true)
        sp:setTouchSwallowEnabled(false)
        sp:setTouchMode(cc.TOUCH_MODE_ONE_BY_ONE)
        sp:addNodeEventListener(cc.NODE_TOUCH_EVENT, function (event)
        	if event.name == "began" then
                print("sp began")
            elseif event.name == "moved" then
                print("sp moved")
            elseif event.name == "ended" then
                print("sp ended")
            end
    
            return true
        end)
    
        sp:addNodeEventListener(cc.NODE_TOUCH_CAPTURE_EVENT, function (event)
        	if event.name == "began" then
                print("sp capture began")
            elseif event.name == "moved" then
                print("sp capture moved")
            elseif event.name == "ended" then
                print("sp capture ended")
            end
    
            return true
        end)
    	
    end

    触摸吞噬都关闭,各个事件返回值都是true,print的结果是。


    由于sprite后加入。他们在同一个zOrder上所以sprite要靠前,先捕获到事件,然后到触摸事件,做完之后传递到以下的layer,layer開始捕获然后处理触摸事件。


    这就是quick对于捕获事件的原理了。如有错误。欢迎指出。


  • 相关阅读:
    #Leetcode# 338. Counting Bits
    POJ 3614(Sunscreen)
    POJ 2392(Space Elevator)
    POJ 3666(Making the Grade)
    Coursera吴恩达《构建机器学习项目》课程笔记 -- 机器学习策略(下)
    Coursera吴恩达《构建机器学习项目》课程笔记-- 机器学习策略(上)
    深度学习入门--Stanford CS230--学习笔记
    POJ 1065 (Wooden Sticks)
    POJ 1742(Coins)
    C++ 按位与(&)、或(|)、异或(^)等操作符
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/6699721.html
Copyright © 2011-2022 走看看