GMS 2 Depth

When you draw somthing then draw something else, the last 'draw' code will cause that to be on top. Is there any way to tell the draw functions which layer I intend for it to be drawn regardless of its chronological position as it were?
 

Psycho_666

Member
depth=-y
As simple as that.
If the object moves - in the step event.
If the object doesn't move - put it in the create event...
Depth is a built-in variable, so you can easily use it. The draw event automatically draws the objects with the highest depth first and the ones with lowest depth last. So depth -1 will be drawn before depth -50...
 
I have problems with exactly this. I made my character have a depth of -y, and it disappeared behind the background! So for debugging I went into the room settings and made the background invisible. And the character reappeared but acted very strangely. Whenever it moved, it 'painted' itself across the screen - that is, its image every step remained there creating a blur across the screen.

Very confused! Why does simple depth need to be so buggy? I've not used any draw events anywhere, so it's not that.
 

Psycho_666

Member
Show me your draw code...
There could be a lot of things wrong...
Wait, your character 8s depth -y
Are the rest of the objects depth -y?
Is the background depth -10000?
 

Yal

🐧 *penguin noises*
GMC Elder
When you draw somthing then draw something else, the last 'draw' code will cause that to be on top. Is there any way to tell the draw functions which layer I intend for it to be drawn regardless of its chronological position as it were?
Drawn things are drawn at the depth of the object that has the draw event. If you want something to be drawn further up, you need to draw it later (i.e., from an object with lower depth). The only thing the depth order influences actually is in which order draw events are run (they're using the Painter's Algorithm) so there's no way to change depth mid-drawing.

This has a cool effect, though: using with(object){draw_something()} in a control object that's on top of everything else's code will make those things also be drawn on top. This is useful for things like silhouettes of characters behind walls.
 
What Yal said... BUT if your just trying to change the order of the draws within the drawing object and not move them to different depths outside the drawing object then you could do that. You just need to make sure you draw things in the correct order. You could go about doing that many ways, but possibly the easiest, depending on what your doing, could be to push your draws into an array or data structure and then in your draw loop over that data and organize your draws that way. It would be a pain, but if you need to do it that would be one way.

If you need to change depths OUTSIDE of the drawing object then there are also solutions, but a bit more complicated. Since you cant set drawing to a depth outside the drawing object you instead need to create new objects at the depth you want things drawn. So, when you would normally say DRAW_WHATEVER(X,Y) or whatever your using to draw, you would instead say something like with(instance_create(draw_object,x,y)){ depth = 123; DRAW_WHATEVER(X,Y) } Then you would want to build a little controller to handle the new draw object that you are using to disperse these draw events. But, this will be kind of messy if your talking about making a lot of draws at different depths. You would essentially need an object at every depth you want to draw on.

Just as an aside, and probably nothing at all like what your doing, but for my game (top down zelda style) I have 4 master draw depths that I draw effects to. Below the floor, below the player, the player, and above the player. Those four depths allow me to put things pretty much anywhere I need with some limitations. So, my point though is that perhaps you only need a handful of actual depths to draw to. If you need some large number or some random number then you should probably make system like I mentioned above to place objects at the depth you want and then draw from those.
 
Thanks, thats the question I was asking not about the objects. So draw them in order. that's sort of what I was expecting. Thanks
 

TheouAegis

Member
Also, don't forget about Draw Begin and Draw End. Of course, these two events aren't always viable, but sometimes they are very handy.

If one object is doing all the drawing (say, to a surface), then you can put the stuff you always want on the bottom in the Draw Begin event. Then you can use the Draw event for stuff you might want drawn next. Sure, you could do it all in the same Draw event, but using Draw Begin might keep things more organized for you. To each their own.

However, if multiple objects are going to be drawing things, Draw Begin would let you draw certain things before anyone else gets to draw anything. Then everyone would run their Draw events, systematically drawing over what was rendered in the Draw Begin. Then if you had the Draw End event, it would draw everything in that event on top of everything else. (And then the GUI supercedes all of them, but that's on its own surface so it's unimportant.)

So if order mattered for, say, the background and the foreground but not everything else in between, the Draw Begin and Draw End events would be ideal.
 
That's true. I have been using GMS for a while and could never really see the point in those from a functional perspective but for the organisation, I guess it makes sense.
 

TheouAegis

Member
Functionally, they are very useful. ...Maybe not as useful as Begin Step and End Step, but still pretty useful. I think they may have become a bit obsolete once GMS2 introduced layers, but it's still very handy to have a separate event for drawing certain things before the main draw routine is executed, or drawing things after the main draw routine is executed but still on the primary surface/canvas instead of the GUI.

And now Predraw and Postdraw are some of my favorite events, even though I have so far found only one use for them. Maybe they're even more useful in HTML5, I dunno.
 
Show me your draw code...
There could be a lot of things wrong...
Wait, your character 8s depth -y
Are the rest of the objects depth -y?
Is the background depth -10000?
All my draw events are empty. I'm setting the depth in the creation event and in the step end event (in fact the manual says I can't set the depth in the draw event anyway).

