214 lines
10 KiB
C#
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));
|
|
}
|
|
|
|
}
|
|
|
|
} |