There are a bunch of tweaks and fixes I still need to do for the 3D changes. I am currently holding off changing collisions/physics, since they technically work (good enough). And I’m still not ready to mess with lights.
One glitch I have is with the sorting order of the wall (and door) tile sprites:
In short, side and front sprites have the same value, but also similar “to-camera-distance” values, which confuses certain shader setups as to what is to be rendered first.
I can solve this fairly easily with the new list- and designation- based sorting of sprites. I can differentiate the side and front of the tiles:
I also just removed the back face, because it’s never visible (I don’t rotate the camera).
I do render sprites that are invisible — the side and front sprites of walls when they have adjacent walls. I could just leave it as is and not bother with this. But there’s a specific issue I need to solve, which is “fading” the walls:
In short, fading top and front reveals the partly-faded side (double) sprites as well. Basically, I have no choice but to code some logic to remove/hide these. So if a tile has a visible neighbour, that side’s sprite gets hidden.
I do have a pretty involved pipeline for how the tile even gets to that point. I need to generate the dungeon, set the tile type (wall/floor/etc.), then spawn the player, then reveal the tiles around the player, and only then can I properly update the sprite visibility. To go through the pipeline, I had to write a nice little debug editor telling me all about a selected tile (world object):
It took a while to get things fixed, especially door interactions. But now, the fading is much better (at least, without any obvious glitches):
I also sort of want to do backside culling for the sprites. The problem is that the camera perspective can “hide” wall side sprites when they are facing away from the player, and this causes that wall to still render and thus fade weirdly:
I considered just toggling on culling, but this ends up breaking more things than it fixes, due to various shader reasons. I think I will just leave it as is — that is, good enough.
I also draw the front/side sprites of walls even when it is never visible from a certain direction (connect to nothing):
So I am flags for those as well:
And the visibility is then controlled by the blocked flag and this flag together.
Unfortunately, there’s an issue of being able to see under the wall:
I don’t actually know how to solve this. I can’t add more walls in the “gaps”, because they won’t be visible anyway. I could extend my dungeon generation, lighting and visibility algorithms to include it… but I really don’t want to spend that much time. In fact, I think the simplest resolution is to just have a special sprite for this case:
And these appear in-game on the invisible sides of the walls:
I can even color them the same as the background, thus making them essentially hide the wall back-sides. Although, I will likely keep them slightly different.
I am now also using an (asset store) shader that renders pixel art much nicer when not pixel-perfect and when zoomed in or slanted. This lets me enable filtering on sprites and have the shader deal with precision “pixel-perfect blending”. There were a few issues with integrating this, but I got it all working in the end. It’s not a huge difference, but now my “incorrectly” scaled and rotate sprites no longer flicker like crazy and no longer blur to oblivion if smoothly filtered.
The downside is that I lost all of my custom shader code to flash and tint the sprites. Although I think the shader code is simple enough where I could re-add this without too much trouble. At a later time.
I still have a bunch of issues because of this. For example, the sprite render sorting order seems to completely ignore the hierarchy:
So I went back to Z-ordering of sprites:
But it also seems to completely ignore the Z coordinate of “overlapping” sprites. So I guess need to change the sorting order for each sprite manually. So I need a sorting designations for every possible mob part render offset/layer:
I then have to specify each mob’s sprite renderer with its own sorting group:
(I really need to just use the sprite renderers instead of the whole sorting group. Not sure how much difference it makes.)
But of course, I don’t know what the sorting designations are until I “build” the mob. And even then they change based on direction and such. So I need to “teach” the mob world object to look up the designation based on the layer:
And a little debug to let me see if the right layer is chosen at runtime:
And that fixes the mobs back to what they were before, but now with 50 extra steps.
Another issue I have is that world object elevation, such as the elevation at which projectiles leave weapon barrels, is totally fake. What I do is just offset the main coordinate to fake it and make it look like it’s flying above ground:
Unfortunately, that means that I have a bunch of problems with aligning projectiles to weapons and such. I won’t go into all the issues this adds, but, for example, effects don’t spawn on walls, but on the floor below them. What I need is to “lift” the sprite according to its elevation. In other words, like this:
A whole lot of math and tweaking later, I have it more or less working. It’s not perfect and the camera angle means there’s always some error, but it’s much better. And with a hand-chosen constant multiplier, I can get it to look exact in-game (as long as I don’t change camera angles too much):
It even looks (and is) like the projectile hits the wall and spawn the effect at the right location:
This is one of the things I can do in my 3D setup that I couldn’t do in 2D with fake walls due to the way “collisions” worked.
Anyway, those are the major issues I’ve had recently. Hopefully, they are sorted now, although I fully expect more to come. Such is the price of doing semi-fake 3D.