Skip to content
blexlol edited this page Mar 29, 2016 · 7 revisions

« 1b Tables and Loops | index | 1d Strings »

On this tutorial we’ll remove repetition from the Quad specification.

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

Prerequisites

This step assumes that you know about generic loops. They are explained on the loops tutorial.

Quads again

In the previous step we’ve learnt to specify the tiles in a compact way, by using a table (TileTable).

Something tells me we can do the same with the Quads table. Let’s give it a look:

Quads = {
  love.graphics.newQuad(0,   0, TileW, TileH, tilesetW, tilesetH), -- 1 = grass
  love.graphics.newQuad(32,  0, TileW, TileH, tilesetW, tilesetH), -- 2 = box
  love.graphics.newQuad(0,  32, TileW, TileH, tilesetW, tilesetH), -- 3 = flowers
  love.graphics.newQuad(32, 32, TileW, TileH, tilesetW, tilesetH)  -- 4 = boxtop
}

Most of the text on those lines is copy-pasted!

It might not look like a big deal now because there are only 4 quads. But imagine when we have 16, or 32 tiles!

In order to remove repetition, the first thing is taking note of which parts are repetitive and which ones change from line to line. On those lines, everything repeats, except:

  • The coordinates on which each quad starts
  • The comment at the end

quadInfo

If we were to remove all the repetitive text from those lines, then we could end up with a table similar to this one:

local quadInfo = {
  {  0,  0 }, -- 1 = grass 
  { 32,  0 }, -- 2 = box
  {  0, 32 }, -- 3 = flowers
  { 32, 32 }  -- 4 = boxTop
}

It seems like getting our old Quads variable from there should be easy enough:

Quads = {}
for i,info in ipairs(quadInfo) do
  -- info[1] = x, info[2] = y
  Quads[i] = love.graphics.newQuad(info[1], info[2], TileW, TileH, tilesetW, tilesetH)
end

Line by line:

Quads = {}

We start by initializing Quad to an empty table.

for i,info in ipairs(quadInfo) do

That is the beginning of a generic loop using ipairs. The i variable will be incremented by 1 on every iteration, and info will have the {x,y} values of each quad. So on the first iteration, info will contain the table {0, 0}, on the second one it will contain {32, 0}, etc.

In other words, it is equivalent to making:

for i=1, #quadInfo do
  local info = quadInfo[i]

I just wanted to show ipairs on this example. A loop with ipairs is slightly slower than its numeric equivalent, but I find them more readable and they are shorter. In this case the loop is being used only once, on the loading phase, so it is absolutely fine to use it.

  Quads[i] = love.graphics.newQuad(info[1], info[2], TileW, TileH, tilesetW, tilesetH)

This initializes Quads using the values stored in info, and keeping the repetitive parts in a loop.

Now our code is better prepared for the future, when we have 64 different tiles!

love.draw

We have also made some changes on love.draw. This is the new one:

function love.draw()

  for rowIndex,row in ipairs(TileTable) do
    for columnIndex,number in ipairs(row) do
      local x,y = (columnIndex-1)*TileW, (rowIndex-1)*TileH
      love.graphics.draw(Tileset, Quads[number], x, y)
    end
  end

end

It is basically equivalent to the previous drawing loop, except that we are using ipairs to iterate on both loops.

In other words, we are using generic loops instead of numeric ones (see the loops tutorial if you are not sure about the difference). This way we can create the iterator variables (rowIndex and columnIndex) at the same time that we create the values variables (row and number). So our code is a bit shorter and easier to read.

One small word of warning: using ipairs is slightly less efficient than using a plain numeric loop, despite being shorter to write and easier to read. If you are having performance issues, keep in mind that you can squeeze some cycles by transforming loops with ipairs into numeric ones. On the other hand, if you are not having performance issues, I recommend using ipairs instead – legibility is more important than getting a few extra cycles that you don’t use anyway.

Next steps

On the next step we’ll go further in optimizing TileTable by using strings.

Exercises

  1. Edit countryside.png and make it 128×64 pixels, so 4 new quads fit on the right side. Draw something on those quads – anything, it can be just letters. Then add the information of your 4 new tiles to quadInfo, so that your new tiles become numbers 5,6,7 & 8. Modify some numbers in TileTable so they point to your newly created tiles.

« 1b Tables and Loops | index | 1d Strings »

Clone this wiki locally