Skip to main content
GameDev.net gamedev.net
🔒 Locked

Problems with proper drawing order

Started by its_dxman Mar 12, 2008 at 4:59 PM 8 replies 2.2k views
Original Post
its_dxman
its_dxman
Hi. I'm currently working on a 2D RPG, more specifically, the graphical part of it. Unfortunately, though, I've hit a roadblock when it comes to drawing the map layers and sprites in the proper order. I was hoping that someone with a bit more experience would be able to point me in the right direction. For reference, I intend for the sprites to move pixel-by-pixel, and they will be able to jump... up to higher places and down to lower places if I can manage that part of it. The first drawing method I tried was to draw each layer of a map, then the sprites on that layer from top to bottom, then repeat the process for each successive layer. However, this caused a problem when a map included things like fences. Here is what I mean. The picture on the left is what the scene should look like, and the animation on the right shows where the problem arises: So, to solve this problem, I reworked the process to draw each row of the map one my one, drawing any sprites whose bottom edge falls in that row at the appropriate layer. This seemed to work until I considered the situation of a bridge which sprites could walk across or walk under: Next, I tried giving each tile of the map two parts: one to be drawn under sprites on that tile, and the other to be drawn over it. Again, though, a problem came up: So now, I'm not sure what to try next. It occured to me that just about all these problems would be solved by treating all the trees, fences, handrails, etc, as objects, and drawing the whole thing at once, at the same time as the other sprites on that layer, but that seems like a bit of a kludge to me, though I could be wrong. I also wonder how I would handle something like a very long staircase, spanning multiple layers, which a sprite could walk up, or behind it. Maybe I'm missing something obvious after thinking about things too hard, or maybe there's already a generally-accepted solution to things like this and I'm just reinventing the wheel here. Anyway, I would greatly appreciate any advice. PS: My artistic skills are bad, but they're not as bad as the pictures above. I just slapped those together quickly to illustrate the problem.
O-san
O-san
This is a difficult topic. I don’t know of a generally-accepted solution. In my game I use the z-buffer to sort my objects. That way I don’t have to worry about the drawing order or multiple layered maps. Instead I need to know/learn a 3D graphics API like OpenGL which comes with its own set of problems.
FervInt
FervInt
I solved this by giving each object a fake z value based on how many tiles deep the object would be if it were 3D.

I put all objects into a render list and sorted on zvalue...then drew the list.


The normal z value would be its row position. If the tile were 1 tile deep i would keep the z value and continue. If the tile was 2 tiles deep I would subtract 1 from the z value.

this means that if your bridge there were 3 tiles deep it would have a Z value of y-2 which would draw before anything that was 2 rows above it since it was supposed to have that much depth anyway.

its_dxman
its_dxman
Thanks a lot, guys. You've given me some things to think about. I'm actually doing this with OpenGL in an SDL window. I draw each part of the scene with a vertex array that forms a grid the size of the screen with an extra tile on each side (for scrolling), translate and change the texture coordinates, then draw the next part. I did it out of trying to save memory, but really, I'm only working in 2D, so I could likely get away with just having vertices for each layer instead of doing the translation. I haven't had enough experience with OpenGL to know what would be the smartest way to do it on a memory vs processing time scale.

One thing that occurs to me about treating things like trees as sprites, rather than as part of the map, is that it would make it easy to attach action and event scripts to them, so I could do things like hiding an item inside a hole in the trunk, or I could detect a collision if, say, there were a weapon powerful enough to blow up the tree (tempting, but probably excessive).

The only thing that makes me hesitate is that I wonder if it would unnecessarily clog the sprite list in a place like a forest, even if my system is smart enough to only deal with the sprites that are currently onscreen (which it is).

I'll have to think it over, along with considering the ideas you've given me. If anyone else has any advice, I'd be happy to hear it.
Iftah
Iftah
What I do is place all the sprites that are in screen in a list, then sort the list and then draw them by order.

