ID:1475165
 
(See the best response by Ter13.)
I have a problem with my project. It's a 3/4 top-down view, a la Chrono Trigger. However, in order to get rendering on the trees right (due to some transparency tricks), I need to use SIDE_MAP.

The problem, then, is that rendering on SIDE_MAP messes up my sprite (i.e /mob) rendering. If I could render all my objects as SIDE_MAP, but leave mobs rendered as TOPDOWN_MAP (i.e. slip the /mob images between the layers of the trees/their overlays), this would actually completely solve my problem.

Is there any way to do this, or approximate something similar to it?

TOPDOWN_LAYER would probably help with this.

Of course, my standing layer system has been a pretty good alternative to the messy SIDE_MAP format.
We're using TOPDOWN_LAYER right now, and this is what it looks like: Overlay Pasta. You can see the "correct" layering above the player, however.

Switching to SIDE_MAP "fixed" our tree ordering, but it broke the reason for using it in the first place; the trees wholly show up over top of the player, including the opaque part that usually doesn't.

Comparisons:
SIDE_MAP
SIDE_MAP if you walk behind the trees (Oh no, where's the player!?)
#define TILE_HEIGHT 32
#define TILE_WIDTH 32

#define MAX_PIXEL_Y (TILE_HEIGHT * world.maxy)

atom
var
standing = 0
tmp
base_layer = 0
New()
. = ..()
if(standing)
base_layer = src.layer
src.layer = base_layer - ((src.y - 1) * TILE_HEIGHT) / MAX_PIXEL_Y
movable
Move(atom/NewLoc,Dir=0,step_x=0,step_y=0)
//store old location data
var/atom/OldLoc = src.loc
var/odir = src.dir
var/osx = src.step_x
var/osy = src.step_y
//call default action
. = ..(NewLoc,Dir,step_x,step_y)
if(.)
//if move was successful, call Moved() hook.
src.Moved(OldLoc,odir,osx,osy)
proc
Moved(atom/OldLoc,Dir=0,osx=0,osy=0)
//adjust the layer via FIDGET method.
if(standing)
src.layer = base_layer - ((src.y - 1) * TILE_HEIGHT + src.step_y) / MAX_PIXEL_Y
New()
. = ..()
//this is a standing mob, and will need to be managed by FIDGET layering.
if(standing)
src.layer = base_layer - ((src.y - 1) * TILE_HEIGHT + src.step_y) / MAX_PIXEL_Y


This approach is almost identical to KaioChao's standing layer system.

It pretty much completely fixes the problems with layering in SIDE_MAP. Make sure you are using TOPDOWN_MAP format, though.

Also, you will want to use FLOAT_LAYER for overlays with my approach, because if you wind up using explicit layering, you will run into some serious problems with the FIDGET approach to layer modification.
Unfortunately Ter13, that doesn't solve my problem. In TOPDOWN_MAP, the overlays on top of the trees interfere with each other, but layering between the trees, their overlays, and the player is correct.

In SIDE_MAP, the trees all layer nicely without any problem, -but- the player is either in front of them (in which case the shadows still work properly), or they're behind the tree, in which case the player is drawn entirely behind the tree, including the fully-opaque back image.

What I need is a way to arrange the trees and their overlays according to the existing SIDE_MAP implementation, but then draw the player above the base images and below the overlays, regardless of where the player actually is. I haven't been able to do that, and the TOPDOWN_LAYER doesn't help since that just puts the player on top of everything.
As for solving the tree issue, my advice would be to adjust the trees like so:

obj
tree
var/tmp
overlapping = 0
obj/trunk
density = 0
bound_x = 0
bound_y = 16
bound_width = 96
bound_height = 80
New()
. = ..()
var/turf/t = locate(src.x+1,src.y,src.z)
var/obj/o = new/obj{density=1;bound_width=32;bound_height=32;}()
o.loc = t
o.step_x = src.step_x
o.step_y = src.step_y
trunk = o
Del()
del trunk
. = ..()
Crossed(atom/movable/o)
if(istype(o,/mob))
overlapping++
if(overlapping==1)
src.alpha = 192
Uncrossed(atom/movable/o)
if(istype(o,/mob))
src.overlapping--
if(overlapping==0)
src.alpha = 255


Basically, what this does is use the tree's bounding box to determine if an object is stepping under the tree, and uses a separate bounding box to act as the dense part of the tree.

When a mob steps under the tree, the tree will become transparent. When there are no mobs under the tree, the tree will revert back to solid.

The bounding box is set up arbitrarily. Configure it to your needs.
In response to Topkasa
Topkasa wrote:
Unfortunately Ter13, that doesn't solve my problem. In TOPDOWN_MAP, the overlays on top of the trees interfere with each other, but layering between the trees, their overlays, and the player is correct.

It does solve your problem. Take a look at it again.

I use this exact system to acheive tall-object layering based on the Y coordinates of the object, which is pretty much how SIDE_MAP works.
Except that object-ordering isn't the problem; specifically the problem relates to ordering so that the Tree base (which is fully opaque) is always under the player regardless of their relative positions, but always above trees -and their overlays- that are "behind" it. SIDE_MAP already does this perfectly.

The problem I was trying to solve (and which I have indeed switched to making trees fade in/out as needed for) was keeping the player always above the "base layer" of each tree, and always below it's overlays (i.e. rendering as TOPDOWN_MAP), while the trees were as the same time ordering themselves, relative to each other, according to SIDE_MAP.
Except that object-ordering isn't the problem; specifically the problem relates to ordering so that the Tree base (which is fully opaque) is always under the player regardless of their relative positions, but always above trees -and their overlays- that are "behind" it. SIDE_MAP already does this perfectly.

Which is, yet again, what my system does, perfectly.

This recording is taken from a game running in TOPDOWN_MAP format with my layering system on it.



This is how they are constructed.



If the player is south of the pillars, he will always appear over them. If the player is north of the pillars, he will always appear under them. Plus, objects sharing the standing tag will adjust their layers based on their position so that they correctly overlay each other based on their y position in the world.

You are making this way more difficult than it needs to be. What you are asking for is basically two different layering systems that will automatically know how to layer things over the player, regardless of the layering rules.

That just isn't possible without a proper depth buffer. You need to use a single rule, and you need to ditch your original concept. There's literally no way to make work what you are trying to work. This approach does perform admirably, given the two snippets I've passed on.

The system will work as a perfect substitute to SIDE_MAP, plus allow exactly what you are asking for.

I can't help but think you are discarding the solution off-hand without even knowing what it actually does.
Since so many people have been using my old standing layer system, I went ahead and turned it into a library. I haven't had any complaints about it, although it's been mentioned throughout the forums several times in the past year, haha.

This library depends on my map info library and another one that deals with absolute pixel positions. They've all been sitting around for years in my Dropbox, so I made hubs for them, which also makes it easier for me to include them.
I'm really not.

The trees are made up of two halves:

*The "Back part" that is ALWAYS under the player, and fully opaque.

*The "Front part" that is ALWAYS above the player, and is partially transparent. This includes a semitransparent part of the foliage, and the shadow that is cast.

In TOPDOWN_MAP, the overlays conflict with each other; in the first image I linked you can see how the overlays are visible through each other, and the player is also visible "through" the tree.

In the two SIDE_MAP images (a, b), the trees no longer exhibit the graphical conflicts of TOPDOWN_MAP, but as you can see the player character appears wholly behind the tree -including the "Back part"- when "behind" it.

Your system works great for fully-opaque objects, but not the two-part objects I'm using. Simply adjusting Z-layers as your library does won't work for my situation, hence why I'm rejecting it. Trees with a lower Y value need to have their "back part" render over the "Front part" of trees with a higher Y value (i.e. further back). The player needs to render over every "Back part " regardless of his Y position. The player needs to render under every "Front part" regardless of his Y position.

It's not a case of over/under rendering, it's a rock-paper-scissors case. A needs to render over B needs to render over C needs to render over A.
And for the record, I figured BYOND can't "natively" do this - but I assumed I could have missed something, hence why the question asked "Is there any way to do this, or approximate(ly) something similar to it?"
In response to Topkasa
Best response
Topkasa wrote:
And for the record, I figured BYOND can't "natively" do this - but I assumed I could have missed something, hence why the question asked "Is there any way to do this, or approximate(ly) something similar to it?"

What does that even mean?

With finality. Absolutely, NO.

The way you want to do it simply is not possible without client-side rendering, or per-instance fiddling. The closest approximation to what can be done has been provided above.
It means I consider myself fallible, and I definitely do not know everything about BYOND.

And thank you, that was the answer I was looking for.