3
\$\begingroup\$

I'm making a topdown 2d game, and I've made a decent entity system so far. But I want to do the following with it: I want to have drawing depth, so if, for instance, a tree is above another tree, then it should be drawn underneath the other tree. Here is basically a picture of what I mean.

This is what I'm trying to avoid:

This is what I have RN, but it's bad

Instead of that I want something like this:

This is what I'm trying to achieve automatically in rendering

If you have any idea how to do this, please tell me. If you need any code, here's basically what I do: In my main class I call a generate entities class. In that then I add Tree class-es to an arraylist through which it renders them. Thanks.

\$\endgroup\$
1
  • \$\begingroup\$ For these kinds of top-down games you can often just draw things from top to bottom, left to right, and get the right kind of overlap without necessarily bothering with a z-order. \$\endgroup\$
    – user77245
    Commented Jan 8, 2018 at 22:32

3 Answers 3

1
\$\begingroup\$

I like the other answers but I think they are too verbal. What you can do is simple:

  • Make an array that holds all the objects that are meant to be drawn depending on their Y. Add any object that can either walk in front of other object, or that it can hide objects behind it. For example, don't add the ground as it always drawing below them, but add the trees, probably a house (assuming you can walk behind it) and characters.

  • Sort the array based on the Y of those objects, from lower to higher. Now when you draw these objects, draw them from 0 to array.length, objects with low value will be drawn first, then objects with higher value will be drawn on top of them.

Sorting can be resource-intensive if you are sorting the whole array every frame, especially with having more and more objects in it. Considering that the array is initially sorted based on the Y value, every time an object's Y coordinates change, move them up/down the array based on its neighbours, no need to sort the rest of the array.

\$\endgroup\$
0
\$\begingroup\$

It's quite simple, you're already sort of doing it with your terrain, right? You draw your terrain first and then you draw your entities. Whatever is drawn first will be drawn further back in the depth. What you can do for your drawable entities is give them a depth sorting index. Then when you tell them to draw you sort them into collections based on their depth and actually draw them from lowest depth to highest depth.

If entities draw immediately when you tell them to you may need to reorganize that. What I do in my engine is I have a Rendering Manager class. When I want to draw something I pass what I want to draw to my Rendering Manager which sorts them into different collections based on their properties and then draws them in the right order with the right properties. The Rendering Manager is the class that actually executes the draw logic; when Entities "Draw" they just alert the Rendering Manager that they want to be drawn.

I don't know how in-depth you've gotten with Slick and frankly I'm not really familiar with the API but it appears to mostly expose OpenGL. If you represent your entities with a world matrix you can simplify this process quite a bit. You're working in 2D but OpenGL always has a concept of all 3 dimensions. The Z axis can act as a depth ordering axis of sorts. The further back something is positioned on the Z axis from your camera, the further back in the scene it will be drawn. If you do this you don't have to worry about the order of your draw calls at all but rather objects should naturally be drawn behind other objects if they're positioned further away on the Z axis. If you're not directly doing any OpenGL calls this won't really be possible unless Slick2D gives you a way to represent position on the Z axis.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ To add to this: assuming you can position on the Z axis, and that you're rendering orthographically, a common way to achieve this sort of effect is to make Z position inversely dependent upon Y position. I.e. the farther up the screen something is, the farther back it is. \$\endgroup\$ Commented Nov 20, 2015 at 22:34
0
\$\begingroup\$

If you need dedicated layering of graphical entities and you already have a kind of an entity system, you can introduce the layering easily within the rendering.

I think you have already something like a "Transform" component for an entity that has the x/y axis position of the entity and also some other orientation information stored. just add a layer information there. This can be a simple number from 0 to 100 for example and defines the the layer on witch this entity has to paint to.

Then on the renderer or renderer system you can sort the entities within the layer and paint them in the right layering order. Or if you have a proper event system, you can simply fire render-events for every layer within layer order and the renderer system that receives this events paints the entities for that layer.

But this doesn't solve your problem right? because all the trees are probably on the same layer but the tree in the back should be rendered first, before the tree in the front. So what kind of perspective do you really have in your game? It seems like a tile map where the things painted in the upper rows are behind the things painted in the following rows.

Instead (or additional to) the layer information you can have a grid position information for sorting the entities on rendering to get the right order. Or maybe in your case it would be enough to just sort the entities to paint within the y-axis position. The important thing for you is to think about the perspective your game should have or has and with what kind of sorting you can get the expected result on rendering.

\$\endgroup\$

You must log in to answer this question.

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