GameMaker Ways to achieve z-depth in 3/4 perspective, with tiles

matharoo

manualman
GameMaker Dev.
Our game is a 3/4 perspective one, with z-axis support. So you can jump around, get on elevated platforms, and all that. It's working, except for the depth system.

For the platforms, we have tiles, and each tile layer has its own z position.

Here's an example of what we need:
upload_2019-10-8_23-55-36.png

The hill and the bridge are all tiles.
Avoid the man behind the hill, we can cut that and just have them go around.
But we need the objects to properly show above the tiles when they're above the layer's z position, and vice versa.

Currently I'm using a simple data structure method to draw all instances, where they're sorted using a grid and then drawn in a single loop. I'm confused as to how I can implement a third axis in that system and make it work.

Any ideas are appreciated!
 

Yal

🐧 *penguin noises*
GMC Elder
Here's an idea.

The y position you draw things at in the end should be y + z (where z is negative upwards). So the vertical movement is separate from the XY movement. To get easier calculations, you want the "z origin" to be at the bottom of everything (and it helps if the sprites' y origin is at the bottom as well). Depth sort things using only their Y position (since that's the measurement of how close/far they are from the screen). You want everything to be depth sorted into the same list (both tiles and instances), so you might need to sort some "source-agnostic" data (having objects add their sprites to the list when they are created and remove them when they're destroyed, updating the positions each step).
 

matharoo

manualman
GameMaker Dev.
The y position you draw things at in the end should be y + z (where z is negative upwards). So the vertical movement is separate from the XY movement. To get easier calculations, you want the "z origin" to be at the bottom of everything (and it helps if the sprites' y origin is at the bottom as well). Depth sort things using only their Y position
Actually, I'm already using that system, but was having trouble implementing tile layers into it.

You want everything to be depth sorted into the same listt (both tiles and instances)
For that to work, wouldn't each hill (or each group of tiles) have to be in separate layers? Because that wouldn't work if I had, say, 3 different hills in the same layer that required different depths.
But now that I think of it, that doesn't make sense. Of course they need to be in separate layers!

So, I'll try that out, and report back. Thanks!
 
I just added bridges to my game... I'm just using depth = -(y +depthMod);

At the bottom of every staircase, I have a trigger that lowers depthMod by like a thousand. Another trigger at the top raises it by a thousand.

Cheap and probably dumb, but it's working okay so far, hahah!
 

SoVes

Member
The easy way to get tiles working is using z tilting. There's a blof post about it somewhere and it does wonders.
 

SoVes

Member
Z-Tilting does not work for us, too limiting.
Oh yeah, it's a high rez game. I got around the alpha limitations, but I think you can also get around the height limit. It would require an extra variable for each object though. Which can be annoying, but with parent objects it might not be as bad
 

Yal

🐧 *penguin noises*
GMC Elder
Oh yeah, it's a high rez game. I got around the alpha limitations, but I think you can also get around the height limit. It would require an extra variable for each object though. Which can be annoying, but with parent objects it might not be as bad
You're talking about maybe using parenting? Feels like a completely different world to me, lol :p I'm basically writing "event_inherited()" at the start of every event I crate... I guess it's second nature to me at this point, it's one of those things that are perfect if you love breaking everything down in hierarchical relationships to organize them. I spent a huge chunk of yesterday making this graph of how all the concepts of an app I'm responsible for at my day job relating to each other...
upload_2019-10-9_23-19-19.png
(blurred out for confidentiality reasons)

Parenting doesn't solve EVERYTHING, but it if you parent things early, you automatically get a well-organized project. Don't underestimate it or forget about it.
 

matharoo

manualman
GameMaker Dev.
Yep, parenting is very important. All of the objects in my game that need to be drawn with a depth are under a parent called "oDepthParent".
 

matharoo

manualman
GameMaker Dev.
Here's an idea.

The y position you draw things at in the end should be y + z (where z is negative upwards). So the vertical movement is separate from the XY movement. To get easier calculations, you want the "z origin" to be at the bottom of everything (and it helps if the sprites' y origin is at the bottom as well). Depth sort things using only their Y position (since that's the measurement of how close/far they are from the screen). You want everything to be depth sorted into the same list (both tiles and instances), so you might need to sort some "source-agnostic" data (having objects add their sprites to the list when they are created and remove them when they're destroyed, updating the positions each step).
So, the issue I'm facing now is about depth-sorting platform tile layers. For example, let's say I have this hill in one tile layer:

upload_2019-10-10_17-25-24.png

If I depth sort that into the same list as everything else, it will be sorted based on its y origin. So if a player is standing on top of it, it won't appear on top if its y < tile_layer_y.
So how can I implement a broad platform tile layer into the depth system?
 

Yal

🐧 *penguin noises*
GMC Elder
The depth-sort-based-on-y system works better the more flat (i.e., lesser size along the y axis) the things you sort have, since that makes the approximation that things are either in front of or behind every other thing less wrong. To implement a platform this way, you'd technically need to make it out of hundreds of individual, 1 pixel wide layers, but that would be a nightmare in terms of resource usage (especially for the depth sorting loop). But maybe it could work if you split it up into several parts, each taking up a Y thickness of some certain size? Parts don't need to end abruptly, they could have smooth overlapping edges... this helps masking depth sort issues a bit, and might help with resource reusage as well (e.g. you can combine parts in new ways to make new types of hills with the same graphical assets).


Some other ideas...

Rather than sorting by coordinate alone, you could define a "which thing would APPEAR to be the frontmost?" function that takes into account an object's shape and z coordinate. For your rounded hill example, the player would appear to be behind it when its bottom is inside a certain region in 3D space (let's call this the "shadow" of the hill), and in every other position, would appear to be in front of it, or it would make no difference (when they don't overlap). Since we want a total order to sort EVERYTHING with, we could rule that for y coordinates starting at the very start of the shadow, and anything further y-upwards, the object is behind the other object.

This becomes extra interesting if we draw this representation:
upload_2019-10-10_20-46-2.png

Note that the thing sticks up along the Z-axis. The depth sorting confusion fails because we're trying to simplify a 3D problem into a 2D problem, losing us out on information.

Now, what does this mean? I'm not sure. We might need to take both y and z into account when depth sorting, making the player sort first when it overlaps the hill y-wise and is above it z-wise, even when the hill would win due to lower y coordinate. Not sure how messy handling walking into the shadow of the object from being atop it would be, but it feels like this solution makes intuitive sense. You just need another variable representing the size of the hill at the ground level, and you probably already can handle this via the collision mask's data.


EDIT: Someone posted this thing in a different topic on the same subject, could be interesting.
 
Last edited:

NightFrost

Member
To implement a platform this way, you'd technically need to make it out of hundreds of individual, 1 pixel wide layers, but that would be a nightmare in terms of resource usage (especially for the depth sorting loop).
I recall this system works just like that, and claims to be very fast. It generates a bunch of layers and has the instances jump between them. However I lack the time now sit through the 30 min video to check the details.
 
Top