If you’re hacking a game together for a jam or #1GAM, you’re probably not too concerned about doing it “the right way”. In this article, I’ll share some tips for drawing and coding pseudo-isometric levels quickly and easily.
Technically, “isometric” refers to a projection where the angle between the x-, y-, and z-axes (in screen dimensions) is 120°. And the proper way to convert between screen coordinates and isometric coordinates is by using a transformation matrix.
But forget that! In this Quick Tip, we’re going to cut some corners and cheat a little.
1. Drawing a Grid
Check this out. We can turn a regular, 90°-grid into something that looks close enough to an isometric grid with two simple steps.
Step 0
Start with a grid like this (I’ll call this a Cartesian grid):
Step 1
Rotate it 45°:
Step 2
Squash it 50% vertically:
Done! This should correctly be referred to as dimetric rather than isometric, as explained in this wonderful article, but it’ll do for most purposes.
2. Adding an Object
That grid’s not going to make much of a game on its own. Maybe you want to add chess pieces, maybe you want to add monsters – whatever you add, you’ll need to know where to put it.
Here’s the object I’ll use (from The Noun Project):
We don’t need to rotate it or squash it to make it fit on the grid; just scale it down appropriately:
As you can see, the base (the guy’s feet, in this case) should just go in the centre of the grid space. So we need to figure out where this is.
We could use trigonometry or a transformation matrix or something, but there’s some simple algebra that’ll do the job.
Step 1
Measure the diagonal tile half-width and half-height (in screen dimensions):
var tileHalfWidth = 17.5; var tileHalfHeight = 8.75;
Step 2
Figure out the grid indices of the space you’re interested in:
As you can see, I use the centre of the grid as the origin. The guy is standing on space (4, 2)
.
Step 3
Convert the grid space coordinates to screen coordinates, using this formula:
screenX = (isoX - isoY) * tileHalfWidth; screenY = (isoX + isoY) * tileHalfHeight;
In our case, this will give screen coordinates of (35, 52.5)
.
This is actually the “top” corner of the space; to get the centre of the space, you’ll need to add tileHalfHeight
to the result for screenY
.
Step 4
You’ll need to add an offset. Just manually figure out the coordinates of the origin (centre) grid space, in screen coordinates, and add them to (screenX, screenY)
.
Your final conversion code looks like this:
screenX = ((isoX - isoY) * tileHalfWidth) + screenOriginOffsetX; screenY = ((isoX + isoY) * tileHalfHeight) + tileHalfHeight + screenOriginOffsetY;
3. Mapping a Click to a Space
Suppose we want to spawn an object in whichever grid space the player clicks on. How do we figure out which space was clicked?
With a little algebra, we can just rearrange the above equations to get this:
// First, adjust for the offset: var adjScreenX = screenX - screenOriginOffsetX; var adjScreenY = screenY - screenOriginOffsetY; // Now, retrieve the grid space: isoX = ((adjScreenY / tileHalfHeight) + (adjScreenX / tileHalfWidth)) / 2; isoY = ((adjScreenY / tileHalfHeight) - (adjScreenX / tileHalfWidth)) / 2;
Then just lop off everything past the decimal points to figure out which grid space this is.
4. Rendering Multiple Objects
One little thing to remember: if you’re blitting, make sure you render the objects in the back first! Otherwise, you could end up with some weird overlapping effects:
It’s simple to do this; you just need to order those with the lowest (that is, top-most) screenY
values first:
Note as well that you don’t need to resize the objects based on their distance from you; with a pseudo-isometric view like this, objects that are further away do not appear smaller than those closer to you.