fix: correct dirt autotile direction and simplify edge logic

Dirt tiles (dirt-on-transparent) must be applied to DIRT tiles checking
for non-dirt neighbors, not to GRASS tiles. The previous approach had
dirt edges facing the wrong direction because the dirt island's edges
point inward from the center, not outward from the grass.

Water edges (watergrass = grass-on-water) remain applied to GRASS tiles
since the grass portion aligns correctly with the base grass layer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
root
2026-03-07 23:50:07 +00:00
parent 17621fbd59
commit f1f79ed765
+54 -31
View File
@@ -163,34 +163,59 @@ export class GameScene extends Phaser.Scene {
return terrain[y * worldWidth + x];
};
// For a GRASS tile, pick the watergrass/dirt transition tile based on
// which neighbors are the "other" terrain type.
// The LPC edge tiles are drawn FROM the grass perspective (grass is the terrain,
// water/dirt is the background bleeding through at edges).
const pickEdgeTile = (x: number, y: number, otherTerrain: number): number => {
const isOther = (dx: number, dy: number) => getTerr(x + dx, y + dy) === otherTerrain;
const n = isOther(0, -1), s = isOther(0, 1), w = isOther(-1, 0), e = isOther(1, 0);
const nw = isOther(-1, -1), ne = isOther(1, -1), sw = isOther(-1, 1), se = isOther(1, 1);
// Pick autotile for a GRASS tile in the watergrass layer.
// watergrass.png = grass-on-water: edge tiles show grass with water bleeding through.
// Applied to GRASS tiles, checking which neighbors are WATER.
const pickWaterEdge = (x: number, y: number): number => {
const isW = (dx: number, dy: number) => getTerr(x + dx, y + dy) === Terrain.WATER;
const n = isW(0, -1), s = isW(0, 1), w = isW(-1, 0), e = isW(1, 0);
const nw = isW(-1, -1), ne = isW(1, -1), sw = isW(-1, 1), se = isW(1, 1);
// Outer corners (two cardinal sides are the other terrain)
if (n && w) return 6; // outer-NW: grass only in SE, other terrain in NW
if (n && e) return 8; // outer-NE
if (s && w) return 12; // outer-SW
if (s && e) return 14; // outer-SE
// Edges (one cardinal side is the other terrain)
if (n) return 7; // N-edge: other terrain bleeds from north
if (s) return 13; // S-edge
if (w) return 9; // W-edge
if (e) return 11; // E-edge
// Inner corners (all cardinal = grass, but a diagonal is the other terrain)
if (se) return 0; // inner-SE: other terrain peeks in SE corner
if (sw) return 1; // inner-SW
if (ne) return 3; // inner-NE
if (nw) return 4; // inner-NW
// No adjacent other-terrain at all
// Outer corners (two cardinal sides are water)
if (n && w) return 6;
if (n && e) return 8;
if (s && w) return 12;
if (s && e) return 14;
// Edges (one cardinal side is water)
if (n) return 7;
if (s) return 13;
if (w) return 9;
if (e) return 11;
// Inner corners (diagonal-only water) — small water notch in grass
if (se) return 0;
if (sw) return 1;
if (ne) return 3;
if (nw) return 4;
return -1;
};
// Pick autotile for a DIRT tile in the dirt layer.
// dirt.png = dirt-on-transparent: edge tiles show dirt with transparent edges.
// Applied to DIRT tiles, checking which neighbors are NOT dirt.
const pickDirtEdge = (x: number, y: number): number => {
const notDirt = (dx: number, dy: number) => getTerr(x + dx, y + dy) !== Terrain.DIRT;
const n = notDirt(0, -1), s = notDirt(0, 1), w = notDirt(-1, 0), e = notDirt(1, 0);
const nw = notDirt(-1, -1), ne = notDirt(1, -1), sw = notDirt(-1, 1), se = notDirt(1, 1);
// Outer corners (two sides are not-dirt → this dirt tile is at a corner of the dirt body)
if (n && w) return 6;
if (n && e) return 8;
if (s && w) return 12;
if (s && e) return 14;
// Edges
if (n) return 7;
if (s) return 13;
if (w) return 9;
if (e) return 11;
// Inner corners (diagonal-only grass → small transparent notch in dirt)
if (se) return 0;
if (sw) return 1;
if (ne) return 3;
if (nw) return 4;
// Fully surrounded by dirt
return FILL;
};
// Build tile data arrays for each layer
const grassData: number[][] = []; // base: solid grass everywhere
const waterData: number[][] = []; // watergrass transitions + solid water
@@ -209,20 +234,18 @@ export class GameScene extends Phaser.Scene {
// Base: always solid grass
grassRow.push(FILL);
// Water layer
// Water layer: watergrass edges on GRASS tiles, solid fill on WATER tiles
if (t === Terrain.WATER) {
waterRow.push(FILL); // solid water
waterRow.push(FILL);
} else if (t === Terrain.GRASS) {
waterRow.push(pickEdgeTile(x, y, Terrain.WATER));
waterRow.push(pickWaterEdge(x, y));
} else {
waterRow.push(-1);
}
// Dirt layer
// Dirt layer: dirt edges on DIRT tiles (checking for non-dirt neighbors)
if (t === Terrain.DIRT) {
dirtRow.push(FILL); // solid dirt
} else if (t === Terrain.GRASS) {
dirtRow.push(pickEdgeTile(x, y, Terrain.DIRT));
dirtRow.push(pickDirtEdge(x, y));
} else {
dirtRow.push(-1);
}