07 April 2015
Tutorial: Working With a Grid Layout
Many games use a grid where pieces or items are positioned in rows and columns. Classic examples would be chess or checkers, but even more modern games like Candy Crush™ position the pieces in a grid as well.
Mechanically, a grid is nothing more than a two-dimensional array, and each element in the array represents a single spot on the grid. In Lua, two-dimensional arrays are basically a table in which each child table represents a row for the grid, and each entry in that row table represents a column index within the row.
Let’s look at the core Lua code used in a demo project which you should download and experiment with alongside this tutorial.
First, we define some constants: the number of rows and columns as
GRID_HEIGHT respectively. We also define the width and height of each cell on the grid as
CELL_HEIGHT. Following this, we create an empty table for the overall grid, then we execute a loop for the total number of rows in the grid (
GRID_HEIGHT) and, in that index position, we create another empty table which will represent the overall row.
Next, we place the grid’s image on the screen and position it in the center of the content area. Then we create two more constants for offsetting pieces relative to the image. Here, we calculate
gbOffsetY based on the grid image’s location and size.
Because we have effectively created a “stack of rows,” a specific cell must be referenced in a
[row][column] manner as follows:
local somePiece = grid
This code will reference the cell 5 positions from the left (5th column) and 4 positions from the top (4th row). Thus, the row value comes first and the column value second.
Now conceptually, it may be more logical to reference cell positions as an
x,y coordinate position, or in other words, a “column, row” format. For example, the top-left space on a checkers board would be
1,1 and the top-right space would be
8,1 (remember that checkers uses an 8×8 board). Thus, when calling the
spawnPiece() function, two parameters,
yPos, are expected to represent the position in the grid.
Within the actual
spawnPiece() function, we first validate the parameters passed in. This includes checking the piece type and ensuring that the cell position is not outside the range (size) of the grid. If the validation succeeds, we generate the piece’s display object and store the piece’s position on the board as attributes of that object. Finally, we place the piece in the actual screen position (pixel coordinates) based on the constants we defined earlier.
The next function is used to move a piece. In this example, we test this function by calling it after a timer of 2 seconds, but this would likely be done via a touch, swipe, selecting the piece and tapping its destination, or any number of other methods.
In any case, within the
movePiece() function, we first validate that the requested position is within range of the grid and confirm that the position is not occupied by another piece. If the validation passes, we move the piece’s position within the
grid table and then visually slide (transition) the piece to the new position.
As shown in this tutorial, it’s simple to use a two-dimensional array to create a grid, store the position of pieces within the array, and use basic math to position and move the visual pieces based on logical coordinates. Remember to download the demo project to experiment with and edit for use in your own grid-based app project.