Over my Christmas break week, I thought I’d take the time to hop off the story progress train for a little while and deal with one of the graphical aspects of the game that’s been really bugging me for a while.
First, though, a confession: I find it quite annoying and even demotivating when my game’s graphics are lacking and/or don’t look the way I want them to. It’s like having a big, dark cloud hovering over your head – except the cloud is awfully misshapen, has very dodgy shading, used waaaay too much dithering, and overall looks like it was thrown together in MS Paint in five minutes.
In all seriousness though, it really is hard to motivate myself to work on story and coding aspects when I know the graphics still need work.
One of those aspects which I’ve really been wanting to work on are the tiles. Instead of using objects (or instances) for walls, I use graphical tiles for walls and water since they take up less memory and require much less time to process than an actual instance. The wall and movement system itself is a grid-based system, which you can read more about in a previous post.
Tiles are really important to get looking good since the player sees them all the time. The problem, though, is that much of Ambience takes place in procedurally generated dungeons, and so the tiles have to be placed and chosen automatically. Hence we enter the wonderful world of autotiling algorithms…
The Double-Layer Method: 32 Tiles
On the internet you’ll find plenty of algorithms for autotiling, including 16-tile systems for four-directional walls (up, down, left, right) and 47- or 64-tile systems for eight directions (i.e. including diagonal directions). The original system I used in Ambience, however, employed only 32 tiles and used a sort of “double-layer system” to place tiles and make them look good.
What do I mean by that? Well, for each tile/square in the room, the computer would place two tiles. The first, bottom tile was chosen from a set of 16 tiles and depended on the presence of adjacent walls in the four basic directions (up, down, left, and right) – just like the 16-tile system I mentioned earlier. Then, the computer would also place a “corner tile” on top to fill in the corners, depending on whether there were adjacent walls in the diagonal directions.
Perhaps you’ve already realized that this requires the use of twice the number of tiles to be processed in each room compared with a more conventional, “single-layer” system which puts a single tile on each square. But in practice, I found another problem as well. The system worked fairly well for flat tiles, but not for tiles which had the illusion of rising out from the screen – such as these rocky walls, which I had to place manually for this screenshot:
The reason why the double layers didn’t work here was because the corner tiles don’t work well with the upward-facing wall sections. Perhaps this graphic can explain it:
A Better Method: 47 Tiles
The bottom line was, I needed a better strategy.
There’s a reason why people tell you to avoid “reinventing the wheel” – in other words, if the technology’s already out there and it works, use it! In the end, I decided to scrap the original double-layer method and go with the better-established 47-tile method (see the links at the end of this post). It turns out that you can make every possible wall combination in 8 directions with only 47 tiles and a neat algorithm, which I incorporated manually into Ambience‘s autotiling system.
The biggest reason why I made this change was because the double-layer, 32-tile method didn’t work well for the rise-out-of-the-ground type of walls, which I actually preferred over the flatter wall tiles I had been using previously. And indeed, the results from the new system were much nicer than what I had before!
You may also notice that I also made the floor background a little darker to account for the different shading on the walls making them a little lighter, even though I used the same colour scheme as before.
So, what did I learn from all this?
I think the two main take-away messages from this are:
- Don’t reinvent the wheel. If you’re thinking of using a new method that looks a little too easy, then chances are it’ll cause problems later down the track. Think hard about what you want out of a system before you implement it.
- Don’t skimp out on good graphics. It’s a lot more satisfying and motivating to see your game looking nice graphics-wise, instead of seeing boring flat walls or MS Paint disasters. Also, if you can’t make good graphics yourself, either learn how to or get someone else to help you out.
- Here’s a nice link explaining probably everything you could ever want to know about autotiling algorithms (or bit-masking as it’s also called), including the 47-tile method.
- Also, the system I’m now using is adapted from this resource on the YoYo Games Marketplace (for use in GameMaker: Studio), which uses the 47-tile sheets.