So, what's the deal with the graphics in ADiA?
Added 2022-10-15 11:58:47 +0000 UTC
ADiA doesn't use 3D or ray casting; all of the graphics are pure 2D sprites. I get asked a lot about what engine do I use, but it doesn't matter! As long as your engine can display 2D graphics, you're good to go.

As is pretty obvious, the map is made up of squares. The data comes from a tile set, corresponding to every possible wall combination.

This is what's being drawn when you look at the map! But it also acts as the collision map. Every tile is enumerated, so the game uses a look-up table to see if there's a wall in the direction the player is looking in in that particular tile. There are also walls, which ignore collision, and special walls, which use different graphics (such as Okuu windows in the Palace of the Earth spirits).
The same look-up table is used to draw walls. First, we need a projection.

The game check several tiles in front of the player, iterating from closest to farthest. Let's see what happens when the game checks a tile, like this one:


The sides are checked first so they can be drawn in front of the wall which is farther away from the player. But wait... If we actually draw them like this, we'll have some problems.

The walls are being drawn in the wrong order! Instead of drawing the walls right as they are being detected by the collision code, we add them to a queue, and when the algorithm is finished, we draw the walls from farthest to closest. Each wall has its own offset to be drawn to, to align with the projection.
Now let's look at some optimization! As you can tell, the graphics are pretty static when the player is not moving. There's no need to draw the walls every frame, so the game draws the walls to another surface ONLY when needed, such as when taking a step or rotating. Then, this surface is drawn to the upper screen every frame. This also makes it possible to use shaders, such as a heat haze effect, or a pallet swap shader. This pallet swapping gives the candles in the Palace their animation! (The same technique applies to drawing the lower screen. Basically, if something's not moving, the game doesn't bother redrawing it every frame.)
You might have noticed, there's no culling! The game draws a wall regardless if there's another wall in front of it. I didn't see a reason to implement culling when the wall drawing algorithm is already decently fast, and only updates once when needed. This also gives me opportunity to make a dungeon with transparent walls, or one where the walls are shorter than normal.

Here is an example of the wall graphics in the Palace of the Earth Spirits.

Each frame corresponds to a specific wall animation and type. You can also see the highlighted colors which act as a mask for the pallet swapping shader!
In conclusion, there's not a single polygon being drawn to the screen, everything is pure 2D with a very specific projection and hard-coded values. I'm not sure if this is how old-school SMT handled this, and I didn't use any tutorials; this is my own implementation.
This is a very surface-level explanation, so If you have any specific questions, feel free to ask!
Comments
This is really cool, I love reading about stuff like this! It makes it even more exciting to watch it all happen in game knowing how it's put together. Especially knowing you didn't use any tutorials to come up with this system, and it turned out pretty optimized... That's super cool.
Ninety Spiff
2022-10-15 15:55:22 +0000 UTC