the order is actually the sprite floor pixel (usually bottom pixel, can be overridden, its virtual). I lately added layers of sprites which was a small change to the order calculation.
something along:
long Sprite::order(){   return  this.layer*10000  // layer ordering is most powerful          + screenCoord.y + image.height  // order is bottom pixel value          - this.floorPixel();  // adjust for image floor pixel}long Sprite::floorPixel() {   return 0;  // usually floor is bottom most pixel}


for some sprites you may want the floor pixel to be somewhat higher in the image, for example for a flying bullet the floor pixel will be several pixels below the bullet.

Btw- for your tree example I would suggest having the tree as one large sprite.


Iftah.

[Edited by - Iftah on March 15, 2008 2:51:33 PM]
its_dxman
its_dxman
Quote:
Original post by Iftah
What I do is place all the sprites that are in screen in a list, then sort the list and then draw them by order.

the order is actually the sprite floor pixel (usually bottom pixel, can be overridden, its virtual). I lately added layers of sprites which was a small change to the order calculation.
something along:
*** Source Snippet Removed ***

for some sprites you may want the floor pixel to be somewhat higher in the image, for example for a flying bullet the floor pixel will be several pixels below the bullet.


Yeah, that's pretty much what I've done in my program as well. For the "floor pixel", I plan to have a shadow on the ground associated with each sprite, and that will be the location which determines the sorting order of the sprites. Like you've said, that would allow for things like bullets, people who are jumping, etc. I haven't added that part yet, though. The problems arose when I started trying to think of more complicated scenes which might cause errors.

Quote:
Original post by Iftah
Btw- for your tree example I would suggest having the tree as one large sprite.


I think that is what I'm going to end up doing. I think I should be able to solve the other problems through smart map designing. Thank you.
LorenzoGatti
LorenzoGatti
Quote:
Original post by Davian_
The only thing that makes me hesitate is that I wonder if it would unnecessarily clog the sprite list in a place like a forest, even if my system is smart enough to only deal with the sprites that are currently onscreen (which it is).


You might want to consolidate static objects (e.g. the trees of the forest) into one big sprite with per-pixel Z values; you could render these blobs along with regular sprites (e.g. squirrels) with very little overdraw.

Note that this approach would be somewhat complex and not necessarily faster than throwing ten times as many fragments at the graphics card.
Omae Wa Mou Shindeiru
jbadams
jbadams
Quote:
Original post by Davian_
One thing that occurs to me about treating things like trees as sprites, rather than as part of the map, is that it would make it easy to attach action and event scripts to them, so I could do things like hiding an item inside a hole in the trunk, or I could detect a collision if, say, there were a weapon powerful enough to blow up the tree (tempting, but probably excessive).
You don't have to treat them exactly the same to have them both in the same drawing list; you can interleave the images that need to be drawn with those from your sprites in a drawing list but not attach all those other properties if you don't want to.
- Jason Astle-Adams
Badgerigar
Badgerigar
It's always worth considering using OpenGL, even if you still use sprite graphics.
its_dxman
its_dxman
Thanks a lot, everyone. I think I've finally devised a solution.

Part of my original problem was that I was having trouble getting OpenGL's depth buffer to work the way I wanted it to, while still allowing for alpha transparency. Well, last night, I discovered alpha testing, and that solved all my problems. Now I just have to make sure everything has the correct z-coordinates, and OpenGL will take care of the rest.

Each tile layer's z-coordinate will correspond to the layer number (1.0, 2.0, etc), then each sprite's z-coordinate will be the layer number, plus its bottom y-coordinate divided by 1000 (A sprite on layer 2, at (250, 250) on the screen would have a z-coordinate of 2.250).

I've still got a little bit of that rush that comes from getting something to work, so I haven't yet thought hard enough about it to encounter any problems that can't be fixed by smart map design.

So, I just wanted to pop back in and thank everyone.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.