在 Corona SDK 中的对象中放置监听器函数

是否可能将监听器函数放置在对象模块中?

我有一个实现显示对象的 Cloud 类。目前,该类只创建图像。我希望它也负责自己的监听事件,这样我就不需要为我生成的每个对象调用 addEventListener。

我尝试了几种变化,但最终监听函数始终为 null。我也尝试过将 addEventListener 函数拆分,以便在主函数中调用。

我开始感到对象中的监听器函数不受支持了。也许我对此采取了错误的方法?我的要求可行吗?如果是,我做错了什么呢?

--
-- Cloud.lua
--

local Cloud = {}
local mtaCloud = { __index = cloud } -- metatable

local display = require "display"

-- DOESN'T WORK
function Cloud.scroll( event )
  img.y = img.y - img.scrollSpeed
  if (img.y + img.contentWidth) < 0 then
    img.x = 0
    img:translate( math.random(1,_W), 1800  )
  end
end

function Cloud.New( strImage, intHeight, intWidth, intScrollSpeed)

  local image = display.newImageRect( strImage, intWidth, intHeight )
  image.anchorX = 0; image.anchorY = 0.5;
  image.x = _W/2; image.y = _H/2;
  image.scrollSpeed = 10
  image.enterFrame = scroll
  Runtime:addEventListener("enterFrame", scroll)

  local newCloud = {

    img = image

  }

return setmetatable( newCloud, mtaCloud )

end

return Cloud

-- main.lua (simplified)
local cloud = require "object.cloud"

function scene:create( event )
  local group = self.view
  cloud = cloud.New("img/cloud.png", 230, 140)
  group:insert(cloud.img)
end
点赞
用户3455883
用户3455883

是的,如果你指的是在面向对象编程中讨论的对象,那么可以在对象上设置监听器,具体请参考 Programming in Lua 第 16 章。这涉及正确获取 self 的引用。我在这个回答中包含了一个可以正常工作的实现。

我不确定你是否可以在 DisplayObject 上执行此操作,但这也不是你示例中的处理对象(DisplayObject 是你的 image,而不是你的构造函数 Cloud.New() 返回的对象,它是表 newCloud)。

这里有一种可以保证工作的方法。你的 Cloud.lua 应该像这样子(我在这个示例中使用了 ShapeObject 进行测试;你需要更改并使用自己的图像资源):

-- Cloud.lua

local Cloud = {}

function Cloud:scroll()

    self.img.x = self.img.x + self.scrollSpeed
    if self.img.x >= display.contentWidth + self.img.contentWidth then
        self.img.x = - self.img.contentWidth
    end

end

function Cloud:enterFrame( event )
    self:scroll()
end

function Cloud:new( intHeight, intWidth, intScrollSpeed )

    local aCloud = {}

    local img = display.newRect( 0, 0, intWidth, intHeight )
    img:setFillColor( 1 )

    aCloud.img = img
    aCloud.scrollSpeed = intScrollSpeed
    aCloud.id = id

    setmetatable( aCloud, self )
    self.__index = self

    Runtime:addEventListener( "enterFrame", aCloud )

    return aCloud

end

return Cloud

请注意 Cloud:new() 函数中的 setmetatable 以及 self.__index = self。这很关键。

我在函数定义中使用了“冒号表示法”(例如 Cloud:new(...)),这是一种语法糖,用于将函数的第一个参数设置为 self(例如 Cloud.new( self, ...))。

此外,我使用的是对象(表)监听器(而不是函数)。在每个 enterFrame 事件中,Runtime 会检查对象(即在指定表中找到的函数是否存在)并调用 enterFrame() 函数。

假设项目子目录“objects”中有一个名为“Cloud.lua”的文件,在你的 scene 中,你需要这样:

local cloud = require("objects.Cloud")

local maxScrollRate = 4
local cloud1 = cloud:new( 100, 50, 1 + math.random( maxScrollRate )  )
cloud1.img.x = 200
cloud1.img.y = 200
sceneGroup:insert(cloud1.img)

local cloud2 = cloud:new( 100, 50, 1 + math.random( maxScrollRate ) )
cloud2.img.x = 100
cloud2.img.y = 400
sceneGroup:insert(cloud2.img)

希望这能有所帮助。

2017-03-14 16:46:13