-
Notifications
You must be signed in to change notification settings - Fork 37
1c more tables
« 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:
This step assumes that you know about generic loops. They are explained on the loops tutorial.
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
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!
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.
On the next step we’ll go further in optimizing TileTable
by using strings.
- 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 inTileTable
so they point to your newly created tiles.