将单个lua函数分解为小文件

时间:2014-05-27 23:21:44

标签: lua code-cleanup love2d

我正在使用Lua和LÖVE进行游戏。

我更喜欢基于闭包的OOP方法,每个级别都是一个包含运行游戏所需的所有本地和函数的函数的新实例。

我想将这个单一功能分解为多个文件。我目前的解决方案与我在此处所做的类似:concatenating multiple files into a single one - 但我真的不认为这是理想的。

例如,我将从下面的代码段中获得一个带有self.load函数的load.lua文件。

巨型函数的代码片段,供以下参考:

levelSetup = function()
local time = 60
local timer = time
local timerIsRunning = true
local danger = 10
local handSize = 2
local itemsLeft = handSize
local curHand = 0
local lastHand = 10
local multiplier = 1
local self = {}

------------------------------------------------------
-- Initialize Values based on level Creation
------------------------------------------------------
self.load = function()
  if curLevel.time == 1 then
    time = 60
  elseif curLevel.time == 2 then
    time = 40
    multiplier = multiplier*1.5
  else
    time = 20
    multiplier = multiplier*2
  end

  if curLevel.danger == 1 then
    danger = 10 --low catastrophe chance
  elseif curLevel.danger == 2 then
    danger = 30 --medium chance
    multiplier = multiplier*1.5
  else
    danger = 50--high chance!
    multiplier = multiplier*2
  end

  if curLevel.handSize == 1 then
    handSize = 2
  elseif curLevel.handSize == 2 then
    handSize = 3
    multiplier = multiplier*1.5
  else
    handSize = 4
    multiplier = multiplier*2
  end
  itemsLeft = handSize
  timer = time
  self.nextHand()
end

  return self
end

最佳解决方案是什么?

2 个答案:

答案 0 :(得分:1)

将代码分解为较小的文件总是好的。如果你打算这样做,一个优雅的解决方案(以我的拙见)将使用return声明。这是Lua生态系统中的very common and preferred practice

我们假设您的项目包含几个子模块,分别是 submoduleA.lua submoduleB.lua submoduleC.lua < / em>的。每个子模块都包含一些专用代码(它可以是单个函数,也可以是一组函数,但我们假设每个子模块中都有一个函数)。

添加到这些子模块中,您还有一个主文件(名为 main.lua ),您可以从中调用并使用子模块中定义的函数。

submoduleA.lua 将包含名为 funcA 的某个函数的定义。这个函数可以有自己的本地,并使用upvalues,没问题。理想情况下,对于范围问题,此 funcA 应声明为 submoduleA.lua 文件中的本地。然后,在文件末尾,使用return语句返回函数本身。

-- declaring upvalues, if any
local upvalue1 = ... -- placeholder code
local upvalue2 = ... -- placeholder code

-- function definition
local function funcA(arg1, arg2, ...)
  -- some code
end

return funcA -- at the end of the file

submoduleB.lua submoduleC.lua

同样如此

然后,在 main.lua 文件中,您可以使用require语句轻松调用子模块中定义的函数。请注意require的一个详细信息,您不需要添加扩展名“.lua”,因为它会自动执行此操作(文档非常清楚)。

local funcA = require ('submoduleA') 
local funcB = require ('submoduleB')
local funcC = require ('submoduleC')

就是这样。同样,这是Lua非常常见的模式。我在编写自己的项目/库时使用类似的技术,特别是当代码跨越多个文件时。请参阅JumperFloodFill,以供参考。

我还会推荐那些深入反思的附加讲座,因为他们在编写Lua模块时会指出一些非常好的策略:

希望这有帮助。

答案 1 :(得分:1)

必须在单个块中定义函数。但是,使用load函数,您可以使用多个源汇编块数据。 E.g:

function closuredef( ... )
  local modules, n = { ... }, select( "#", ... )
  local index = -1
  local function reader()
    index = index + 1
    if index == 0 then -- chunk prefix
      return "local self = {};"
    elseif index == n+1 then -- chunk suffix
      return "\nreturn self"
    else -- read specified Lua files and add them to the chunk data
      local modname = modules[ index ]
      if modname ~= nil then
        local fname = assert( package.searchpath( modname, package.path ) )
        local file = assert( io.open( fname, "r" ) )
        local data = assert( file:read( "*a" ), "could not read '"..fname.."'" )
        file:close()
        return data
      end
    end
  end
  return assert( load( reader, "=closuredef" ) )
end

levelSetup = closuredef( "level.variables", "level.load" )

此示例实现使用package.searchpath(在Lua 5.2中是新的)来实现 指定Lua文件更方便。如果仍然使用Lua 5.1,则可以使用绝对文件名或实现自己的package.searchpath函数。有关示例,请参阅hereherehere

我不确定这是解决您问题的最佳解决方案,例如您将很难将错误消息中的行号映射到实际错误位置......