Tutorial: Working With a Grid Layout

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.

[gist id=8387deec14650adf03a4]

First, we define some constants: the number of rows and columns as GRID_WIDTH and GRID_HEIGHT respectively. We also define the width and height of each cell on the grid as CELL_WIDTH and 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 gbOffsetX and gbOffsetY based on the grid image’s location and size.

Referencing Cells

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[4][5]

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, xPos and yPos, are expected to represent the position in the grid.

Spawning Pieces

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.

Moving Pieces

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.

Rob Miracle

Rob Miracle creates mobile apps for his own enjoyment and the amusement of others. He serves the Corona Community in the forums, on the blog, and at local events.

  • J. A. Whye
    Posted at 02:53h, 09 April

    A while back I created a utility that helped me with a grid-based problem. Given any location in any sized grind, I wanted to know which grid squares were around it (left, right, up, down, and diagonals).

    I ended up with the code you can see here:

    There’s probably some cool math-based way that makes the solution a one-liner, but until someone posts that, feel free to use that code if it helps solve your problem.