cocos2dx-lua基础内容之 用户事件中的触摸事件

本篇博客是描述使用coocs2dx lua 使用触摸事件的演示。关于main.lua的文件,请从同系列的前面文章中寻找。

基础的内容将不再讲解,本文将讲述重点的内容。

使用步骤

  1. 创建需要的监听器(触摸监听器,键盘监听器)。
  2. 监听器设置是否吞没。
  3. 监听器设置需要监听的事件类型(cc.Handler.EVENT_TOUCH_BEGAN),以及对应的回调函数。
  4. 创建分发器,注册事件监听器。

使用案例

size=cc.Director:getInstance():getVisibleSize()

local testScene=class("Test",
        function() 
            return cc.Scene:create() 
        end
        )

--初始化
function testScene:ctor()
   print("ctor running")
end


function testScene:create()
   local scene=testScene.new()           --创建场景。
   local layer=testScene:createLayer()   --创建层。
   scene:addChild(layer)                 --将层添加到场景中
   return scene                          --返回场景
end

function testScene:createLayer()
   local layer=cc.Layer:create()                         --创建场景
   spriteTag=100
   local sp=cc.Sprite:create("HelloWorld.png")
   sp:setPosition(cc.p(size.width/2,size.height/2+200))
   layer:addChild(sp,10,spriteTag)   

   spriteTag1=101
   local sp1=cc.Sprite:create("HelloWorld.png")
   sp1:setPosition(cc.p(size.width/2-100,size.height/2+50))
   layer:addChild(sp1,10,spriteTag1)

    --回调函数的参数依次为触摸对象,以及被绑定的node对象。顺序不能错。
    local function touchBegan(touch,event)
       print("touchBegan")
       --获取绑定的Sprite对象,只有使用SceneGraph注册时有用
       local node=event:getCurrentTarget()
       local pos=node:convertToNodeSpace(touch:getLocation())
       local size=node:getContentSize()
       local rect=cc.rect(0,0,size.width,size.height)
       --判断触摸点是否触摸到被监听的对象。
        if cc.rectContainsPoint(rect,pos) then 
           print("pos.x="..pos.x,"pos.y"..pos.y)
           print("node tag="..node:getTag())
           node:runAction(cc.ScaleTo:create(0.5,1.5))
           --需要返回true,才能调用后面两个函数。
           return true
        end

        return false
    end

    local function touchEnded(touch,event)
       print("touchEnded")
       local node=event:getCurrentTarget()
       node:runAction(cc.ScaleTo:create(0.5,1.0))
    end

     function touchMoved(touch,event)
       print("touchMoved")
       local node=event:getCurrentTarget()
       local nodeX,nodeY=node:getPosition()
       local diff=touch:getDelta()
       node:setPosition(cc.p(nodeX+diff.x,nodeY+diff.y))
      end
--创建单点触摸监听器
 local listeners=cc.EventListenerTouchOneByOne:create()
--设置是否吞没事件。
   listeners:setSwallowTouches(true)
--注册回调函数以及事件属性   
  listeners:registerScriptHandler(touchBegan,cc.Handler.EVENT_TOUCH_BEGAN)
   listeners:registerScriptHandler(touchMoved,cc.Handler.EVENT_TOUCH_MOVED)
   listeners:registerScriptHandler(touchEnded,cc.Handler.EVENT_TOUCH_ENDED)

   --创建事件分发器
   local eventDispatcher=cc.Director:getInstance():getEventDispatcher()
   --监听器被注册一次,就无法再次注册了。可以使用clone()克隆一个同样的监听器
   listener1=listeners:clone()
--精灵对象sp,sp1注册事件监听   
  eventDispatcher:addEventListenerWithSceneGraphPriority(listeners, sp)
    eventDispatcher:addEventListenerWithSceneGraphPriority(listener1,sp1)

每一个事件监听器只能被添加一次,addEventListenerWithSceneGraphPriority和addEventListenerWithFixedPriority会在添加事件监听器时设置一个注册标识,一旦设置了注册标识,该监听器就不能再用于注册其他事件监听了,因此需要使用clone()函数获得一个新的监听器对象,把这个新的监听器对象用于注册。

如何获取被触摸的对象

当使用addEventListenerWithSceneGraphPriority()注册监听器时,可以使用event:getCurrentTarget()获取被绑定的精灵对象。如:

local function onTouch(touch,event) 
   local node=event:getCurrentTarget()
end

当使用addEventListenerWithFixedPriority()注册监听器时,不可以使用event:getCurrentTarget()获取绑定的精灵对象,因为使用FixedPriority时,根本就没有绑定的精灵。所以这个时候,只能使用layer:getChildByTag(number)一个一个获取,然后再判断。

