Search code examples
luacode-cleanuplove2d

Breaking a single lua function into small files


I'm working on a game using Lua and LÖVE.

I prefer a closure based approach to OOP and each level is a new instance of a function containing all the locals and functions needed to run the game.

I'd like to break this single function into multiple files. My current solution is similar to what I did here: concatenating multiple files into a single one - but I really don't think this is ideal yet.

For instance, I would have a load.lua file with the self.load function from the snippet below.

Code snippet of giant function for reference below:

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

What is the best solution for this?


Solution

  • A function must be defined in a single chunk. However, using the load function you can assemble your chunk data using multiple sources. 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" )
    

    This sample implementation uses package.searchpath (which is new in Lua 5.2) to make specifying Lua files more convenient. If you still use Lua 5.1, you can use absolute file names or implement your own package.searchpath function. See here, here, or here for samples.

    I'm not sure this is the best solution for your problem though, e.g. you will have a hard time mapping line numbers in error messages to the real error locations ...