using System.Collections.Generic; using System.Text.Json.Serialization; using Godot; using static TerrainPeering; /// <summary> /// 地形配置数据, 数据都为 int 数组, 下标0和1分别代表x和y, 单位: 像素 /// </summary> public class TileSetTerrainInfo : IClone<TileSetTerrainInfo> { public const byte TerrainLayerType = 1; public const byte MiddleLayerType = 2; public const byte FloorLayerType = 3; /// <summary> /// 地形名称 /// </summary> [JsonInclude] public string Name; //type = 3 /// <summary> /// 地板 (1块) type = 3 /// </summary> [JsonInclude] public Dictionary<uint, int[]> F; /// <summary> /// 侧方墙壁 (4块) type = 2 /// </summary> [JsonInclude] public Dictionary<uint, int[]> M; /// <summary> /// 自动平铺地形 (47块/13块) type = 1 /// </summary> [JsonInclude] public Dictionary<uint, int[]> T; /// <summary> /// 地形类型, 0: 3x3地形, 1: 2x2地形 /// </summary> [JsonInclude] public byte TerrainType; public void InitData() { TerrainType = 0; F = new Dictionary<uint, int[]>(); M = new Dictionary<uint, int[]>(); T = new Dictionary<uint, int[]>(); } public TileSetTerrainInfo Clone() { var terrainInfo = new TileSetTerrainInfo(); terrainInfo.InitData(); terrainInfo.Name = Name; foreach (var pair in T) { terrainInfo.T.Add(pair.Key, new []{ pair.Value[0], pair.Value[1] }); } foreach (var pair in M) { terrainInfo.M.Add(pair.Key, new []{ pair.Value[0], pair.Value[1] }); } foreach (var pair in F) { terrainInfo.F.Add(pair.Key, new []{ pair.Value[0], pair.Value[1] }); } terrainInfo.TerrainType = TerrainType; return terrainInfo; } /// <summary> /// 返回这个TileSet地形是否可以正常使用了 /// </summary> /// <returns></returns> public bool CanUse() { if (TerrainType == 0) { if (T == null || T.Count != 47) { return false; } } else { if (T == null || T.Count != 13) { return false; } } return M != null && M.Count == 4 && F != null && F.Count == 1; } /// <summary> /// 将存储的坐标数据转换成 Vector2I 对象, 返回的 Vector2I 单位: 格 /// </summary> public Vector2I GetPosition(int[] ints) { return new Vector2I(ints[0] / GameConfig.TileCellSize, ints[1] / GameConfig.TileCellSize); } /// <summary> /// 将地形掩码中的坐标转换为索引。 /// </summary> /// <param name="bitCoords">地形坐标</param> /// <param name="type">地形类型</param> public int TerrainCoordsToIndex(Vector2I bitCoords, byte type) { if (type == TerrainLayerType) { return bitCoords.Y * GameConfig.TerrainBit3x3.X + bitCoords.X; } else if (type == MiddleLayerType) { return bitCoords.Y * GameConfig.TerrainBitMiddle.X + bitCoords.X; } else if (type == FloorLayerType) { return bitCoords.Y * GameConfig.TerrainBitFloor.X + bitCoords.X; } return -1; } /// <summary> /// 将地掩码值转换为索引值 /// </summary> /// <param name="bit">地形掩码值</param> /// <param name="type">地形类型</param> public int TerrainBitToIndex(uint bit, byte type) { if (type == TerrainLayerType) //顶部墙壁 { if (TerrainType == 0) //47格 { switch (bit) { case Center | Bottom: return 0; case Center | Right | Bottom: return 1; case Left | Center | Right | Bottom: return 2; case Left | Center | Bottom: return 3; case LeftTop | Top | Left | Center | Right | Bottom: return 4; case Left | Center | Right | Bottom | RightBottom: return 5; case Left | Center | Right | LeftBottom | Bottom: return 6; case Top | RightTop | Left | Center | Right | Bottom: return 7; case Center | Right | Bottom | RightBottom: return 8; case Top | Left | Center | Right | LeftBottom | Bottom | RightBottom: return 9; case Left | Center | Right | LeftBottom | Bottom | RightBottom: return 10; case Left | Center | LeftBottom | Bottom: return 11; case Top | Center | Bottom: return 12; case Top | Center | Right | Bottom: return 13; case Top | Left | Center | Right | Bottom: return 14; case Top | Left | Center | Bottom: return 15; case Top | Center | Right | Bottom | RightBottom: return 16; case Top | RightTop | Left | Center | Right | LeftBottom | Bottom | RightBottom: return 17; case LeftTop | Top | Left | Center | Right | LeftBottom | Bottom | RightBottom: return 18; case Top | Left | Center | LeftBottom | Bottom: return 19; case Top | RightTop | Center | Right | Bottom | RightBottom: return 20; case Top | RightTop | Left | Center | Right | LeftBottom | Bottom: return 21; case LeftTop | Top | Left | Center | Right | LeftBottom | Bottom: return 23; case Top | Center: return 24; case Top | Center | Right: return 25; case Top | Left | Center | Right: return 26; case Top | Left | Center: return 27; case Top | RightTop | Center | Right | Bottom: return 28; case LeftTop | Top | RightTop | Left | Center | Right | Bottom | RightBottom: return 29; case LeftTop | Top | RightTop | Left | Center | Right | LeftBottom | Bottom: return 30; case LeftTop | Top | Left | Center | Bottom: return 31; case Top | RightTop | Left | Center | Right | Bottom | RightBottom: return 32; case LeftTop | Top | RightTop | Left | Center | Right | LeftBottom | Bottom | RightBottom: return 33; case LeftTop | Top | Left | Center | Right | Bottom | RightBottom: return 34; case LeftTop | Top | Left | Center | LeftBottom | Bottom: return 35; case Center: return 36; case Center | Right: return 37; case Left | Center | Right: return 38; case Left | Center: return 39; case Top | Left | Center | Right | LeftBottom | Bottom: return 40; case Top | RightTop | Left | Center | Right: return 41; case LeftTop | Top | Left | Center | Right: return 42; case Top | Left | Center | Right | Bottom | RightBottom: return 43; case Top | RightTop | Center | Right: return 44; case LeftTop | Top | RightTop | Left | Center | Right: return 45; case LeftTop | Top | RightTop | Left | Center | Right | Bottom: return 46; case LeftTop | Top | Left | Center: return 47; } } else if (TerrainType == 1) //13格 { switch (bit) { //第一排 case Center | RightBottom: return 0; case Center | RightBottom | LeftBottom: return 1; case Center | LeftBottom: return 2; case Center | LeftTop | RightTop | LeftBottom: return 3; case Center | LeftTop | RightTop | RightBottom: return 4; //第二排 case Center | RightTop | RightBottom: return 5; case Center | LeftTop | LeftBottom | RightTop | RightBottom: return 6; case Center | LeftTop | LeftBottom: return 7; case Center | LeftTop | LeftBottom | RightBottom: return 8; case Center | RightTop | LeftBottom | RightBottom: return 9; //第三排 case Center | RightTop: return 10; case Center | LeftTop | RightTop: return 11; case Center | LeftTop: return 12; } } } else if (type == MiddleLayerType) { if (bit < 4) { return (int)bit; } } else if (type == FloorLayerType) { if (bit == 0) { return 0; } } return -1; } /// <summary> /// 根据给定的索引和类型计算地形掩码值。 /// </summary> /// <param name="index">用于确定地形掩码的索引。</param> /// <param name="type">要计算地形位值的图层类型。</param> /// <returns></returns> public uint IndexToTerrainBit(int index, byte type) { if (type == TerrainLayerType) //顶部墙壁 { if (TerrainType == 0) //47格 { switch (index) { case 0: return Center | Bottom; case 1: return Center | Right | Bottom; case 2: return Left | Center | Right | Bottom; case 3: return Left | Center | Bottom; case 4: return LeftTop | Top | Left | Center | Right | Bottom; case 5: return Left | Center | Right | Bottom | RightBottom; case 6: return Left | Center | Right | LeftBottom | Bottom; case 7: return Top | RightTop | Left | Center | Right | Bottom; case 8: return Center | Right | Bottom | RightBottom; case 9: return Top | Left | Center | Right | LeftBottom | Bottom | RightBottom; case 10: return Left | Center | Right | LeftBottom | Bottom | RightBottom; case 11: return Left | Center | LeftBottom | Bottom; case 12: return Top | Center | Bottom; case 13: return Top | Center | Right | Bottom; case 14: return Top | Left | Center | Right | Bottom; case 15: return Top | Left | Center | Bottom; case 16: return Top | Center | Right | Bottom | RightBottom; case 17: return Top | RightTop | Left | Center | Right | LeftBottom | Bottom | RightBottom; case 18: return LeftTop | Top | Left | Center | Right | LeftBottom | Bottom | RightBottom; case 19: return Top | Left | Center | LeftBottom | Bottom; case 20: return Top | RightTop | Center | Right | Bottom | RightBottom; case 21: return Top | RightTop | Left | Center | Right | LeftBottom | Bottom; case 23: return LeftTop | Top | Left | Center | Right | LeftBottom | Bottom; case 24: return Top | Center; case 25: return Top | Center | Right; case 26: return Top | Left | Center | Right; case 27: return Top | Left | Center; case 28: return Top | RightTop | Center | Right | Bottom; case 29: return LeftTop | Top | RightTop | Left | Center | Right | Bottom | RightBottom; case 30: return LeftTop | Top | RightTop | Left | Center | Right | LeftBottom | Bottom; case 31: return LeftTop | Top | Left | Center | Bottom; case 32: return Top | RightTop | Left | Center | Right | Bottom | RightBottom; case 33: return LeftTop | Top | RightTop | Left | Center | Right | LeftBottom | Bottom | RightBottom; case 34: return LeftTop | Top | Left | Center | Right | Bottom | RightBottom; case 35: return LeftTop | Top | Left | Center | LeftBottom | Bottom; case 36: return Center; case 37: return Center | Right; case 38: return Left | Center | Right; case 39: return Left | Center; case 40: return Top | Left | Center | Right | LeftBottom | Bottom; case 41: return Top | RightTop | Left | Center | Right; case 42: return LeftTop | Top | Left | Center | Right; case 43: return Top | Left | Center | Right | Bottom | RightBottom; case 44: return Top | RightTop | Center | Right; case 45: return LeftTop | Top | RightTop | Left | Center | Right; case 46: return LeftTop | Top | RightTop | Left | Center | Right | Bottom; case 47: return LeftTop | Top | Left | Center; } } else if (TerrainType == 1) //13格 { switch (index) { //第一排 case 0: return Center | RightBottom; case 1: return Center | RightBottom | LeftBottom; case 2: return Center | LeftBottom; case 3: return Center | LeftTop | RightTop | LeftBottom; case 4: return Center | LeftTop | RightTop | RightBottom; //第二排 case 5: return Center | RightTop | RightBottom; case 6: return Center | LeftTop | LeftBottom | RightTop | RightBottom; case 7: return Center | LeftTop | LeftBottom; case 8: return Center | LeftTop | LeftBottom | RightBottom; case 9: return Center | RightTop | LeftBottom | RightBottom; //第三排 case 10: return Center | RightTop; case 11: return Center | LeftTop | RightTop; case 12: return Center | LeftTop; } } } else if (type == MiddleLayerType) { if (index >= 0 && index < 4) { return (uint)index; } } return None; } /// <summary> /// 将地形掩码存入 TileSetTerrainInfo 中 /// </summary> public void SetTerrainCell(int index, byte type, int[] cellData) { if (type == TerrainLayerType) //顶部墙壁 { var terrainBit = IndexToTerrainBit(index, type); if (terrainBit != None) { T[terrainBit] = cellData; } } else if (type == MiddleLayerType) //侧方墙壁 { switch (index) { case 0: M[0] = cellData; break; case 1: M[1] = cellData; break; case 2: M[2] = cellData; break; case 3: M[3] = cellData; break; } } else if (type == FloorLayerType) //地板 { F[0] = cellData; } } /// <summary> /// 移除地形掩码 /// </summary> public void RemoveTerrainCell(int index, byte type) { if (type == TerrainLayerType) //顶部墙壁 { var terrainBit = IndexToTerrainBit(index, type); if (terrainBit != None) { T.Remove(terrainBit); } } else if (type == MiddleLayerType) //侧方墙壁 { switch (index) { case 0: M.Remove(0); break; case 1: M.Remove(1); break; case 2: M.Remove(2); break; case 3: M.Remove(3); break; } } else if (type == FloorLayerType) //地板 { F.Remove(0); } } /// <summary> /// 获取指定索引的地形掩码存储的数据 /// </summary> public int[] GetTerrainCell(int index, byte type) { if (type == TerrainLayerType) //顶部墙壁 { var terrainBit = IndexToTerrainBit(index, type); if (terrainBit != None) { if (T.TryGetValue(terrainBit, out var cellData)) { return cellData; } } } else if (type == MiddleLayerType) //侧方墙壁 { switch (index) { case 0: { if (M.TryGetValue(0, out var cellData)) return cellData; } break; case 1: { if (M.TryGetValue(1, out var cellData)) return cellData; } break; case 2: { if (M.TryGetValue(2, out var cellData)) return cellData; } break; case 3: { if (M.TryGetValue(3, out var cellData)) return cellData; } break; } } else if (type == FloorLayerType) //地板 { if (F.TryGetValue(0, out var cellData)) return cellData; } return null; } }