Fix water nukes water depth gradient

This commit is contained in:
FloPinguin
2026-06-18 21:23:25 +02:00
parent 1f20bd21dc
commit d954e357b2
2 changed files with 42 additions and 6 deletions
+38 -5
View File
@@ -167,13 +167,19 @@ func GenerateMap(ctx context.Context, args GeneratorArgs) (MapResult, error) {
removeSmallIslands(ctx, terrain, minIslandSize, args.RemoveSmall)
processWater(ctx, terrain, args.RemoveSmall)
// Water adjacent to impassable terrain should be deep (no depth gradient),
// just like water at the map edge. Override the BFS-calculated magnitude
// so these tiles render as the deepest shade.
setImpassableNeighborWaterDepth(ctx, terrain)
terrain4x := createMiniMap(terrain)
removeSmallIslands(ctx, terrain4x, minIslandSize/2, args.RemoveSmall)
processWater(ctx, terrain4x, false)
setImpassableNeighborWaterDepth(ctx, terrain4x)
terrain16x := createMiniMap(terrain4x)
processWater(ctx, terrain16x, false)
setImpassableNeighborWaterDepth(ctx, terrain16x)
thumb := createMapThumbnail(ctx, terrain4x, 0.5)
webp, err := convertToWebP(ThumbData{
@@ -322,11 +328,11 @@ func processShore(ctx context.Context, terrain [][]Terrain) []Coord {
}
} else if tile.Type == Water {
// Water tile adjacent to land is shoreline
for _, c := range buf[:n] {
if terrain[c.X][c.Y].Type == Land {
tile.Shoreline = true
shorelineWaters = append(shorelineWaters, Coord{X: x, Y: y})
break
for _, c := range buf[:n] {
if terrain[c.X][c.Y].Type == Land {
tile.Shoreline = true
shorelineWaters = append(shorelineWaters, Coord{X: x, Y: y})
break
}
}
}
@@ -386,6 +392,33 @@ func processDistToLand(ctx context.Context, shorelineWaters []Coord, terrain [][
}
}
// setImpassableNeighborWaterDepth forces water tiles adjacent to impassable
// terrain to deep-water magnitude. Without this, the processDistToLand BFS
// assigns them a shallow magnitude (close to "land"), producing a visible
// depth gradient next to impassable terrain. Impassable terrain is void —
// like the map edge — so the water beside it should be uniformly deep.
func setImpassableNeighborWaterDepth(ctx context.Context, terrain [][]Terrain) {
width := len(terrain)
height := len(terrain[0])
const deepMagnitude = 20 // packed as 10 (÷2), matches max render depth
var buf [4]Coord
for x := 0; x < width; x++ {
for y := 0; y < height; y++ {
if terrain[x][y].Type != Water {
continue
}
n := neighborCoords(x, y, width, height, &buf)
for _, c := range buf[:n] {
if terrain[c.X][c.Y].Type == Impassable {
terrain[x][y].Magnitude = deepMagnitude
break
}
}
}
}
}
// neighborCoords fills out with the valid orthogonal neighbours of (x, y) and
// returns the count. out must be a caller-allocated [4]Coord buffer; by
// reusing the same buffer across calls the caller avoids any heap allocation.
+4 -1
View File
@@ -299,6 +299,9 @@ export class WaterManager {
const sMaxY = Math.min(h - 1, cMaxY + MAX_MAG_DIST * 2);
// Seed from coastline water tiles inside the seed box.
// Impassable terrain is void (like the map edge), so water tiles
// adjacent only to impassable terrain are NOT coastline — they should
// be uniformly deep with no depth gradient.
for (let by = sMinY; by <= sMaxY; by++) {
const rowStart = by * w;
for (let bx = sMinX; bx <= sMaxX; bx++) {
@@ -306,7 +309,7 @@ export class WaterManager {
if (!map.isWater(tile) || stampArr[tile] === stamp) continue;
const end = pushNeighbors(tile, nb, 0);
for (let i = 0; i < end; i++) {
if (map.isLand(nb[i])) {
if (map.isLand(nb[i]) && !map.isImpassable(nb[i])) {
stampArr[tile] = stamp;
distArr[tile] = 0;
magQueue.push(tile);