For my game, I decided to go with a relatively unusual projection called oblique projection.
There are several reasons why I picked this particular projection as opposed to the most popular isometric projection.
For one, it is sprite friendly. This projection works better along with side-view flat sprites, such as those in platform games.
The image above illustrates this well. Look at the character, especially his feet. You can see how the sprite looks aligned with the plane, and this feels right. You don't need to add any real depth to the character by placing one feet further to the back. Flat sprites like this just work.
On the other hand, the isometric projection forces you to perceive a 3D direction for the player. Using a flat sprite, it looks like it is aligned to the diagonal line across the plane. The isometric projection is also perceptually from a more vertical angle, as if the camera was higher up from the ground.
If you think about it, the oblique projection is nothing but your standard sideways 2D projection with some depth axis slapped onto it. This new axis could point anywhere, even directly up, but having it go diagonally at a 45° angle allows you to actually show the depth axis on its own, enhancing the sense of depth.
Another important thing to notice is that the horizontal axis is truly horizontal in the oblique projection, and that the depth axis is visually unambiguous: it is immediately obvious where the character will move to once you press the up key.
On the isometric projection, this is not the case. Up could be both to the upper left or to the upper right. You'll have to pick one, arbitrarily, and the player will have to deal with it.
Or you could make it go truly up across the screen, diagonally in the world's axes, but this would be a recipe for disaster, since our entire world is made of boxes aligned with the world grid, and the character movement will clash with this alignment.
Isometric also fails regarding animations. In order for them to look correct, you need several angles for the character walk/run cycles, which means more time spent drawing and animating. On oblique projection, the effect of recycling animations doesn't look that bad.
Of course, none of this would be a big issue if your isometric game is just a turn based RPG or something like Sim City, but for a 2.5D platformer, these issues are important.
Having settled on the type of projection, it is time to construct our world. This is where problems began.
The big problem with tile-based 2.5D: depth sorting
On tile-based 2.5D, it is very common to use the Painter's algorithm to draw the scene. In order to do this properly, you need to accurately compute the actual depth of each tile before drawing, otherwise you'll run into problems.
Assuming tiles of the exact same size, this is not a problem. By simply drawing rows in the right order, you can get a perfect result every time. This also works every time if you don't stack tiles into columns. As long as you draw things in the right order, you should be fine.
But this is not always the case. Consider the following, well-known example:
In this scenario, all three boxes must be both behind and in front of the others. So how do we resolve this?
Remember when I said it would work perfectly if you assumed tiles were the same size?
That is the golden idea here. If you break apart these objects into equal elements, you can safely reach your desired result.
Of course, this is not feasible if you are working with completely arbitrary sized boxes. For that, you need more complicated algorithms, which you can find elsewhere on the Internet. In my game, this sort of thing will not be necessary.
But the technique of breaking apart objects is important because it also applies to a common issue in 2.5D games like this: drawing sprites using the Painter's algorithm.
As the image illustrates, you'll run into problems no matter how you decide to draw the sprite.
The solution here is to break the sprite into parts. If the sprite is 4 tiles high, you slice it in 4 and draw each piece as if it were a tile. If it is 4 tiles wide, you can do the same thing horizontally.
But since the sprite is infinitely thin, you don't need to worry about slicing its depth axis. Just make sure you draw in the proper position and you'll be done.
The result of this can be seen in the following video.
Resolving this issue means I can finally work on collisions! But that'll be the subject of another post.