Ich bin hierher gekommen, indem ich dieses Problem selbst gegoogelt, die verlinkten Artikel gelesen und eine relativ kompakte Lösung erstellt habe, die den gemeinsamen Satz von 47 Kacheln generiert. Für das automatisch gekachelte Material ist ein 2x3-Kachelsatz erforderlich:
Mit einer Einzelkachelvariante oben links, inneren Ecken oben rechts und vier äußeren Eckkacheln unten (Sie können diese Anordnung von RPG Maker erkennen).
Der Trick besteht darin, jede "logische" Kartenkachel zum Rendern in 4 Halbkacheln zu unterteilen. Darüber hinaus kann sich eine halbe Kachel im Kachelsatz nur in dieser Position in einer generierten Kachel befinden, sodass eine obere linke halbe Kachel nur in einer Position oben links verwendet werden kann.
Diese Einschränkungen bedeuten, dass Sie nur 3 Vollkachelnachbarn pro Halbkachel anstelle aller 8 benachbarten Kacheln überprüfen müssen.
Ich habe diese Idee schnell umgesetzt, um sie zu testen. Hier ist der Proof-of-Concept-Code (TypeScript):
//const dirs = { N: 1, E: 2, S: 4, W:8, NE: 16, SE: 32, SW: 64, NW: 128 };
const edges = { A: 1+8+128, B: 1+2+16, C: 4+8+64, D: 4+2+32 };
const mapA = { 0:8, 128:8, 1:16, 8:10, 9:2, 137:18, 136:10, 129:16 };
const mapB = { 0:11, 16:11, 1:19, 2:9, 3:3, 19:17, 18:9, 17:19 };
const mapC = { 0:20, 64:20, 4:12, 8:22, 12:6, 76:14, 72:22, 68:12 };
const mapD = { 0:23, 32:23, 4:15, 2:21, 6:7, 38:13, 34:21, 36:15 };
export function GenerateAutotileMap(_map: number[][], _tile: integer): number[][]
{
var result = [];
for (var y=0; y < _map.length; y++) {
const row = _map[y];
const Y = y*2;
// half-tiles
result[Y] = [];
result[Y+1] = [];
// each row
for (var x=0; x < row.length; x++) {
// get the tile
const t = row[x];
const X = x*2;
if (t != _tile) continue;
// Check nearby tile materials.
const neighbors = (North(_map, x, y) == t? 1:0)
+ (East(_map, x, y) == t? 2:0)
+ (South(_map, x, y) == t? 4:0)
+ (West(_map, x, y) == t? 8:0)
+ (NorthEast(_map, x, y) == t? 16:0)
+ (SouthEast(_map, x, y) == t? 32:0)
+ (SouthWest(_map, x, y) == t? 64:0)
+ (NorthWest(_map, x, y) == t? 128:0);
// Isolated tile
if (neighbors == 0) {
result[Y][X] = 0;
result[Y][X+1] = 1;
result[Y+1][X] = 4;
result[Y+1][X+1] = 5;
continue;
}
// Find half-tiles.
result[Y][X] = mapA[neighbors & edges.A];
result[Y][X+1] = mapB[neighbors & edges.B];
result[Y+1][X] = mapC[neighbors & edges.C];
result[Y+1][X+1] = mapD[neighbors & edges.D];
}
}
return result;
}
Erläuterung:
A
ist der obere linke Teil der Kachel, B
ist der obere rechte Teil, C
ist der untere linke Teil, D
ist der untere rechte Teil.
edges
enthält Bitmasken für jede dieser Informationen, sodass wir nur die relevanten Nachbarinformationen abrufen können.
map*
sind Wörterbücher, die Nachbarzustände grafischen Indizes im Kachelsatzbild (0..24) zuordnen.
- Da jede halbe Kachel 3 Nachbarn prüft, hat jede 2 ^ 3 = 8 Zustände.
_tile
ist die Kachel, die für das Autotiling bestimmt ist.
- Da unsere logischen Kacheln doppelt so groß sind wie unsere Rendering-Kacheln, müssen alle Autotile-Koordinaten (x, y) in der Rendering-Map verdoppelt werden.
Wie auch immer, hier sind die Ergebnisse (jedenfalls mit nur einer Kachel):