AuthorTopic: Need help with draw order sorting tiles for top down action rpg  (Read 2080 times)

Offline startselect

  • 0001
  • *
  • Posts: 81
  • Karma: +0/-0
    • startselect__
    • View Profile
I'm making a top down action rpg with a tiled terrain. This isn't exactly a pixelart question but since so many here seem to be creating similar things my hope is that someone will have already figured this out (or figured out that it is impossible).



The game generates a terrain from a height map and it can create terrain such as the first image. It also generates colliders for different height levels that the player will collide with. The yellow lines show the colliders for the player when standing on the ground level and the red lines show the colliders when standing on top of the terrain, shown in the second image. The blue diamond is the players own collider.

One thing to note is that the top corners are actually two tiles on top of each other with the ground grass tile drawn behind and the cliff corner drawn on top.

What I would like is for the player sprite to be able to stand in front of the terrain and be drawn on top, stand to the side of the terrain and be drawn below, stand behind and be drawn below and finally also be able to stand on top of the terrain and then be drawn on top, as shown in the second image.

Another important thing to note is that the player sprite can have pixels both to the left and right of the player collider, when walking the most extended leg pose is the most extreme but when have equipment in hand it becomes even further extended outside the collider. Also the player is about 2,5 tiles tall, but I would like to find a solution that allows much taller sprites to walk around the terrain.

If I sort the terrain according to its height as shown in the third image the player can stand on top, to the left and behind the terrain and be drawn correctly but its head gets drawn below the tiles with height 1 when standing infront.

To fix this I added y-value to the sorting order, shown in the fourth image, combined with height, shown in the fifth image, this fixed the problem of standing in front of the terrain. But sadly it added the issue shown in the sixth image when standing on the side of terrain, parts of the sprite gets drawn over terrain tiles higher up on the y-axis.

The player gets drawn after all tiles with the same sorting order as the one the player is standing on has been drawn but before any with higher sorting order is drawn.

Is there any way of sorting the tiles draw order to fix all the cases or is this just impossible? I've been trying to figure this out for 3 days non stop now and I just can't crack it (also starting to get a bit insane :crazy:). But I feel a bit like the fact that the sprites extend outside the collision bounds messes it all up, but that's sort of a must for me to have spears and what not as equipment.

Any and all help is very much appreciated!

Offline 0xDB

  • 0011
  • **
  • Posts: 873
  • Karma: +0/-0
  • Dennis inter-is.
    • dennisbusch_de
    • http://pixeljoint.com/p/1287.htm
    • 0xdb
    • View Profile
    • 0xDB
Maybe do what you originally started out with (third image) but not just treat the terrain as having different height levels but also split the sprite blits into sections of different heights.

draw terrain at level 0
draw sprite part which is at level 0
draw terrain at level 1
draw sprite part which is at level 1
...

You can calculate the section of the sprite to blit on each layer by determining which layer it is resting on (start from its own bottom). Blit only a section as high as a single tile and on the next layer blit the section above that previous section after drawing the terrain for that next layer.

You will still run into sorting problems for elements like arms and weapons however unless you build a sophisticated sprite editor where you can define metadata. Split your sprites into individual body parts and for each frame define a drawing order of the parts and also define at which logical height each part starts, so that you can split each part itself into different blits accordingly (and even with that you'll run into special cases where it would not work, so you still need to craft your graphics and maps carefully to avoid positions that look off).

Another completely different thing to consider is switching to a 3D-API and generating real geometry for the terrain. Sprites could be textured quads. With an orthographic projection and without anti-aliasing, you can setup the camera to be pixel perfect. That would hand off all the sorting issues to the 3D system.

Offline Ai

  • 0100
  • ***
  • Posts: 1057
  • Karma: +2/-0
  • finti
    • http://pixeljoint.com/pixels/profile.asp?id=1996
    • finticemo
    • View Profile
Drawing sprites as a bunch of tiles probably will do the right thing here.
For example, your diagram 6, the sprite has ..8 tiles making it up. I'll describe the drawing order:

tile "1a"
top of head
tile "2a"
main head and upper shoulders
tile "<3a" (the one to the left of the tile torso is shown in)
upper ankle/heel
tile "3a"
torso
hand+toe tile (before raised tile "4", because same y, lower height)
raised tile "4"
tile "<4a"
lower heel
tile "4a"
main feet
lower toe (before raised tile 5, because same y, lower height)
raised tile "5"

The 'a' in '4a' indicates a tile in the same column as char that has (or can be inferred to have) the specified number.


However, it is usually also possible to use the drawing engine to clip the sprite however you want -- in your case 6 and a hypothetical case 7 in which the character is sandwiched between higher-level elements,  you should be able to check if there are any raised/higher level tiles that the sprite would interact with, and clip that area out of the sprite. This is slightly less powerful, as transparent areas in the 'top' wouldn't show through any parts of the sprite falling into that tile.
If you insist on being pessimistic about your own abilities, consider also being pessimistic about the accuracy of that pessimistic judgement.

Offline aeveis

  • 0001
  • *
  • Posts: 11
  • Karma: +0/-0
    • aeveis
    • http://pixeljoint.com/p/36754.htm
    • aeveis
    • aeveis
    • View Profile
    • aeveis.tumblr.com
It looks like you have it mostly solved, if it's just those side tiles, why not split up those like you did with the top corner tiles, and have the top layer set as the max possible height (you have to detect how long the platform is though).