Files
godot-------/Script/Map/DoubleMap.cs
m0_75251201 7700703099 初次提交
2025-07-12 11:30:22 +08:00

214 lines
10 KiB
C#

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<Tuple<TileType, TileType, TileType, TileType>, 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<TileType, TileType, TileType, TileType> GetNearTileData(Vector2I coord)
{
return new Tuple<TileType, TileType, TileType, TileType>(
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));
}
}
}