PDA

View Full Version : Tilemaps and autotiles



Darkhog
10-07-2013, 10:38 PM
RPG Maker has nice feature called Autotiles. Those tiles are made so one tile can be shrinked to as small amount as 3x3 tile square plus one tile with cramped corners.

Example autotile
http://i.imgur.com/VPLxXf3.png
Top-left tile is used only as display of tile in editor, top right contains inside corners of tile. 3x3 tiles square contains outside corners, sides and middle of tile.

Here are tiles that can be made out of this:
http://i.imgur.com/6xBuJBW.png

(I'm using unofficial Polish translation of RPG Maker XP so title is because of that).

I have pretty much idea how I can break up autotiles and make all those tiles. Problem is another one - how I choose "right" tile so they'll fit together in map?

Let's assume that in following code "0" represent normal tile and "1" autotile. I want to display them properly:

0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0 1 0 0
0 0 0 0 1 1 1 0 1 0 0
0 0 0 1 1 1 1 0 1 1 0
0 0 0 0 0 1 0 0 0 1 0
0 0 0 1 1 1 1 1 1 1 0

How can I achieve this?

Super Vegeta
11-07-2013, 09:31 AM
I used to check all eight adjacent tiles if they are the same type or not, and then draw the autotile accordingly. I had two variables, one for sides, one for corners. Each of them was actually kind like a 4-bit flag. I set them according to the adjacent tiles, and then I had a huge (16-element, duh) case of sides_variable. Like, if no adjacent autotiles, draw the "single spock", if only one adjacent autotile, draw the connecting gfx on one half, and on the other half draw corners (which can be either inside or outside facing).

If you'd like, I can share some code, but you'll have to give me some time to add comments et cetera so it can be readable.

Darkhog
11-07-2013, 12:14 PM
Sure! Will wait.

Super Vegeta
11-07-2013, 05:10 PM
Instead of posting actual code, I think I'll just describe the logic I used.

First of all, this code was designed to use a different format of autotiles, like this:
http://svgames.pl/trash/brickblue.png
5 tiles placed horizontally: full tile, top & bottom border, left & right border, outside corners, inside corners.



// Bit flags for sides and corners.
const SIDE_TOP = 1; SIDE_BOT = 2; SIDE_LEF = 4; SIDE_RIG = 8;
COR_TL = 1; COR_TR = 2; COR_BL = 4; COR_BR = 8;

// I assume map to just hold integers with tile types
Procedure DrawMapTile(X,Y : Integer; Gfx : whatever)
Var Edges, Corners : Integer;
begin
Edges := 15; Corners := 15; // All flags set means that autotile is stranded and we have to draw borders.
If (Y = 0) or (Map[X][Y-1] = Map[X][Y]) then Edges -= SIDE_TOP; // We mark top side as no-border
If (Y = (MapH-1)) or (Map[X][Y+1] = Map[X][Y]) then Edges -= SIDE_BOTTOM; // We mark bottom side as no-border
// The same for left
// The same for right
If (X = 0) or (Y = 0) or (Map[X-1][Y-1] = Map[X][Y]) then Corners -= COR_TL; // We mark top-left corner as the same type
// Same for top-right
// Same for bottom-left
// Same for bottom-right
Case Edges of
00: begin // 00 means that all sides are connected. We either have to draw a full tile or an all inside-corners tile.
DrawFullTile(X,Y);
DrawCorner(X,Y,Corners,COR_TL);
DrawCorner(X,Y,Corners,COR_TR);
DrawCorner(X,Y,Corners,COR_BL);
DrawCorner(X,Y,Corners,COR_BR)
end;
01: begin // 01 means that there is a border on the bottom side.
DrawBorder(X,Y,Edges,SIDE_TOP);
DrawBorder(X,Y,Edges,SIDE_BOT);
DrawCorner(X,Y,COR_TL);
DrawCorner(X,Y,COR_TR);
end;
Et cetera, et cetera. Edges can be 00-15, so you have 16 cases. DrawBorder() should check if the appropriate edge (SIDE_XXX) flag is set in Edges, and either draw a border or draw the connecting part of tile. DrawCorner() behaves the same way.

This approach requires much copy-pasta and introduces some over-draw, but I've found the easiest to implement in terms of logic.

Darkhog
11-07-2013, 09:58 PM
Well, 16 tiles aren't enough.

Sure, you could do tile like this:

-------
|######
|######
|######

or this:

-------
#######
#######
#######

But how about this:

--------
|######|
|######|
|######|
or this:



------
######
######
------
? I know you know RPG Maker because I know you from Polish RPG Maker forum, even you are using same avatar. I want solution like in case of RPG Maker.

Also I've said that I have no problem with breaking autotile into individual tiles, main problem is getting "right" "sub tile" for the job.

//edit: Anyway, I've decided that I'll write "breaker" program that would break autotile into individual tiles and output it into image file. Then in map editor I'd place them manually. Would save myself coding pain.

Super Vegeta
11-07-2013, 11:22 PM
It's not limited to 16 tiles, you can do all the shapes an autotile can have on a square map.
-------
|######
|######
|######
Edges = 5 (top + left). Draw left border, top border, top-left outside corner, and then either a continuous tile or inside corner in bottom-right.
-------
#######
#######
#######Draw top border. Bottom side, each quarter-tile is either continuous or an inside corner.
--------
|######|
|######|
|######|Draw left, right border, and top inside corners.

------
######
######
------Draw top and bottom border.

If you forget about the "continuous or inside corner" issue, you only have 16 possible tiles - depending on the four neighbouring tiles: top, bottom, left and right. That's why I wrote about 16 cases. In the cases I draw borders and outside corners, because they depend only on those 4 tiles.
x----
-Xxx
-xxxWe can tell the "big X" must have an outside corner at the top-left, no matter if the (X-1,Y-1) tile is of the same type, or not. So, like I said, checking the 4 neighbours gives me 16 cases, and in every case I know exactly which borders and inside corners I have to draw. Then I only need to check if any of the remaining quarters of the tile should be continuous or have an inside corner.


If it still sounds bizarre, give me a day and I'll write you an example.

Super Vegeta
24-07-2013, 08:49 PM
I'm writing yet another project, which also uses autotiles. The result looks like this:
http://svgames.pl/trash/autotiles.png
If you're still interested, I can post a sample program here.

WILL
25-07-2013, 06:02 PM
Here is an old "guide" that I made for my current game project some years ago.

1189

The tiles aren't used quite exactly the same way. It was more meant for walls instead of your typical RPG map tiling. However it shows all the checks to select a tile from a list of 47 individual case scenarios you would encounter.

The basic idea was to check your 4 cardinal directions and if a wall (or in your case tile of the same type) was detected in 2 tiles beside a corner it would check that corner too.

Not sure if this would be of any help, but it sort of relates so it might give you other ideas of just confuse. ;) Enjoy! lol

