Skip to content
Howld edited this page Dec 12, 2015 · 8 revisions

« 1e Functions | index | 1g Global Variables »

On this step we’ll split the code we have into several parts.

The complete source code of this step can be found here:

The problems

Cleanliness

First, there’s the obvious motivation: we want main.lua to be as clean as possible. By clean we mean that it should be a hub were the game starts, draws, and ends – but it should not delve on the specifics. Those should be moved to different files.

In order to do that, we can use Lua’s require function:

-- main.lua
require 'map-functions'

function love.load()

  ... -- define tileString and quadInfo
  
  loadMap(32,32,'countryside.png',tileString,quadInfo) -- loadMap is now in map-functions.lua
end

function love.draw()
  drawMap() -- drawMap is also defined in map-functions.lua
end

Now that we’re starting getting more files, we should also move the images to a subfolder – We’ll call it images. Our paths will have to be modified so the tileset is now loaded from there.

That is well and good. However, there’s a second problem what we should fix.

Single-mapness

Right now our game is only able to load a single Map. Changing the map requires manually modifying the newly-created map-functions.lua.

We have already paved the way for multiple-mapness. On the previous step, we separated the map-specific data from loadMap and we put it inside love.load.

On this section we’ll move each map’s specific data to its own file.

  • Map data will be on a file inside the /maps/ directory.
  • loadMap will take a single parameter: the path to the file that defines a map
  • love.load will look like this:
    function love.load()
      loadMap('/maps/map1.lua')
  • A new function, called newMap, will do what loadMap used to do. It will be called from inside the files inside the /map/ directory.

So the /maps/map1.lua file, if it existed, should call newMap with the right parameters at some point.

Sample tilemaps

On this lesson we’ll abandon countriside.png and will use two new tilemaps.

Since we’ll start getting more and more files, I’ve decided to put the images inside an /images/ subfolder.

This will be the resto tileset (/images/resto.png)

And this will be the lab tileset (/images/lab.png)

Sample maps

I’ve also created a couple sample maps (one per tilemap). The first one is a small tavern, called “Chez Peter”. It will look like this:

The second example is a computer room called “Core Dump”.

On the sourcecode of this example, Chez Peter is loaded by default. This is the complete source of the new main.lua:

require 'map-functions'

function love.load()
  loadMap('maps/chez-peter.lua')
end

function love.draw()
  drawMap()
end

Changing so it loads core dump would be as simple as modifying the line that says loadMap('maps/chez-peter.lua') with loadMap('maps/core-dump.lua') .

chez-peter.lua is a lua file that simply invokes newMap with the correct parameters:

-- file: /maps/chez-peter.lua
local tileString = [[
#########################
#                #      #
#  L[]R   L[]R   # L[]R #
#  L()R   L()R   # L()R #
#                #      #
#                ###  ###
#  L[]R   L[]R          #
#  L()R   L()R    L[]R  #
#                 L()R  #
#                       #
#  L[]R   L[]R          #
#  L()R   L()R   ###  ###
#                #LL  RR#
#                #LL  RR#
#  L[]R   L[]R   #LL  RR#
#  L()R   L()R   #LL  RR#
#                #LL  RR#
#########################
]]

local quadInfo = { 
  { ' ',  0,  0 }, -- floor 
  { '[', 32,  0 }, -- table top left
  { ']', 64,  0 }, -- table top right
  { '(', 32, 32 }, -- table bottom left
  { ')', 64, 32 }, -- table bottom right
  { 'L',  0, 32 }, -- chair on the left
  { 'R', 96, 32 }, -- chair on the right
  { '#', 96,  0 }  -- bricks
}

newMap(32,32,'/images/resto.png', tileString, quadInfo)

core-dump.lua is very similar so I will not show it here.

newMap

The newMap function is a line-by-line copy of the previous loadMap function: it accepts some parameters and builds some global variables with them. It is defined inside map-functions.lua now:

function newMap(tileW, tileH, tilesetPath, tileString, quadInfo)
  
  TileW = tileW
  TileH = tileH
  Tileset = love.graphics.newImage(tilesetPath)
  
  local tilesetW, tilesetH = Tileset:getWidth(), Tileset:getHeight()
  
  Quads = {}
  
  for _,info in ipairs(quadInfo) do
    -- info[1] = the character, info[2] = x, info[3] = y
    Quads[info[1]] = love.graphics.newQuad(info[2], info[3], TileW,  TileH, tilesetW, tilesetH)
  end
  
  TileTable = {}
  
  local width = #(tileString:match("[^\n]+"))

  for x = 1,width,1 do TileTable[x] = {} end

  local x,y = 1,1
  for row in tileString:gmatch("[^\n]+") do
    assert(#row == width, 'Map is not aligned: width of row ' .. tostring(y) .. ' should be ' .. tostring(width) .. ', but it is ' .. tostring(#row))
    x = 1
    for tile in row:gmatch(".") do
      TileTable[x][y] = tile
      x = x + 1
    end
    y=y+1
  end

end

loadMap

The loadMap function has changed. It uses love.filesystem.load.

function loadMap(path)
  love.filesystem.load(path)() -- attention! extra parenthesis
end

The only thing worth mentioning about this implementation is those parenthesis at the end.

If you read the love.filesystem.load documentation, it says it very clearly: that function does not “invoke” a lua file. It returns a “chunk”, which is like a function than, when executed, runs the code in the file. In a way, it similar to a function declaration. We could have re-written the code above like this:

function loadMap(path)
  local f = love.filesystem.load(path) -- obtain a function
  f() -- run a function
end

Conclusions

On this section we started using several folders and files in our project. We also separated map-specific code from code that could be used on any map. Finally, we made an extra function that allowed for super-clean map loading with very little code.

On our next function, we’ll finish cleaning up by removing unnecesary global variables.

Exercises

  1. Make sure that you are able to load both maps: Chez Peter and Core Dump, by changing the path of the map loaded inside love.load.
  2. Experiment by modifying the layout of Chez Peter – move chairs around, remove one table, etc.
  3. Create your own map! You can use the tilesets on this step (lab.png or resto.png), the one used on previous steps (countryside.png) or a new one created by you.

« 1e Functions | index | 1g Global Variables »