To do this we take the objects/tiles position on the map and translate it, so we grab it's 'x' and 'y' on the map and set new variables, we'll call isoX and isoY based on it's current position.
isoX = ((x-y));
isoY = ((x+y)/2);
This will translate the 'x' and 'y' into isometric coordinates, but we need to do a little more here then that. For everything to tile nicely we need to make sure that the 'x' and 'y' are aligned onto a grid, so when translated and drawn the tiles align correctly. What size should our grid be though? A good rule is that it needs to be a square grid, like 16x16 or 32x32 for example. Sizes like 32x16 will place our tiles all wonky, remember this isn't our isometric tiles size just our top down grid. For our example we'll use 64x32 as the isometric tiles dimensions.
What we want to do is make the grid for the top down map the size of the height of our tiles or 32x32 in our case. Why would we do that though? When the engine starts layering the tiles we need them to match up. Isometric tiles are drawn offset from each other with each row or column being offset usually by half of the tile size, so that the edges of the diamond shapes match up. If you look at this example, I highlighted the edges of the tiles touching. If the tiles are not offset correctly the edges won't line up. You can also see how the tiles are placed in a zig zag pattern.
What about width? Remember isometric shifts each column of tiles in one direction so that the diamond shape of the tiles interlock and match up. We said the grid needs to be square, so if our height is 32 then our width must be 32 as well. Which just " happens ;) " to be exactly half of our tiles actual width, which when the grid is offset it is done by 32 and the tiles line up. It's important to have your tiles be the correct size and your grid setup to account for this otherwise tiles will overlap and not line up at all. I will discuss in a later blog post how to deal with uncommon isometric tiles that are for example 64x16(a very shallow isometric angle) or 64x48 ( a very steep one).
I know your asking, "But my tiles are not flat, they have varying heights. What about that?". That is true but all those tiles "should" be based of a default tile that "IS" flat or in a correctly proportioned cube. For example our tiles are 64x32 but if it was a cube tile, it would actually be 64x64 in size. So what do we do? we know that we can take that cubed tile and actually make it flat again into a 64x32 (the bottom face of the cube) so what we need to do is make sure the tiles origin is offset so that its at that 64x32 mark. Look at the picture below, it has our tile as a flat tile, then cubed. We show the bottom face of the tile highlighted in red, I included a textured tile as well for visualizing that bottom face.
To set the new origin for the CoinPurse engine, this is as simple as counting up from the bottom 32 pixels and setting the origin there. We maintain our tiles origin to the left so it's 'x' is always equal to 0 but it's 'y' is either 0 or adjusted depending on the tiles height and where the "bottom face" of the tile would be. The CoinPurse Engine does this because and I will discuss later, probably next weeks blog post, our tiles depth is determined by it's y and x so the further up and to the left you are the "deeper" in the map the tiles should be. Keeping the tiles origin in this location makes most of the work later on way easier and keeps such a nice consistency to handling the depth.
After we keep all this in mind when our map is finally drawn, everything will be lined up perfectly and we'll have an isometric map! We use the same tricks for other game objects like "players" or "enemies" within the game, converting there position on the map and drawing them in isometric, all the while technically the player is playing a top down game that just appears isometric. This is a really simple concept to grasp, once you have everything being drawn into isometric it makes adding anything else to the game very easy, and that has been the goal for the engine from the beginning. Provide scripts people can plop down in the "Create" and "Draw" event of an object and everything else works, from movement to the game view.
That's how the core of the engine works :) and in next weeks blog post, I'll discuss how depth and the Z axis comes into play with all of this. Be sure to leave and questions/comments you may have for me or the engine and thanks for reading! Be sure to follow/subscribe/share!