Darkhog
26-07-2013, 09:20 AM
Hm, that chart helps a lot. Thanks!

@Super Vegeta, sure, post it!

SilverWarior
26-07-2013, 10:30 AM
I will try to post my idea of how to solve this shoretly I hope.

Anywhay in my idea you have numerical property which tels you which sprite you need to use for that tile. Since you are afecting this number by changing seperate bits of this numerical variable (each bit represents each side and each corner) there will be no need to use any logical system for constantly figuring out which sides/corners of your current sprite are neighboring to other wall sprite for instance. Since the system uses 8 bit integer (byte) for determining autotile you have 256 posible options for each cell.

Now I'm currently testing different aproaches for changing seperate bits of this numerical variable to see which is best and safest. I'll try to make it thread safe so it can be easily used in multithreading applications.

I hope I will be able to write you full solution example this weekend.

Super Vegeta
29-07-2013, 09:11 AM
http://svgames.pl/trash/autotile-explanation.png
Source code of a sample program generating a pseudo-random map and drawing it using the descibed method: http://svgames.pl/trash/autotiles.zip
Uses SDL, SDL_image, OpenGL and Sour (included).

User137
29-07-2013, 11:26 AM
Seems you can save some memory with that technique, but there is a downside. That is performance, for drawing 4 times as many tile-patterns, than you would with full tiles.

In this thread http://www.pascalgamedevelopment.com/showthread.php?15288-2D-tileset-generator&p=88337&viewfull=1#post88337
i ended up with 32 unique tile-fades. It should be enough for most games. But i moved on to shader-based fading...

Darkhog
29-07-2013, 09:30 PM
Thanks, SV. It's too bad you don't use RM anymore ;). Anyway I've decided that I'll just write autotile breaker which would break tiles into all 47 possible graphics. It'll make then tileset made from static tiles. Will give much more flexibility when designing maps at the cost of automatic placement ;). Thing of placing autotiles in RM with shift key.

WILL
31-07-2013, 06:35 PM
I had tried to make a RPG Maker clone for a project of my own many years ago. (using Delphi 5 or 7) I had even made a near exact clone of Dragon Quest 1 (with a reenactment cutscene of the battle taking place at "destroyed the town of Hawkness") with semi-accurate battle stats too. So I got to work with and get a feel for the autotile system. Actually I took at a lot of inspiration from that engine.

Super Vegeta's system is a pretty good one. Covers all cases and is compressed to the point of no overhead of assets. Fading from one tile pattern to the next is a challenge and makes graphics content a bit heavier the number of terrain or pattern combinations.

If you are looking to reduce the number of pre-drawn tiles that you need, you could try using a transparency mask that is designed to fade one tile pattern over another. Essentially you'd be drawing in alpha. Not an easy task, but I'm sure there are tutorials out there. The trick is to make an alpha fade pattern that isn't a linear gradient, but a bit nosier and at the same time seamless with each other alpha fade tile.