ID:2902600
 
BYOND Version:515.1620
Operating System:Windows 11 Home
Web Browser:Chrome 119.0.0.0
Applies to:Dream Maker
Status: Open

Issue hasn't been assigned a status value.
Descriptive Problem Summary:
So what I've found is that bound_x/y plays into calculation for SIDE_MAP's drawing order in rather unexpecting ways.

So it seems that the render assumes that all of the sprites must have the same starting points. So if one the atoms has a greater bound_x/y, that atom's "starting point" is considered to be further ahead. For example:

atomA has a bound_y of 24.
atomB has a bound_y of 6.

As a result, the calculation for whether atomA will be drawn first or second is offset by an additional 18 pixels (in terms of position). This is clearly not intended behavior.

My explanation may have sucked. HMU on discord if you have any questions.


Numbered Steps to Reproduce Problem:
* Walk over to the Squirrel in-game. You'll see that you'll need to be at least 19 pixels north of the Squirrel to have your character drawn behind it.

You can see this by simply examining the overlays representing your bounds.

* Once done, use the "Equalize Bounds" verb, this will set your bound_x/y to the same values as the squirrel. At this point, you'll see that the overlay that represents your bounds are readjusted. This time, your position will only need to be 1 pixel north of the squirrel for you to be drawn behind it.

You can use "Initial Bounds" verb to go back to your normal bound_x/y to see if it continues. You can also use Change Density verb to test collision while Dense.

Code Snippet (if applicable) to Reproduce Problem:
https://cdn.discordapp.com/attachments/725458598213451879/ 1181607259814498345/SIDEMAPTEST.zip?ex=6581ac83&is=656f3783& hm=8ac43105ee8b8331397548a74043ab94ea9166485aef0918139cc5dfd 986d8c4&


Ter's version:
https://cdn.discordapp.com/attachments/725458744711839873/ 1182493530300620882/SIDEMAPTEST_src.zip?ex=6584e5eb&is=65727 0eb&hm=f7fcfddfb9ae6e892b79e70c62eb2b1f4750f5d2cd044e30a4dd0 e2b995f5e66&
Expected Results:
The rendering process should consider each atom's individual bound_x/y values without affecting their drawing order. This means that atoms should be drawn based on their actual positions, irrespective of the differences in their boundary dimensions.

Actual Results:

The rendering incorrectly offsets the drawing order based on the differences in bound_x/y values of the atoms. For example, if atomA has a bound_y of 24 and atomB has a bound_y of 6, atomA's drawing position is offset by an additional 18 pixels, leading to an unintended alteration in the drawing sequence.
Does the problem occur:
Everytime.

When does the problem NOT occur?
As far as I know, it has never NOT occurred.

Workarounds:
Make sure that all your sprites start at the bottom left of the frame. Basically, there is no workaround.
int iconSortFuncSide_T(MapIcon const *mi1, MapIcon const *mi2) {
if(mi1->bound.x1 <= mi2->bound.x0) return 0;
if(mi2->bound.x1 <= mi1->bound.x0) return 0;
if(mi1->bound.y1 <= mi2->bound.y0) return 0;
if(mi2->bound.y1 <= mi1->bound.y0) return 0;
if(mi1->posbound.y0 >= mi2->posbound.y1) return -1;
if(mi2->posbound.y0 >= mi1->posbound.y1) return 1;
if(mi1->z != mi2->z) return mi1->z < mi2->z ? -1 : 1;
int ret;
if((ret = mi2->posbound.y0 - mi1->posbound.y0)) return ret;
// tiebreaker: objects to the left should be drawn first when overlapping
if((ret = (mi1->posbound.x0+mi1->posbound.x1) - (mi2->posbound.x0+mi2->posbound.x1))) return ret;
// return original order if bounds are totally equal
if(mi1->posbound == mi2->posbound) return mi1->i - mi2->i;
return 0;
// TODO: It'd be nice to consider original order for big icons laid down over small ones, but I think it's more likely to result in deadlocks
}


This is code that Lummox provided a while ago in BYOND Discord. So what I'm thinking is that posBound for each MapIcon needs to subtract the bound_x/y value from the atom(s) carrying their respective icons. And that probably resolves the issue.

But this seems like a very simple solution so it's probably wrong.
I did pop in to investigate this issue a bit, and asked for a test case, as I use SIDE_MAP extensively, and one of the axioms that I have developed for working with SIDE_MAP and getting the results I want, is to totally disregard bound_x/y, and ONLY use pixel_w/z to offset large graphics to match the bounding box. Why? because w/z do not affect the sort order of sprites.

In the process, I built a visualization tool that described the problem and showed that we needed to be talking about visual bounds, and that physical bounds were irrelevant to the sort in our case.

Honestly, developers do want to think of their layering position in some cases as being based on physical bounds rather than visual bounds. bound_x and bound_y are undesirable to use in SIDE_MAP at this time, because they severely impact layering of sprites.

There is definitely value in considering some sort of investigation into what would work better, because the axioms I have followed for years to get good results out of SIDE_MAP have been described as "band-aids", and even criticized by you, Lummox. But again, given my understanding of how the sort order works, I just can't get results from the engine any other way than manipulating the visual position of objects using pixel_w/z, and pixel_x/y to tweak the position of objects based on their visual bounds.
Thanks again to the horseman for providing more context to this issue. So here's my thing, upon closer examination, we can see that the issue is actually that the sorting is depending on the bottom-left corner of the sprite -- not the bottom-left corner of the bounds, as mentioned above.

I will show an image of the "bug".

Descriptive Text

The red box is the "visual bounds" (basically the frame size for my icon) of the Human. The light blue box is the visual bounds for the squirrel. The dark blue is the bounding boxes.

As you can see, because the visual bounds for the human is lower on the y-level, no matter what the squirrel is going to be drawn first. My initial confusion came from my belief that this was supposed to be based on the physical bounds.(I have receipts of Lummox saying as such, so I assumed this was intended behavior. I may have been misreading)

It's also why the human character had to go at least 19 pixels north to be drawn behind, because it is misaligned with the bottom_left of the visual bounds.

It's why to rectify this, the Horse man came up with using pixel_w/z to adjust the positioning and simply foregoing the use of bound_x/y. This way, your icon is always pushed to the bottom left of the visual bounds.

It works, but I don't think that should even be necessary. It needs to go based on the object's boundary. It would be neat if we could get some insight if this is considered a bug, or if its even feasible to adjust to be more sensible.


EDIT:

So there appears to be a weird connection between physical and visual bounds. At least I think there is.

I ran some tests to have the bounding_box to be BELOW where the visual bounds would be. I did this by setting the monster's bound_y to -40. I found that whenever my human character's VISUAL BOUNDS passed was at least 1 pixel over the physical bounds for the monster, it was drawn second.

I was not able to reproduce this for bound_x/y values above 0.

You can see an image of this below:

Descriptive Text

EDIT #3:

So I found that whenever your physical boundaries go BELOW the visual bounds, then the sorting works as anticipated.


https://i.imgur.com/ot46aBE.mp4


All in all, this shit don't make sense. There are a lot of holes in the function. Lord Lummox JR, please come make sense of this!