Autotiles! You can add them to your game, too :3
15 years ago
General
Hello, please bear with me, as there is some useful source code and tools available at the end of this little rant :3
First, let me tell the story leading up to this post. As part of a job-related project, I've been working the last couple of weeks on getting RPGMaker-style AutoTiles to work in MMF, as part of a tile engine I've been working on for several months. Autotiles in MMF are actually quite difficult, since MMF doesn't really like to be forced to render a zillion pieces onto the canvas, and AutoTiles are actually subdivided compared to standard sized tiles on a tile engine's grid, quadrupling the potential number of tiles needed to blit. Furthermore, the way MMF handles code, adding events to check for multiple condition states becomes a hassle as the number of these states increases, unless the event can be folded into a larger condition. Since the number of combinations of adjacent tiles in a standard cartesian grid, this would mean that for each condition check in MMF, I'd have to have 256 events!!
I spent a long time trying to figure out a solution to these problems, and had given up for several months while working on other features of my tile engine. However, a couple weeks ago, the solution for both problems just sorta floated into my head. I'll discuss the solutions in the next couple paragraphs, but if you're not making a game in MMF then you can skip them and head to the next part, as the results are still very useful for any game.
Since each adjacent tile to an autotile can be given a boolean value (tile match or no match), it could be expressed in a single byte of data, or an integer value between 0-255 in MMF's case. The conditions can be folded down by instructing MMF to always check a lookup table for the resultant pieces of an autotile image to paint onto the surface. This solved the "too many events" problem, by limiting the number of check conditions needed per loop when loading the map. The next problem to solve was number of background objects on screen.
MMF doesn't seem to like too many backdrop objects on screen at once. Its limit before starting to slow down on my machine in software mode is about 4000 BGO's, which can easily be reached with my original (inefficient) tile engine pasting about 5 layers of 32x32 tiles at 1024x768. The secondary solution to the autotiles problem came from optimizations to lower this amount down to ~1000 BGO's. By ignoring blank tiles, the optimized tile engine would paste less objects to the screen, thereby increasing the speed. It doesn't seem to matter much the size of the BGO pasted/blitted into the background as much as it does the number of them in-memory for MMF, therefore, the larger the tiles can be made before pasting them to the surface, the faster the game will run. For AutoTiles, this meant generating a custom lookup table to skip over as many pasting operations as possible inside the loading loop. Since the BGO's persist throughout the frame and will continue to slow it down even after the map is loaded, having as few paste operations as possible was crucial.
To solve the problem of creating the custom lookup table, I wrote a tool specifically to edit and output one in an MMF-friendly format. The values are delimited by CrLf newlines, so it would be easy to include my custom table in your own code, but I thought that it would be even better if I included the program for people to make their own custom tables, for example, a non-mmf-optimized table which would probably have cleaner code in a real programming language, or super special lookup tables which can handle diagonals correctly to make the autotiles look less blocky (this would require non-rpgmaker-compatible autotile files). Here is the source code:
http://nobuyuki.gpknow.com/lab/Auto.....ookupTable.rar
It was created with VB.NET, so you'll need Visual Studio or VBE to edit the source. A compiled version is included in /bin/debug, and the file "ATLookupTable" is the custom table. Click the Open button to import the table, and the save button to save to this file. Here is a screenshot:
http://img340.imageshack.us/img340/2503/atlt.png
To use this in your game, simply check the line number of the integer value of the bitmask of the adjacent tiles times 4 in the table for the proper tile to blit to the surface. Each adjacent tile has an associated bit value, with the upper left being the LSB and the lower right being the MSB. Or, in integer terms, the upper left adjacent tile, if it exists, has a value of 1, the upper middle, 2, the upper right, 4, and so on until the lower right (128). Add the values of the adjacent tiles together when checking which tiles to blit to the current spot, and then check that position *4 for the upper left, *4+1 for the upper right, *4+2 for the lower left, and *4+3 for the lower right.
I hope this application and associated code will be useful to anyone working on their own tile-based engine.
First, let me tell the story leading up to this post. As part of a job-related project, I've been working the last couple of weeks on getting RPGMaker-style AutoTiles to work in MMF, as part of a tile engine I've been working on for several months. Autotiles in MMF are actually quite difficult, since MMF doesn't really like to be forced to render a zillion pieces onto the canvas, and AutoTiles are actually subdivided compared to standard sized tiles on a tile engine's grid, quadrupling the potential number of tiles needed to blit. Furthermore, the way MMF handles code, adding events to check for multiple condition states becomes a hassle as the number of these states increases, unless the event can be folded into a larger condition. Since the number of combinations of adjacent tiles in a standard cartesian grid, this would mean that for each condition check in MMF, I'd have to have 256 events!!
I spent a long time trying to figure out a solution to these problems, and had given up for several months while working on other features of my tile engine. However, a couple weeks ago, the solution for both problems just sorta floated into my head. I'll discuss the solutions in the next couple paragraphs, but if you're not making a game in MMF then you can skip them and head to the next part, as the results are still very useful for any game.
Since each adjacent tile to an autotile can be given a boolean value (tile match or no match), it could be expressed in a single byte of data, or an integer value between 0-255 in MMF's case. The conditions can be folded down by instructing MMF to always check a lookup table for the resultant pieces of an autotile image to paint onto the surface. This solved the "too many events" problem, by limiting the number of check conditions needed per loop when loading the map. The next problem to solve was number of background objects on screen.
MMF doesn't seem to like too many backdrop objects on screen at once. Its limit before starting to slow down on my machine in software mode is about 4000 BGO's, which can easily be reached with my original (inefficient) tile engine pasting about 5 layers of 32x32 tiles at 1024x768. The secondary solution to the autotiles problem came from optimizations to lower this amount down to ~1000 BGO's. By ignoring blank tiles, the optimized tile engine would paste less objects to the screen, thereby increasing the speed. It doesn't seem to matter much the size of the BGO pasted/blitted into the background as much as it does the number of them in-memory for MMF, therefore, the larger the tiles can be made before pasting them to the surface, the faster the game will run. For AutoTiles, this meant generating a custom lookup table to skip over as many pasting operations as possible inside the loading loop. Since the BGO's persist throughout the frame and will continue to slow it down even after the map is loaded, having as few paste operations as possible was crucial.
To solve the problem of creating the custom lookup table, I wrote a tool specifically to edit and output one in an MMF-friendly format. The values are delimited by CrLf newlines, so it would be easy to include my custom table in your own code, but I thought that it would be even better if I included the program for people to make their own custom tables, for example, a non-mmf-optimized table which would probably have cleaner code in a real programming language, or super special lookup tables which can handle diagonals correctly to make the autotiles look less blocky (this would require non-rpgmaker-compatible autotile files). Here is the source code:
http://nobuyuki.gpknow.com/lab/Auto.....ookupTable.rar
It was created with VB.NET, so you'll need Visual Studio or VBE to edit the source. A compiled version is included in /bin/debug, and the file "ATLookupTable" is the custom table. Click the Open button to import the table, and the save button to save to this file. Here is a screenshot:
http://img340.imageshack.us/img340/2503/atlt.png
To use this in your game, simply check the line number of the integer value of the bitmask of the adjacent tiles times 4 in the table for the proper tile to blit to the surface. Each adjacent tile has an associated bit value, with the upper left being the LSB and the lower right being the MSB. Or, in integer terms, the upper left adjacent tile, if it exists, has a value of 1, the upper middle, 2, the upper right, 4, and so on until the lower right (128). Add the values of the adjacent tiles together when checking which tiles to blit to the current spot, and then check that position *4 for the upper left, *4+1 for the upper right, *4+2 for the lower left, and *4+3 for the lower right.
I hope this application and associated code will be useful to anyone working on their own tile-based engine.
FA+

