0
\$\begingroup\$

I would like to change the layer depth of objects, so that the player can go behind them. Right now it looks like this when the player is behind the object:

enter image description here

The problem is that the layer depth doesn't take into account the players location in relation to the object, so it doesn't look correct when the player is in front of the object:

enter image description here

What would be a good way to accomplish this? Could it be done just by comparing the locations of collision boxes (green boxes in the image) when they overlap? Or should I calculate and change the depth for all objects currently on-screen? How could I do that?

Thanks.

[UPDATE]

Here is the draw call from the base class for game objects:

public virtual void Draw(SpriteBatch spriteBatch) {

        if (texture != null && Active == true) {
            spriteBatch.Draw(texture, position, null, Color, 0f, Vector2.Zero, Scale, SpriteEffects.None, LayerDepth);
        }

        DrawCollision(spriteBatch); // DEBUG

}

It's an overload of the built-in MonoGame SpriteBatch.Draw() function. The thing that determines the draw order is LayerDepth. LayerDepth is a property inside each object. Currently it is just set to a fixed value.

\$\endgroup\$
9
  • \$\begingroup\$ Whenever an object moves you can update its layer (Z value?) based on the Y value of its "foot" where it looks like it would intersect the ground. I think that's probably related to the cyan line in your screenshot. \$\endgroup\$
    – Romen
    Jan 26 at 22:29
  • \$\begingroup\$ @Romen What would I compare the Y-value to, though? Can I somehow compare it to the Y-values of other objects on-screen? What would I use as a reference for changing the value? I think the layer depth can be from 0f to 1f. The green box is basically the collision for the texture, and the cyan box is collision for movement. \$\endgroup\$ Jan 26 at 23:29
  • \$\begingroup\$ Make a deterministic formula to set the depth based on the Y value and set the depth of everything based on the Y value. If the top of the world is Y = 0 (world coordinates, not screen) and the bottom is Y = 1000 then your Z could be set to z = y / 1000 to scale it between 0 1 as you go from the top (back) to bottom (front) of the world. \$\endgroup\$
    – Romen
    Jan 29 at 15:08
  • \$\begingroup\$ @Romen Hmm, yeah, I thought about something like that actually. But what if I don't necessarily know the size of the world? Like if the world is procedurally generated, for example? Should it be done in screen coordinates? \$\endgroup\$ Jan 31 at 16:13
  • \$\begingroup\$ Yes you could do it relative to the screen but make sure to handle things that are "off screen" like a tree below the bottom of the view but you can still see the higher branches over everything. \$\endgroup\$
    – Romen
    Jan 31 at 16:34

1 Answer 1

0
\$\begingroup\$

Scale the shifted negated Y value to use as the LayerDepth.

Lower is nearest to screen.

Note: The following equations are not linear and may require adjustments to fit the runtime environment.


Define(all are float values):

  • GroundY as the Y value in the middle of the green line signifying ground. (Per object)

  • MinY the smallest GroundY value, back-most or highest on the screen, GroundY of any non-background object. (Once)

  • MaxY the largest GroundY value, front-most or lowest on the screen, GroundY of any non-UI object.(Once)

  • RangeY = MaxY - MinY + 100 The added 100(adjust this and the 50, 1/2 of 100 below as needed) pixel offset allows room for background parallax layers and UI layers.(Once, either static or in base object)

Set the LayerDepth value of all ground based objects:

LayerDepth = (GroundY - 50) / RangeY; 
// the 50 evenly divides the 100px/RangeY into:
// Foreground(UI) depth:  (0 to 50)/LayerDepth 
// Background depth: (MaxY to MaxY + 50)/LayerDepth

If the GroundY values are discrete, as in several distinct lanes:

Apply rounding to GroundY about (RangeY-100) / (NumberofLanes + 1).

LayerDepth = NumberofLanes * 

Math.Floor(0.48f + (GroundY -50)/ (RangeY-100) / (NumberofLanes + 1));
```
\$\endgroup\$
1
  • \$\begingroup\$ I just use an overload of the built in MonoGame SpriteBatch.Draw() function for draw calls. I added the draw call code as an update to the post. The thing that determines the draw order in the overload is LayerDepth. LayerDepth is a property inside each object. \$\endgroup\$ Feb 28 at 17:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .