[cocos2dx_Lua]quick中的节点事件

节点事件在一个 Node 对象进入、退出场景时触发。
local node = display.newNode()
node:addNodeEventListener(cc.NODE_EVENT, function(event)
    print(event.name)
end)
scene:addChild(node)
event属性
event.name: 指示节点事件类型,具有下列值:
  • enter: Node 加入了正在运行的场景
  • exit: Node 退出了正在运行的场景
  • enterTransitionFinish: 进入一个新场景时的特效结束
  • exitTransitionStart: 退出一个现有场景时的特效开始
  • cleanup: Node 被完全清理并从内存删除时
下面的示例代码演示了 5 种事件类型的出现时机:
require("framework.init")

-- 首先创建一个空白场景
local sceneInit = display.newScene("sceneInit")
-- 进入该场景
display.replaceScene(sceneInit)

local function createTestScene(name)
    local scene = display.newScene(name)
    local node = display.newNode()
    node:addNodeEventListener(cc.NODE_EVENT, function(event)
        printf("node in scene [%s] NODE_EVENT: %s",
               name, event.name)
    end)
    scene:addChild(node)
    return scene
end

-- 等待 1.0 秒创建第一个测试场景
sceneInit:performWithDelay(function()
    local scene1 = createTestScene("scene1")
    display.replaceScene(scene1)

    -- 等待 1.0 秒创建第二个测试场景
    scene1:performWithDelay(function()
        print("--------")
        local scene2 = createTestScene("scene2")
        display.replaceScene(scene2)
    end, 1.0)
end, 1.0)
输出结果:
node in scene [scene1] NODE_EVENT: enter
node in scene [scene1] NODE_EVENT: enterTransitionFinish
--------
node in scene [scene1] NODE_EVENT: exitTransitionStart
node in scene [scene1] NODE_EVENT: exit
node in scene [scene1] NODE_EVENT: cleanup
node in scene [scene2] NODE_EVENT: enter
node in scene [scene2] NODE_EVENT: enterTransitionFinish
在切换场景时如果没有使用特效,那么事件出现的顺序如上。
但如果将测试代码 display.replaceScene(scene2) 修改为 display.replaceScene(scene2, "random", 1.0),事件出现顺序会变成:

node in scene [scene1] NODE_EVENT: enter
node in scene [scene1] NODE_EVENT: enterTransitionFinish
--------
node in scene [scene1] NODE_EVENT: exitTransitionStart
node in scene [scene2] NODE_EVENT: enter
node in scene [scene1] NODE_EVENT: exit
node in scene [scene2] NODE_EVENT: enterTransitionFinish
node in scene [scene1] NODE_EVENT: cleanup
造成这种区别的原因就是场景切换特效播放期间,会同时渲染两个场景,所以从事件上看,可以看到第二个场景的 enter 事件出现后,第一个场景的 exit 事件才出现。因此,我们在使用节点事件时,不应该假定事件出现的顺序,而是根据特定事件采取特定的处理措施。
通常建议如下:
    enter: 这里可以做一些场景初始化工作
    exit: 如果场景切换使用了特效,可以在这里停止场景中的一些动画,避免切换场景的特效导致帧率下降
    cleanup: 适合做清理工作


为了简化使用,quick 为 cc.Node 封装了几个现成的方法,开发者如果从 Node(或继承类)创建自己的 Lua 类,那么可以直接覆盖这几个方法:
require("framework.init")

-- 定义一个自己的 cc.Node 继承类
local MyNode = class("MyNode", function(sceneName)
    local node = display.newNode()
    node.sceneName = sceneName
    return node
end)

function MyNode:onEnter()
    printf("node in scene [%s] method %s",
        self.sceneName,
        "onEnter")
end

function MyNode:onExit()
    printf("node in scene [%s] method %s",
        self.sceneName,
        "onExit")
end

function MyNode:onEnterTransitionFinish()
    printf("node in scene [%s] method %s",
        self.sceneName,
        "onEnterTransitionFinish")
end

function MyNode:onExitTransitionStart()
    printf("node in scene [%s] method %s",
        self.sceneName,
        "onExitTransitionStart")
end

function MyNode:onCleanup()
    printf("node in scene [%s] method %s",
        self.sceneName,
        "onCleanup")
end


-- 首先创建一个空白场景
local sceneInit = display.newScene("sceneInit")
-- 进入该场景
display.replaceScene(sceneInit)

local function createTestScene(name)
    local scene = display.newScene(name)
    local node = MyNode.new(name)
    node:setNodeEventEnabled(true) -- 启用节点事件,会调用节点预定义的方法
    scene:addChild(node)
    return scene
end

-- 等待 1.0 秒创建第一个测试场景
sceneInit:performWithDelay(function()
    local scene1 = createTestScene("scene1")
    display.replaceScene(scene1)

    -- 等待 1.0 秒创建第二个测试场景
    scene1:performWithDelay(function()
        print("--------")
        local scene2 = createTestScene("scene2")
        display.replaceScene(scene2, "random", 1.0)
    end, 1.0)
end, 1.0)
执行结果如下:
node in scene [scene1] method onEnter
node in scene [scene1] method onEnterTransitionFinish
--------
node in scene [scene1] method onExitTransitionStart
node in scene [scene2] method onEnter
node in scene [scene1] method onExit
node in scene [scene2] method onEnterTransitionFinish
node in scene [scene1] method onCleanup

效果和直接注册事件一样。两种方式让开发者可以根据实际需求灵活选择。

NodeEx.lua提供setNodeEventEnabled方法,设置true后,重写onEnter(),onExit(),...方法就可以了

function Node:setNodeEventEnabled(enabled, listener)
    if enabled then
        if self.__node_event_handle__ then
            self:removeNodeEventListener(self.__node_event_handle__)
            self.__node_event_handle__ = nil
        end

        if not listener then
            listener = function(event)
                local name = event.name
                if name == "enter" then
                    self:onEnter()
                elseif name == "exit" then
                    self:onExit()
                elseif name == "enterTransitionFinish" then
                    self:onEnterTransitionFinish()
                elseif name == "exitTransitionStart" then
                    self:onExitTransitionStart()
                elseif name == "cleanup" then
                    self:onCleanup()
                end
            end
        end
        self.__node_event_handle__ = self:addNodeEventListener(c.NODE_EVENT, listener)
    elseif self.__node_event_handle__ then
        self:removeNodeEventListener(self.__node_event_handle__)
        self.__node_event_handle__ = nil
    end
    return self
end

猜你喜欢

转载自blog.csdn.net/ouyangshima/article/details/78039297