It's the parsing of code within the game that's going to be a greater challenge - I seem not to like making things easy for myself ;)
LoopIndex(X) = 0: AdjacentBitmask += 41
LoopIndex(X) = 31: AdjacentBitmask += 148
LoopIndex(Y) = 0: AdjacentBitmask += 7
LoopIndex(Y) = 23: AdjacentBitmask += 224
this should work because tiles near the edge will never have these adjacent tiles return True because they're out of bounds for your tile array. You have to have special cases to adjust for the corners, of course. If we use the above lines instead of adding AND NOT conditions to exclude edge cases in all lines, we can simply subtract the excess if it's a corner (since there'd be exactly 1 double-counted corner). Again, an example:
LoopIndex(X) = 0 AND LoopIndex(Y) = 0: AdjacentBitmask -= 1
LoopIndex(X) = 31 AND LoopIndex(Y) = 0: AdjacentBitmask -= 4
LoopIndex(X) = 0 AND LoopIndex(Y) = 23: AdjacentBitmask -= 32
LoopIndex(X) = 31 AND LoopIndex(Y) = 23: AdjacentBitmask -= 128
That should make the evaluations for all edge tiles assume that the "outer rim" out of the array bounds is filled with tiles exactly like the current autotile, so that the result looks like the tiles are going off-screen instead of blobbing at the edges. This edge case solution is specifically geared for MMF. In C or VB.NET 8+, bitwise operators would be used instead.
Been toying with making game editor/compilers too, but don't have enough time to stay on track. >_<