代码如下,添加了一个自定义的isTap(),并且修改了触摸事件的回调函数:

    --使用Fixed注册的事件回调函数案例。
    --自定义判断触摸点是否在精灵内
    local function isTap(node,touch)
       local size=node:getContentSize()
       local rect=cc.rect(0,0,size.width,size.height)
       local pos=node:convertToNodeSpace(touch:getLocation())
       if cc.rectContainsPoint(rect,pos) then    
          --如果触摸点在精灵内,则返回true。      
          return true
       end

    end

    local function touchBegan(touch,event)
        --使用layer:getChildByTag(tag)获取一个node。
        --有多少个node需要判断,就需要获取多少个node。
        local node1=layer:getChildByTag(spriteTag)
        if isTap(node1,touch) then 
           node1:runAction(cc.ScaleTo:create(0.5,1.5))
           return true
        end

        local node2=layer:getChildByTag(spriteTag1)
        if isTap(node2,touch) then
            node2:runAction(cc.ScaleTo:create(0.5,1.25))
            return true
        end

       return false
    end

    local function touchMoved(touch,event)

       local node1=layer:getChildByTag(spriteTag)
        if isTap(node1,touch) then 
           print("node1 moved")
           local diff=touch:getDelta()
           local nodeX,nodeY=node1:getPosition()
           node1:setPosition(cc.p(nodeX+diff.x,nodeY+diff.y))
            --如果不return一个空值 ,当下面条件也成立的话,也会执行
            --结果就是两个精灵一起移动。
           return
        end

        local node2=layer:getChildByTag(spriteTag1)
        if isTap(node2,touch) then
           print("node2222 moved")
           local diff=touch:getDelta()
           local nodeX,nodeY=node2:getPosition()
           node2:setPosition(cc.p(nodeX+diff.x,nodeY+diff.y))
           return
        end
    end
 local eventDispatcher=cc.Director:getInstance():getEventDispatcher()
 --注意这里使用的是FixedPriority注册的。
eventDispatcher:addEventListenerWithFixedPriority(listeners, 20)

从上面可以得知,当使用Fixed时,无论是touchBegan,还是touchMoved、touchEnded都需要一个一个获取需要判断的精灵对象,然后再使用自定义的方法isTap()一个一个判断。

注意事项

  1. 首先注册事件不是注册在某一个精灵对象上,而是整个屏幕都会有注册事件。也就是说在整个屏幕都可以触发touchBegan函数。

  2. 因为整个屏幕都会有注册事件,所以应该touchBegan默认返回false,这样touchMove和touchEnded都不会被调用。然后在touchBegan中判断点是否在对象范围内,存在的话执行对其的操作,然后返回true。

  3. 监听器对象不是只能创建一个,可以创建多个。只是当注册了一个事件监听器,就不能再进行注册了,只能使用listener:clone(),还有一个需要注意的是,使用了clone()就没办法移除监听器,因为没有名字。

  4. 使用FixedPriority listeners时,添加完之后需要手动remove,而使用SceneGraphyPriority listener和Node绑定,当Node销毁时会被移除。
    _eventDispatcher:removeEventListener(listener);

  5. 移除监听器的时候,对于listener:clone()的如果不移除,就会一直存在。此时如果在这个监听器的回调函数中获得不到某个精灵时就会报错。而对于使用listener()->clone的就没办法像上面一样移除了,因为它没有名字,它只是克隆出来的,除非移除所有的监听。那么按钮的监听也不能使用了。

  6. 如何获得精灵对象,并对其执行操作。
    使用SceneGraphPriority注册事件,可以使用event:getCurrentTarget();获得绑定的target。
    使用FixtedPriority注册事件,只能使用layer:getChildByTag(精灵Tag值) 获得。除非是常量。

  7. 如果需要单独处理某个对象,就可以考虑使用Fixted,可以针对特定的精灵执行特定的处理。而如果需要对多个对象,做同样的处理,就可以使用SceneGraphPriority。因为可以在函数处理中使用event:getCurrentTarget() //获得被绑定的精灵

  8. SceneGraph 把精灵显示优先级作为事件优先级,即addChild()的第二个参数,zOrder值越大,事件优先级就越大。
    Fixed 指定固定的事件优先级(第二个参数)注册监听器,事件优先级决定事件响应的优先级别,值越小优先级越高。

猜你喜欢

转载自blog.csdn.net/qq_28644183/article/details/72598336
今日推荐