Fake 3D Isometric Engines
I have to admit, I've been getting so much email on this topic, I feel like I should have just written a book called Isometric 3D Games! What are those, you ask? Well, they're games in which the viewpoint is at some skewed angle, such as 45 degrees. Some of the old isometric (ISO) 3D games include Zaxxon, PaperBoy, and Marble Madness.
These days ISO games are making a comeback—Diablo, Loaded, and a slew of RPGs and wargames use it. Its popularity stems from that fact that the view allows a lot of cool gameplay and fairly interesting visuals as compared to full 3D. And of course, ISO 3D is about 10 times easier to create than full 3D. So how do you do it?
Well, this is a secret in the game community, and it's not something that anyone writes about too much. What I'm going to do is give you some food for thought and describe a couple of ways to do this. The hints I give you here should be more than enough for you to implement an ISO engine yourself.
If you really want to learn ISO 3D game programming then check out Isometric Game Programming with DirectX 7.0 by Ernest Pazera.
There are three ways to approach ISO 3D:
Method 1: Cell-Based, Totally 2D
With Method 1, basically you have to decide on your angle of view and then draw all your artwork with that in mind. Usually, you'll draw everything as rectangular tiles, just like you would with a normal scrolling engine. Take a look at the art cells in Figure 8.49.
However, the tricky part comes with the rendering. When you draw the universe, you can't just draw things in any order that you want. You must draw the bitmaps so that the far objects are occluded by near ones. In essence, draw the screen like a painter does, from back to front. Hence, if you have a straight 45-degree view—meaning that the art is tilted 45 degrees from the top view—and you draw the screen from top to bottom, the order should be correct.
This is important when you have an object like a tree, and a little character walks behind the tree. It had better look like the little guy's behind it. Hence, you must make sure to draw him at the right time in the display list. Take a look at Figure 8.50 to see the problem. This is almost a no-brainer if you just make sure to draw the character at the right time, which is after the row that's slightly behind the character and before the row that's slightly in front. This is also shown in Figure 8.50. So, the bottom line is that you have to work out a little math and sorting to draw moveable objects at the right times.
Also, you may have an ISO engine with tiles of varying height. Or in other words, each tile can extend many tiles high. You could just put multiple tiles at multiple row positions, or take height into consideration and think of each row of tiles as varying heights. When you render, you may have to start rendering the current row at a y-position higher than the actual row position.
Figure 8.51 shows this case graphically. There's no difference in drawing this; the only problem is locating the starting y for each block height you add onto the current row. Basically, it's just the height of a cell.
Now, let's make thinks a little harder. What if the angle is 45 tilt and 45 yaw? Or in other words, a standard Diablo or Zaxxon view? In this case, you just need to order your rendering on the x-axis also. So you must draw from left to right (or right to left, depending on the direction of yaw) and from top to bottom. And again, you'll need to sort your objects on both the x- and y-axis when drawing.
Well, think about it: That's one way to do it. Of course, there are a lot of details when it comes to collision and so forth, and many game programmers use complex coordinate systems based on hexagons or octagons and then map objects into these systems, but this technique will get you going.
Method 2: Full-Screen-Based, with 2D or 3D Collision Networks
The full-screen method is much cooler than using tiles. Basically, what you do is draw an ISO 3D world any way you like (with a 3D modeler or what have you), and you can make each screen any size you want. Then you create a secondary data structure that contains collision information that is overlaid onto the fake 2D world. Using this technique, you augment the 2D information (which has no height or collision data) with extra 2D/3D information, either 2D or 3D, depending on how complex you want to get.
Then you simply draw the background bitmap all at once, but as you draw all your moveable objects, you clip them to the extra geometrical data that is overlaid onto the 2D/pseudo-3D image. Take a look at Figure 8.52 to see this. Here you see a 2D-rendered scene that looks ISO.
In Figure 8.53, you see the same scene with polygon information overlaid on it. This is what you use to clip, do collisions, and so forth.
To generate it, you can do one of two things: Extract it from the 3D modeler, or write a tool that allows you to literally draw the information on each screen full of data. I've used both methods, so it's up to you. However, I suggest you use a 3D modeler to draw your universes and then figure out a way to export only certain important geometry. Drawing the collision geometry by hand with a tool is time-consuming, and one change in the graphics means a redo!
Method 3: Using Full 3D Math, with a Fixed Camera View
This is the easiest of all because there aren't any tricks. Basically, using a full 3D engine, you simply lock the camera at an ISO view and you have an ISO game. Moreover, because you know that the view is always at a certain angle, you can make certain optimizations and assumptions about the drawing order and the scene complexity. This is how many ISO games on the Sony PlayStation I and II work—they're really full 3D, but they're locked in a 45-degree view.
As I said, this scrolling stuff is really a 2D topic and could fill up a small book in itself, so I've placed additional articles on the CD if you haven't had enough.