The background depth is 100. Also, even if we could explain why something with a negative depth is disappearing behind a background with a depth of 100, it still wouldn't explain the smudge-paint effect when the background is not visible.

The rest of the objects are a bit different but suffice to say they are being drawn in the correct order.

The thing that frustrates me is that I'm not trying to do anything complicated. I've got no draw event code, I've not fiddled with room settings. I just made an instance have a depth of -y, and it's doing crazy ****. This is basic functionality, it should just work.
 
Depth = -y definitely works, it's working for me and not having any issues. You should add some debug code to see what is wrong. Either turn on debug mode and inspect the depth of the object your having issues with or make the objects draw their depths to the screen so you can see what's going on.
 

TheouAegis

Member
The smudge paint effect is because you probably have automatic window clearing disabled, so the draw buffer stays intact. When the background is enabled, the background gets drawn over the drawing buffer and hides that smudging.

Does the player disappear at all y coordinates, or just some? What is his y coordinate when he disappears? Verify your y-coordinate isn't actually negative at that point. (only saying this because depth=-y worked just fine for me)
 
Thanks for your time on this.

It's fixed. I messed around, tried 1000 - y, then went back to -y and now it works. No idea what happened - some typo somewhere, who knows, but now it's working.
And I learnt something about the draw buffer too, so thanks for that!
 
Put this in any object's step event that needs depth:
Make sure by the way the layer depths of your layers are spaced far enough apart from each other. I have each layer separated by 100 000, more than enough.

depth = layer_get_depth("Layer_Instance_Player") - (((y-depthspecific)*room_width) + x);

"Layer_Instance_Player" depends on what layer you want the object to function on.

depthspecific is a number you need to find yourself: it's an offset number depending on the sprite of the object. Say an object has a sprite of 16x32 pixels. The bottom sprite pixels, starting from the top pixels of that sprite, is +31. You'd want to flll that in as depthspecific, although depending on the sprite you might want to play around a bit with that number. Start at 0 and see what happens.

Basically, this converts the object's x and y coordinate into a new number that contains both values. The depthsorting happens with that new number.

This sorts objects top to bottom and left to right. If an object needs to be static and non-moveable, place that single line of code in the create event.
If the object needs to be dynamic, like a player object, put that line of code in the step event, so the depth is continuously updated.
 

Yal

🐧 *penguin noises*
GMC Elder
Functionally, they are very useful. ...Maybe not as useful as Begin Step and End Step, but still pretty useful. I think they may have become a bit obsolete once GMS2 introduced layers, but it's still very handy to have a separate event for drawing certain things before the main draw routine is executed, or drawing things after the main draw routine is executed but still on the primary surface/canvas instead of the GUI.

And now Predraw and Postdraw are some of my favorite events, even though I have so far found only one use for them. Maybe they're even more useful in HTML5, I dunno.
One of the primary simple use cases for Begin Draw is drawing shadows behind everything else, but there's some other slightly more advanced use-cases that fits it like a glove... one of the big ones is using multiple shaders to affect all drawing with minimal texture batch breaking (and faster than using a with loop to iterate over everything that should be drawn with the effect). Set the shader in a high-depth object's draw begin event, draw shaded things in the draw begin event of affected objects, unset it in the same high-depth object's draw event, then do normal drawing. Or the other way around if you want the shaded effects second. And so on.

Predraw and postdraw are mostly meant for processing effects that affects the entire screen at once, things like bloom (make bright areas bleed out into their surroundings). Since post-draw is triggered before the GUI layer, GUI drawing won't be affected by things you do here (again, bloom is a perfect use-case example for this).
 

TheouAegis

Member
One of the primary simple use cases for Begin Draw is drawing shadows behind everything else, but there's some other slightly more advanced use-cases that fits it like a glove... one of the big ones is using multiple shaders to affect all drawing with minimal texture batch breaking (and faster than using a with loop to iterate over everything that should be drawn with the effect). Set the shader in a high-depth object's draw begin event, draw shaded things in the draw begin event of affected objects, unset it in the same high-depth object's draw event, then do normal drawing. Or the other way around if you want the shaded effects second. And so on.

Predraw and postdraw are mostly meant for processing effects that affects the entire screen at once, things like bloom (make bright areas bleed out into their surroundings). Since post-draw is triggered before the GUI layer, GUI drawing won't be affected by things you do here (again, bloom is a perfect use-case example for this).
Do pre-Draw and Post-Draw work in the room? Are you talking about with the application surface disabled? Because when I had the application surface on, pre-draw and post-draw effects were only visible in the game wi dow behi d the application_surface. Like, I had a sprite move across the screen and drawn in Predraw and Postdraw, but once it reached the application_surface it disappeared until it got to the other side. I believe you, just curious how it was set up.
 

Yal

🐧 *penguin noises*
GMC Elder
When I talk about bloom, I mean that you'd do something with the application surface (or draw another surface altogether) as-is. You don't work with objects or primitives at that point, you work with the surface that all the other drawing has happened to. (You don't NEED to only work with the application surface, of course, but it's supposed to be the main thing for that event, since it happens when the surface is guaranteed to be "done" from the normal drawing's point of view)
 
Top