Tutorial:Isometric Graphics

Isometric graphics are quite popular in RPGs and strategy games, so learning how to draw a grid of isometric cubes could be useful. For the sake of this tutorial I will assume that you are using cubes of equal size as we are working on making a grid of the cubes.

First, you need some source images. If you take a look at the source we have two wonderful cubes that are supposed to represent grass and dirt (using vaguely green and brown colors respectfully). For the sake of reference I have included a border around the cubes which will show up as an actual grid as it makes it easier to discern where one cube ends and the other begins. You should also make note at the fact that the bottom and right borders is missing, this is because the cubes are supposed to form a grid nicely and we don't want to get a double-border anywhere. In your own cubes you can probably draw whatever you want to connect the cubes as you don't HAVE to have a border around it, but I will do it for this example.

Note: This code is made for cubes, but works also if you want to create a grid with only the top face. This will result in the two values block_height and block_depth (as seen below) being the same.

First of all, once we have added the images to our game, we need some values. The width and the height of each cube (easily taken from the width and height of our source images) and a third value: the block_depth. This just means the height of the top face (easier to call it "depth" than to have to write "block_face_height" or something each time) and, in this case, is half the height of the cube itself:

block_width = grass:getWidth()
block_height = grass:getHeight()
block_depth = block_height / 2

These values will be used in doing the lovely math below.


Next, we need the grid itself. A simple 2-dimensional array will do, which we will fill with the value 1 (which represents a grass cube). I also specify a grid size so I can change things easily (if I want to):

grid_size = 20
grid = {}
for x = 1,grid_size do
   grid[x] = {}
   for y = 1,grid_size do
      grid[x][y] = 1
   end
end

For good measure (and to show where the various points would be) let's change two of the grid positions into the value 2 (which represents a dirt cube):

grid[2][4] = 2
grid[6][5] = 2


The actual drawing of the grid is like this (grid_x and grid_y are variables I declared earlier to keep a track of where the center of the grid should be; these would be used when moving the grid):

for x = 1,grid_size do
   for y = 1,grid_size do
      if grid[x][y] == 1 then
         love.graphics.draw(grass,
            grid_x + ((y-x) * (block_width / 2)),
            grid_y + ((x+y) * (block_depth / 2)) - (block_depth * (grid_size / 2)))
      else -- grid[x][y] == 2
         love.graphics.draw(dirt,
            grid_x + ((y-x) * (block_width / 2)),
            grid_y + ((x+y) * (block_depth / 2)) - (block_depth * (grid_size / 2)))
      end
   end
end

But I will focus on just the grass part, to make things easier:

love.graphics.draw(grass,
   grid_x + ((y-x) * (block_width / 2)),
   grid_y + ((x+y) * (block_depth / 2)) - (block_depth * (grid_size / 2)))

This draws the grass cubes starting from the top and moving down along the top-right side, then moves one step to the bottom-left and does it again. This ensures that the cubes are all drawn in the right order so that the ones that are in the "back" will not overlap the ones in the front. This part of the code ensures that the grid_x and grid_y variables point to the center of the grid:

- (block_depth * (grid_size / 2))


Note:If you don't like that the x-coordinate goes from the top to the right and the y-coordinate goes from the top to the left, you can easily switch them by switching their places in the line:

grid_x + ((y-x) * (block_width / 2)),

Which would result in this line:

grid_x + ((x-y) * (block_width / 2)),


Now what about adding a 3rd dimension? This is easy by adding the following code to the end of the y-coordinate you pass to love.graphics.draw:

- block_depth

(multiplied by every subsequent level you go up) So if we wanted to add another level to our grid you would simply put this into the nested for-loops:

love.graphics.draw(grass,
   grid_x + ((y-x) * (block_width / 2)),
   grid_y + ((x+y) * (block_depth / 2)) - (block_depth * (grid_size / 2)) - block_depth)


I hope this has taught you how to draw a simple isometric grid which you can use for fun and profit (if you ever make a profit remember me ^^).