- Title: Easy Top-down --> Isometric Converting
- Description: Easilly converts back and forth between isometric and top-down.
- GM Version: GM 8 (But the scripts alone should work with older versions of Game Maker)
- Registered: Probably not.
- File Type: .gmk
- File Size: 0.02MB
- File Link: Download Here
The example isn't too flash but the engine is very capable. Hope you like it! Credit would be lovely, but not required. Apologies about the game info btw. I was originally going to write the tutorial there but I decided on the site here was a bit nicer. THis way people can see the functions before they download. YAY!
Isometric is a perspective without perspective (ha! a witty opener) and I still don't know of a simple way to explain it (hence the Age of Empires image). Basically it takes the x and y axis and puts them on angles, then adds a third axis (z) in the upwards direction. Its often used in tech drawing, but became quite popular during the 90's in rts games. Sadly it has almost died out, but that's what we are here for! So shall we get started?
So one day, having done a bit of research into this isometric business, it occured to me that calculating EVERYTHING in isomtric was very difficult. Almost as hard as calculating regular 3d, so I tried to think of ways my poor little artist brain could understand it. The conclusion I eventually came to was this engine.
Basically what happens is the entire game is calculated like a top-down game, until it comes time to render the thing. Before it is drawn, all instances calcuate their isometric co-ordinates and they are drawn there instead. This gives the illusion of isometric, while allowing for all of Game Maker's other functions to be used in a simle way (mp_grids for example). This was a break through for me because all of a sudden I had a very simple way of transferring top-down movement (which lets face it is rather boring) into psuedo 3d movement! And I didn't even need to do any of those stupid calculations where I need to reduce speed by half when moving vertical and pathfind around diamond tiles etc.
The other great thing about only drawing in isometric is its REALLY easy to change the view-point of the game. Thaaaaaaaat's right, this engine can render in four different view points (NE,SE,SW and NW), and possibly even top-down if you make it so. Anyway without further ado, on to the engine itself.
The Isometric Engine
To start with we need to set up the game to allow isometric rendering. There is ONE function that will do this for you
iso_start(factor) Begins viewing the room in an isometric projection.
Now what this does is sets up all the variables needed for the isometric engine to work, so MAKE SURE YOU CALL IT BEFORE ANY OTHER FUNCTION. factor refers to the ratio of the y axis to x. So if we want the 'diamond' to be half as tall as it is wide, all we need to put here is 0.5 and done.
Note: In this isometric engine the co-ordinates actually work the opposite way to what you would think. In the 'top-down' processing, everything needs 3 co-ordinates, so that the isometric position can be calculated but when it comes to the isometric rendering, we actually only need two, x and y, because we are talking in terms of the position on the screen rather than the position in the room. The screen is 2d, the room 3d catch my drift? Hope that's clear enough.
Once we have the game set up there is another thing we can do that's very simple and that is set the projection.
iso_set_projection(direction) Sets the direction in which the world will be viewed.
The game automatically sets itself to North-East projection but this can be changed to 3 other directions, each with a corresponding numerical value.
So for direction, 0=North East, 1=South East, 2=South West and 3=North West. Nothing else needs changing for all the other functions to work correctly.
So once we have the easy stuff out of the way, its time to get on to the truely useful functions. These functions calculate an objects drawing co-ordinates, based on its 3 dimensional position in the room.
iso_get_x(x,y,z) Function returns the x co-ordinate used for drawing the instance in isometric.
iso_get_y(x,y,z) Function returns the y co-ordinate used for drawing the instance in isometric.
Easy enough? Before you draw, simply call these functions to find the x and y positions wher you should draw
Note: Make sure you take a look at the spriting tips below to ensure the position is correct.
So what happens if we have something on the screen like the mouse? Remember mouse_x and mouse_y are no longer the mouses position in the room, they are its isometric drawing co-ordinates. To get its real position, we need to perform the following functions.
iso_get_regx(isox,isoy,z) Function returns the x co-ordinate based on isometric co-ordinates.
iso_get_regy(isox,isoy,z) Function returns the y co-ordinate based on isometric co-ordinates.
Sweet as, we whizzed through that, now onto the next show!
Depth is a problem that always plagues isometric engines. The depth in this engine works in layers. Let me explain. Everything with the lowest isoy co-ordinate and the lowest layer number will be drawn first. Then the stuff with the same isoy, but a higher layer number will be next. Then once all the layers are drawn, the engine moves onto the next lowest y value. This way, the closer to the bottom of the screen stuff is, the closer it gets to the viewer, make sense? For this to work we need to define the number of layers we wish to use.
iso_set_depth(depthmin,layers) Sets the depth to be used in the functions.
Now depthmin refers to the depth to use for the top layer at the bottom of the drawing field, and layers is the number of layers to use in the room. Now though this depth seems very limited, it is really useful for flying instances or clouds.. i dunno, I haven't eplored many possibilities. Once improvement that I have only considered as I write this is to allow multiple depth grids. So for example, having the tiles all in a depth grid, so that tiles can overlap with the correct depth, but having them all behind another depth grid, which is used for the instances. Note that that is not currently possible with the engine, but I'll get to work on it straight away.
Anyways back to depth. When it comes to the actual calculation there are two possibilities
iso_get_depth(isoy,z,layer) Returns a depth value based on the units position in the room.
This function can be used to get the depth of instance based on its position in the room. HEED THIS WARNING: This will use a HUGE number of depth values, especially for larger rooms, so this should only really be used on things that wont have their depth updated in every step (tiles for instance).
The other function is much more useful in my opinion
iso_get_depth_view(isoy,z,layer) Returns a depth value based on the units drawing position in the view.
(There is a typo on this in the script, it says room instead of view)
This function takes the minimum drawing position to be the bottom of the current view, so only uses depth values that are currently needed (as we don't need to be drawing anything that's outside the view do we )
NO OF COURSE NOT. Sure I have run out of functions to throw at you but I can still be a bother by giving you some handy hints.
TIP 1 - Masks
EVERY object in your game will need a mask for its top-down collisions. Because its not being auto-drawn, it needs to keep a mask at its top down position to have any sort of presence in the room.
TIP 2 - Center of the image
The example doesn't really show this because it doesn't handle collisions but if you want to do collisions, where you place the 'origin' of the sprite is important. This requires some visualisation on your part. If your sprite has a square mask, try to visualise this square in isometric (it will become a diamond) Now chuck this diamond onto your sprite. Even if on your mask the origin is in the middle, chances are you wont want it in the middle for your sprite. THe diamond should be at the foot of your soldier, so the middle of the diamond will actually be towards the bottom of the sprite. I hope I haven't confused anyone with this, just be careful is all I'm trying to say haha.
TIP 3 - Oh, I only had two tips
I hope you guys found this tutorial useful. There'll be more RTS goodness soon, have fun with it!