Kandria
Broo!
Got ya! Scared ya!
Didn't expect me to write an entry on Saturday already, did ya!
Anyway, since this week I spent a significant amount of time building a demo level, I thought it would be worthwhile to talk a bit about how that works in Kandria. As you might have discovered from the demo already, at any point in the game you can pause it and open the in-game editor by pressing the section key (top left key below Escape).
You can then click on anything in the game window like the player or the current chunk, and it'll open an editor for that. For the chunk, there's also a panel on the right that can be expanded, which shows the active tileset for it. You can then select a tile and draw into the chunk. By activating the switch in the top right of that panel you can also switch to editing the solids – at least that's how it works now, I don't quite remember how it worked in the previous demo, it might be slightly different.
However, placing the tiles manually is extremely tedious and time consuming. Especially if you take into account that the tiles should be varied in places, and that backgrounds and foreground elements need to be added, too. In order to ease the burden of this at least a bit, Kandria includes an 'auto-tiler'. You first draw the outline of a solid object, then switch to the layer it should auto-tile, and Ctrl+Left Click in the middle. That should automatically populate it with the appropriate tiles.
In the demo version this did not work as well as it does now. I spent a good amount of time yesterday fixing this system up to work in more cases and place more types of tiles. In any case, having such a system massively reduces the amount of work required. In fact, it's often so good at it that all you need to do afterwards is draw in backgrounds and place decorations. Most of the original demo level was built exactly like that.
This auto-tiling system works in a couple of steps. First, it marks everything that's inside the shape with a special tile by using a standard bucket fill technique. Being able to discern inside from outside is important for the subsequent steps. Second it scans horizontally and vertically to try and find an edge of the shape. Once a valid edge (one that is not the border of the chunk) has been found, it starts to move along this outer edge to try and determine what kind of tile should be placed there.
This tile recognition happens by applying 3x3 filters to the current position. These filters will only match if the current position indicates a certain type of tile. Here's a short excerpt of some of these filters:
(:t
_ o _
s s s
x x x)
(:tl>
o _ _
_ s s
_ s x)
(:ct
o s o
s s s
x i x)
The first filter recognises a 'top edge'. It does this by ensuring the tiles at position, as well as left and right are definitely solid, the tile above is definitely 'outside', and the tiles below are either solid or inside. The second filter determines a 'top left outwards facing edge'. Similarly, it checks the diagonal is outside, and that we have a nice, solid edge shape appearing around the current tile. The third filter determines a 'T junction facing up'. You should be able to read the pattern pretty easily now. The only thing to note here is that the tile below must be 'inside' and not solid, as otherwise it might also match a cross shape.
There's a bunch of these filters in there to recognise different situations. Each filter then designates one or several tiles in the tilemap that may be placed at this position, of which the system randomly chooses one. Finally, the recognised filter decides in which direction to move next. In general the system tries to move clockwise along the outer perimeter until it reaches its starting position again or encounters an unrecognised tile configuration. To this end, the top edge and top left outwards facing edge will always move one right. However, the T junction will move upwards only if it was previously moving right. Since the solid line going upwards is only one tile thick, there's no "inside" and thus no way to move clockwise along its border. In order to handle this, filters that deal with tiles that have no inside must be aware of where they used to be moving before. A corner piece will then invert direction, so that it can move back towards the "full" shape again. Thus, when the cursor reaches the T junction again this time moving downwards, the T junction will then direct it to then turn and move right instead.
This way the system can handle both "fat" and "thin" shapes without endlessly running in circles. Still, there's a few situations right now where the system trips and doesn't know what to do, though I'll just fix those situations when they come up. For now the system works well enough to not be an immediate thorn in my side.
Next week I'll work on new 'dummy' enemies and refine movement some more, and then I think it's high time to update the demo. There's been some good changes that I'd like to get your feedback on!
See you then!