Thursday, February 17, 2011

AutoTiles, pt. 1

Save for a bit of a graphics card issue I had yesterday, the past several days have been mostly about improving the coordinate system and putting features from the new collision system I demoed for you guys earlier back into the alpha. I've also been working on improving the map loader.

An interesting problem presented itself yesterday when beginning to implement AutoTiles into the alpha. I will explain after the cut.



An example autotile.

AutoTiles are a feature that a lot of you guys should be familiar with.  They're simple tilesets which can be used to create a variety of automatically connected tiles by subdividing the portions of the autotile set.  In FaeSaga, the engine determines how to place down autotiles based on a qualifying bitmask comprising of the adjacent tiles' values, and compares the bitmask to a lookup table to determine which subdivisions of the tileset to use.

The feature was first implemented way back when I was working on the engine for Faerie Tales, but with the new iteration of the engine, some improvements have been made to speed with regards to loading the map files into memory before blasting the tiles to the screen.  To understand why these improvements pose an issue for creating autotiles in the new engine, you must first understand a little bit about my map format.

This is an example of what my map format looks like when opened in a text editor.  Basically, it's formatted like an INI file, with definitions for the various parameters of the map as keys.  The part to pay attention to, however, is how map arrays are (and have always) been stored internally in this map format.  They are a comma-separated list of values -- essentially, a 1-dimensional array.





Originally, in Faerie Tales' tile engine, this value was loaded in and out of a 2d array, just like in the tile editor.  There was really little use for this, as tokenizing and copying over the string to a 2d array didn't serve to make normal linear blitting any more efficient (or the maths that much easier).  So, for FaeSaga, this was changed to simply blit tiles based on the position in the 1d array using the following calculation:  n = yPos * 32 + xPos.  The number referenced at this position in the array determined the tile number to blast to screen.

However, for AutoTiles specifically, having a 2d array did simplify one specific calculation, and that was to create the qualifying bitmask for the AutoTile layer.  Some calculations can be made to check "adjacent" tiles in the imaginary 2d array on this 1d list, but the simple ones I have come up with so far are simply adding and subtracting specific numbers (eg:  n-33 for upper-left, n-32 for top tile, n-1 for left tile, etc.).  This seems to work OK, but only in situations where the array value does not border the edge of the screen.  For example:

Click to Enlarge.

I wrote a program to test these edge cases for me to see potentially what sorts of issues there might be from qualifying the bitmask based on the "hodge" calculations for a 1d array, and to possibly add some case logic to improve the result for the specific autotile made when a tile to be qualified does border the edge.  Under the current 1d array bitmask qualifying function, here is what happens in an edge case:


As you can see, when the tile to be checked (the one surrounded by green diamonds) is near the edge, some of the qualifying tiles wrap around!  This produces an unexpected appearance when autotiles are near the edge in the new engine, and will likely have to be changed in the near future.

Some further information:  In the old engine, edge cases were also handled specially in the 2d array.  When a qualifying tile was in the "imaginary area" outside the bounds of the array, the function would return 1 for that position in the bitmask.  The reason for this is so that autotiles near the edge would appear to go off the edge of the screen instead of stopping at the edge.  I want this same effect replicated in FaeSaga's tile engine, but to do this, I have to come up with a new trick.

Please Share


No comments:

Post a Comment