using Godot; using System; using System.Collections.Generic; using System.Numerics; using static Cosmobox.TileType; namespace Cosmobox { public partial class DoubleMap : Node { [Export] TileMapLayer displayLayer; [Export] TileMapLayer mapLayer; PerlinNoise perlinNoise = new(1573); readonly Dictionary, Vector3I> neighboursToAtlasCoord = new() { {new (Grass, Grass, Grass, Grass), new Vector3I(2, 1,0)}, // All corners {new (Dirt, Dirt, Dirt, Grass), new Vector3I(1, 3,0)}, // Outer bottom-right corner {new (Dirt, Dirt, Grass, Dirt), new Vector3I(0, 0,0)}, // Outer bottom-left corner {new (Dirt, Grass, Dirt, Dirt), new Vector3I(0, 2,0)}, // Outer top-right corner {new (Grass, Dirt, Dirt, Dirt), new Vector3I(3, 3,0)}, // Outer top-left corner {new (Dirt, Grass, Dirt, Grass), new Vector3I(1, 0,0)}, // Right edge {new (Grass, Dirt, Grass, Dirt), new Vector3I(3, 2,0)}, // Left edge {new (Dirt, Dirt, Grass, Grass), new Vector3I(3, 0,0)}, // Bottom edge {new (Grass, Grass, Dirt, Dirt), new Vector3I(1, 2,0)}, // Top edge {new (Dirt, Grass, Grass, Grass), new Vector3I(1, 1,0)}, // Inner bottom-right corner {new (Grass, Dirt, Grass, Grass), new Vector3I(2, 0,0)}, // Inner bottom-left corner {new (Grass, Grass, Dirt, Grass), new Vector3I(2, 2,0)}, // Inner top-right corner {new (Grass, Grass, Grass, Dirt), new Vector3I(3, 1,0)}, // Inner top-left corner {new (Dirt, Grass, Grass, Dirt), new Vector3I(2, 3,0)}, // Bottom-left top-right corners {new (Grass, Dirt, Dirt, Grass), new Vector3I(0, 1,0)}, // Top-left down-right corners {new (Dirt, Dirt, Dirt, Dirt), new Vector3I(0, 3,0)}, // No corners // {new (Grass, Grass, Grass, Grass), new Vector3I(2, 1,1)}, // All corners {new (Water, Water, Water, Grass), new Vector3I(1, 3,1)}, // Outer bottom-right corner {new (Water, Water, Grass, Water), new Vector3I(0, 0,1)}, // Outer bottom-left corner {new (Water, Grass, Water, Water), new Vector3I(0, 2,1)}, // Outer top-right corner {new (Grass, Water, Water, Water), new Vector3I(3, 3,1)}, // Outer top-left corner {new (Water, Grass, Water, Grass), new Vector3I(1, 0,1)}, // Right edge {new (Grass, Water, Grass, Water), new Vector3I(3, 2,1)}, // Left edge {new (Water, Water, Grass, Grass), new Vector3I(3, 0,1)}, // Bottom edge {new (Grass, Grass, Water, Water), new Vector3I(1, 2,1)}, // Top edge {new (Water, Grass, Grass, Grass), new Vector3I(1, 1,1)}, // Inner bottom-right corner {new (Grass, Water, Grass, Grass), new Vector3I(2, 0,1)}, // Inner bottom-left corner {new (Grass, Grass, Water, Grass), new Vector3I(2, 2,1)}, // Inner top-right corner {new (Grass, Grass, Grass, Water), new Vector3I(3, 1,1)}, // Inner top-left corner {new (Water, Grass, Grass, Water), new Vector3I(2, 3,1)}, // Bottom-left top-right corners {new (Grass, Water, Water, Grass), new Vector3I(0, 1,1)}, // Top-left down-right corners {new (Water, Water, Water, Water), new Vector3I(0, 3,1)}, // No corners // {new (Dirt, Dirt, Dirt, Dirt), new Vector3I(2, 1,2)}, // All corners {new (Water, Water, Water, Dirt), new Vector3I(1, 3,2)}, // Outer bottom-right corner {new (Water, Water, Dirt, Water), new Vector3I(0, 0,2)}, // Outer bottom-left corner {new (Water, Dirt, Water, Water), new Vector3I(0, 2,2)}, // Outer top-right corner {new (Dirt, Water, Water, Water), new Vector3I(3, 3,2)}, // Outer top-left corner {new (Water, Dirt, Water, Dirt), new Vector3I(1, 0,2)}, // Right edge {new (Dirt, Water, Dirt, Water), new Vector3I(3, 2,2)}, // Left edge {new (Water, Water, Dirt, Dirt), new Vector3I(3, 0,2)}, // Bottom edge {new (Dirt, Dirt, Water, Water), new Vector3I(1, 2,2)}, // Top edge {new (Water, Dirt, Dirt, Dirt), new Vector3I(1, 1,2)}, // Inner bottom-right corner {new (Dirt, Water, Dirt, Dirt), new Vector3I(2, 0,2)}, // Inner bottom-left corner {new (Dirt, Dirt, Water, Dirt), new Vector3I(2, 2,2)}, // Inner top-right corner {new (Dirt, Dirt, Dirt, Water), new Vector3I(3, 1,2)}, // Inner top-left corner {new (Water, Dirt, Dirt, Water), new Vector3I(2, 3,2)}, // Bottom-left top-right corners {new (Dirt, Water, Water, Dirt), new Vector3I(0, 1,2)}, // Top-left down-right corners { new (Grass, Dirt, Water, Grass), new Vector3I(0, 0,3)}, { new (Dirt, Water, Grass, Grass), new Vector3I(1, 0,3)}, { new (Water, Dirt, Grass, Grass), new Vector3I(2, 0,3)}, { new (Dirt, Grass, Grass, Water), new Vector3I(3, 0,3)}, { new (Grass, Water, Grass, Dirt), new Vector3I(3, 1,3)}, { new (Grass, Dirt, Grass, Water), new Vector3I(3, 2,3)}, { new (Grass, Water, Dirt, Grass), new Vector3I(3, 3,3)}, { new (Grass, Grass, Water, Dirt), new Vector3I(2, 3,3)}, { new (Grass, Grass, Dirt, Water), new Vector3I(1, 3,3)}, { new (Water, Grass, Grass, Dirt), new Vector3I(0, 3,3)}, { new (Dirt, Grass, Water, Grass), new Vector3I(0, 2,3)}, { new (Water, Grass, Dirt, Grass), new Vector3I(0, 1,3)}, { new (Dirt, Grass, Water, Dirt), new Vector3I(0, 0,4)}, { new (Grass, Water, Dirt, Dirt), new Vector3I(1, 0,4)}, { new (Water, Grass, Dirt, Dirt), new Vector3I(2, 0,4)}, { new (Grass, Dirt, Dirt, Water), new Vector3I(3, 0,4)}, { new (Dirt, Water, Dirt, Grass), new Vector3I(3, 1,4)}, { new (Dirt, Grass, Dirt, Water), new Vector3I(3, 2,4)}, { new (Dirt, Water, Grass, Dirt), new Vector3I(3, 3,4)}, { new (Dirt, Dirt, Water, Grass), new Vector3I(2, 3,4)}, { new (Dirt, Dirt, Grass, Water), new Vector3I(1, 3,4)}, { new (Water, Dirt, Dirt, Grass), new Vector3I(0, 3,4)}, { new (Grass, Dirt, Water, Dirt), new Vector3I(0, 2,4)}, { new (Water, Dirt, Grass, Dirt), new Vector3I(0, 1,4)}, { new (Water, Grass, Dirt, Water), new Vector3I(0, 0,5)}, { new (Grass, Dirt, Water, Water), new Vector3I(1, 0,5)}, { new (Dirt, Grass, Water, Water), new Vector3I(2, 0,5)}, { new (Grass, Water, Water, Dirt), new Vector3I(3, 0,5)}, { new (Water, Dirt, Water, Grass), new Vector3I(3, 1,5)}, { new (Water, Grass, Water, Dirt), new Vector3I(3, 2,5)}, { new (Water, Dirt, Grass, Water), new Vector3I(3, 3,5)}, { new (Water, Water, Dirt, Grass), new Vector3I(2, 3,5)}, { new (Water, Water, Grass, Dirt), new Vector3I(1, 3,5)}, { new (Dirt, Water, Water, Grass), new Vector3I(0, 3,5)}, { new (Grass, Water, Dirt, Water), new Vector3I(0, 2,5)}, { new (Dirt, Water, Grass, Water), new Vector3I(0, 1,5)}, }; private static readonly Vector2I[] _shifts = [ new(0, 0), new(1, 0), new(0, 1), new(1, 1) ]; public override void _Ready() { int wide = 100; float scale = 0.1f; // 缩放因子 for (int i = 0; i < wide; i++) { for (int j = 0; j < wide; j++) { // 获取噪声值并归一化到 [0, 1] var noiseValue = perlinNoise.Noise(i * scale, j * scale, 0); var val = (noiseValue + 1) / 2; // 根据噪声值设置地形类型 if (val > 0.3) { mapLayer.SetCell(new Vector2I(i, j), 0, TileTypeToAtlasCoord(Grass)); } else if (val > 0.25) { mapLayer.SetCell(new Vector2I(i, j), 0, TileTypeToAtlasCoord(Dirt)); } else { mapLayer.SetCell(new Vector2I(i, j), 0, TileTypeToAtlasCoord(Water)); } } } UpdateDisplay(); } public void UpdateDisplay() { var tilePos = mapLayer.GetUsedCells(); foreach (var pos in tilePos) { UpdateDisplay(pos); // UpdateDisplay(pos - new Vector2I(1, 0)); // UpdateDisplay(pos - new Vector2I(1, 1)); // UpdateDisplay(pos - new Vector2I(0, 1)); } } public void UpdateDisplay(Vector2I coord) { var key = GetNearTileData(coord); if (neighboursToAtlasCoord.TryGetValue(key, out Vector3I atlasCoord)) { displayLayer.SetCell(coord, atlasCoord[2], new(atlasCoord[0], atlasCoord[1])); } else { displayLayer.SetCell(coord, 1, new(0, 3)); } } public TileType GetTileType(Vector2I pos) { var cell = mapLayer.GetCellAtlasCoords(pos); return AtlasCoordToTileType(cell); } public static TileType AtlasCoordToTileType(Vector2I coord) { return coord switch { Vector2I(0, 0) => Grass, Vector2I(1, 0) => Dirt, Vector2I(2, 0) => Water, _ => Water, }; } public static Vector2I TileTypeToAtlasCoord(TileType tileType) { return tileType switch { Grass => new(0, 0), Dirt => new(1, 0), Water => new(2, 0), _ => new(0, 0), }; } public Tuple GetNearTileData(Vector2I coord) { return new Tuple( GetTileType(coord + _shifts[0]), GetTileType(coord + _shifts[1]), GetTileType(coord + _shifts[2]), GetTileType(coord + _shifts[3]) ); } public void SetTile(Vector2I pos, TileType tileType) { mapLayer.SetCell(pos, 0, TileTypeToAtlasCoord(tileType)); } } }