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:
5 tiles placed horizontally: full tile, top & bottom border, left & right border, outside corners, inside corners.
Code:
// 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.
Bookmarks