Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / map / serialize / tileSet / TileSetTerrainInfo.cs
@小李xl 小李xl on 9 Jan 2024 20 KB 存储和读取房间Tile数据
  1.  
  2. using System.Collections.Generic;
  3. using System.Text.Json.Serialization;
  4. using Godot;
  5.  
  6. /// <summary>
  7. /// 地形配置数据, 数据都为 int 数组, 下标0和1分别代表x和y, 单位: 像素
  8. /// </summary>
  9. public class TileSetTerrainInfo : IClone<TileSetTerrainInfo>
  10. {
  11. public const byte FloorLayerType = 3;
  12. public const byte MiddleLayerType = 2;
  13. public const byte TopLayerType = 1;
  14. //type = 3
  15. /// <summary>
  16. /// 地板 (1块) type = 3
  17. /// </summary>
  18. [JsonInclude] public Dictionary<uint, int[]> F;
  19.  
  20. /// <summary>
  21. /// 侧方墙壁 (4块) type = 2
  22. /// </summary>
  23. [JsonInclude] public Dictionary<uint, int[]> M;
  24. /// <summary>
  25. /// 顶部墙壁47格 (47块) type = 1
  26. /// </summary>
  27. [JsonInclude] public Dictionary<uint, int[]> T;
  28.  
  29. public void InitData()
  30. {
  31. T = new Dictionary<uint, int[]>();
  32. M = new Dictionary<uint, int[]>();
  33. F = new Dictionary<uint, int[]>();
  34. }
  35.  
  36. public TileSetTerrainInfo Clone()
  37. {
  38. var terrainInfo = new TileSetTerrainInfo();
  39. terrainInfo.InitData();
  40. foreach (var pair in T)
  41. {
  42. terrainInfo.T.Add(pair.Key, new []{ pair.Value[0], pair.Value[1] });
  43. }
  44. foreach (var pair in M)
  45. {
  46. terrainInfo.M.Add(pair.Key, new []{ pair.Value[0], pair.Value[1] });
  47. }
  48. foreach (var pair in F)
  49. {
  50. terrainInfo.F.Add(pair.Key, new []{ pair.Value[0], pair.Value[1] });
  51. }
  52. return terrainInfo;
  53. }
  54. /// <summary>
  55. /// 返回这个TileSet地形是否可以正常使用了
  56. /// </summary>
  57. /// <returns></returns>
  58. public bool CanUse()
  59. {
  60. return T != null && T.Count == 47 && M != null && M.Count == 4 && F != null && F.Count == 1;
  61. }
  62.  
  63. /// <summary>
  64. /// 将存储的坐标数据转换成 Vector2I 对象, 返回的 Vector2I 单位: 格
  65. /// </summary>
  66. public Vector2I GetPosition(int[] ints)
  67. {
  68. return new Vector2I(ints[0] / GameConfig.TileCellSize, ints[1] / GameConfig.TileCellSize);
  69. }
  70. /// <summary>
  71. /// 将地形掩码中的坐标转换为索引。
  72. /// </summary>
  73. /// <param name="bitCoords">地形坐标</param>
  74. /// <param name="type">地形类型</param>
  75. public int TerrainCoordsToIndex(Vector2I bitCoords, byte type)
  76. {
  77. if (type == 1)
  78. {
  79. return bitCoords.Y * GameConfig.TerrainBitSize1.X + bitCoords.X;
  80. }
  81. else if (type == 2)
  82. {
  83. return bitCoords.Y * GameConfig.TerrainBitSize2.X + bitCoords.X;
  84. }
  85. else if (type == 3)
  86. {
  87. return bitCoords.Y * GameConfig.TerrainBitSize3.X + bitCoords.X;
  88. }
  89.  
  90. return -1;
  91. }
  92.  
  93. /// <summary>
  94. /// 将地掩码值转换为索引值
  95. /// </summary>
  96. /// <param name="bit">地形掩码值</param>
  97. /// <param name="type">地形类型</param>
  98. public int TerrainBitToIndex(uint bit, byte type)
  99. {
  100. if (type == TopLayerType) //顶部墙壁
  101. {
  102. switch (bit)
  103. {
  104. case TerrainPeering.Center | TerrainPeering.Bottom: return 0;
  105. case TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom: return 1;
  106. case TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom: return 2;
  107. case TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Bottom: return 3;
  108. case TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom: return 4;
  109. case TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom | TerrainPeering.RightBottom: return 5;
  110. case TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom: return 6;
  111. case TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom: return 7;
  112. case TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom | TerrainPeering.RightBottom: return 8;
  113. case TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom | TerrainPeering.RightBottom: return 9;
  114. case TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom | TerrainPeering.RightBottom: return 10;
  115. case TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.LeftBottom | TerrainPeering.Bottom: return 11;
  116. case TerrainPeering.Top | TerrainPeering.Center | TerrainPeering.Bottom: return 12;
  117. case TerrainPeering.Top | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom: return 13;
  118. case TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom: return 14;
  119. case TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Bottom: return 15;
  120. case TerrainPeering.Top | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom | TerrainPeering.RightBottom: return 16;
  121. case TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom | TerrainPeering.RightBottom: return 17;
  122. case TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom | TerrainPeering.RightBottom: return 18;
  123. case TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.LeftBottom | TerrainPeering.Bottom: return 19;
  124. case TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom | TerrainPeering.RightBottom: return 20;
  125. case TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom: return 21;
  126. case TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom: return 23;
  127. case TerrainPeering.Top | TerrainPeering.Center: return 24;
  128. case TerrainPeering.Top | TerrainPeering.Center | TerrainPeering.Right: return 25;
  129. case TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right: return 26;
  130. case TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center: return 27;
  131. case TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom: return 28;
  132. case TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom | TerrainPeering.RightBottom: return 29;
  133. case TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom: return 30;
  134. case TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Bottom: return 31;
  135. case TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom | TerrainPeering.RightBottom: return 32;
  136. case TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom | TerrainPeering.RightBottom: return 33;
  137. case TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom | TerrainPeering.RightBottom: return 34;
  138. case TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.LeftBottom | TerrainPeering.Bottom: return 35;
  139. case TerrainPeering.Center: return 36;
  140. case TerrainPeering.Center | TerrainPeering.Right: return 37;
  141. case TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right: return 38;
  142. case TerrainPeering.Left | TerrainPeering.Center: return 39;
  143. case TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom: return 40;
  144. case TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right: return 41;
  145. case TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right: return 42;
  146. case TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom | TerrainPeering.RightBottom: return 43;
  147. case TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Center | TerrainPeering.Right: return 44;
  148. case TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right: return 45;
  149. case TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom: return 46;
  150. case TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center: return 47;
  151. }
  152. }
  153. else if (type == MiddleLayerType)
  154. {
  155. if (bit < 4)
  156. {
  157. return (int)bit;
  158. }
  159. }
  160. else if (type == FloorLayerType)
  161. {
  162. if (bit == 0)
  163. {
  164. return 0;
  165. }
  166. }
  167.  
  168. return -1;
  169. }
  170.  
  171. /// <summary>
  172. /// 根据给定的索引和类型计算地形掩码值。
  173. /// </summary>
  174. /// <param name="index">用于确定地形掩码的索引。</param>
  175. /// <param name="type">要计算地形位值的图层类型。</param>
  176. /// <returns></returns>
  177. public uint IndexToTerrainBit(int index, byte type)
  178. {
  179. if (type == TopLayerType) //顶部墙壁
  180. {
  181. switch (index)
  182. {
  183. case 0: return TerrainPeering.Center | TerrainPeering.Bottom;
  184. case 1: return TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom;
  185. case 2: return TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom;
  186. case 3: return TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Bottom;
  187. case 4: return TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom;
  188. case 5: return TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom | TerrainPeering.RightBottom;
  189. case 6: return TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom;
  190. case 7: return TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom;
  191. case 8: return TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom | TerrainPeering.RightBottom;
  192. case 9: return TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom | TerrainPeering.RightBottom;
  193. case 10: return TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom | TerrainPeering.RightBottom;
  194. case 11: return TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.LeftBottom | TerrainPeering.Bottom;
  195. case 12: return TerrainPeering.Top | TerrainPeering.Center | TerrainPeering.Bottom;
  196. case 13: return TerrainPeering.Top | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom;
  197. case 14: return TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom;
  198. case 15: return TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Bottom;
  199. case 16: return TerrainPeering.Top | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom | TerrainPeering.RightBottom;
  200. case 17: return TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom | TerrainPeering.RightBottom;
  201. case 18: return TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom | TerrainPeering.RightBottom;
  202. case 19: return TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.LeftBottom | TerrainPeering.Bottom;
  203. case 20: return TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom | TerrainPeering.RightBottom; case 21: return TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom;
  204. case 23: return TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom;
  205. case 24: return TerrainPeering.Top | TerrainPeering.Center;
  206. case 25: return TerrainPeering.Top | TerrainPeering.Center | TerrainPeering.Right;
  207. case 26: return TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right;
  208. case 27: return TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center;
  209. case 28: return TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom;
  210. case 29: return TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom | TerrainPeering.RightBottom;
  211. case 30: return TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom;
  212. case 31: return TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Bottom;
  213. case 32: return TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom | TerrainPeering.RightBottom;
  214. case 33: return TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom | TerrainPeering.RightBottom;
  215. case 34: return TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom | TerrainPeering.RightBottom;
  216. case 35: return TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.LeftBottom | TerrainPeering.Bottom;
  217. case 36: return TerrainPeering.Center;
  218. case 37: return TerrainPeering.Center | TerrainPeering.Right;
  219. case 38: return TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right;
  220. case 39: return TerrainPeering.Left | TerrainPeering.Center;
  221. case 40: return TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.LeftBottom | TerrainPeering.Bottom;
  222. case 41: return TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right;
  223. case 42: return TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right;
  224. case 43: return TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom | TerrainPeering.RightBottom;
  225. case 44: return TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Center | TerrainPeering.Right;
  226. case 45: return TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right;
  227. case 46: return TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.RightTop | TerrainPeering.Left | TerrainPeering.Center | TerrainPeering.Right | TerrainPeering.Bottom;
  228. case 47: return TerrainPeering.LeftTop | TerrainPeering.Top | TerrainPeering.Left | TerrainPeering.Center;
  229. }
  230. }
  231. else if (type == MiddleLayerType)
  232. {
  233. if (index >= 0 && index < 4)
  234. {
  235. return (uint)index;
  236. }
  237. }
  238.  
  239. return TerrainPeering.None;
  240. }
  241. /// <summary>
  242. /// 将地形掩码存入 TileSetTerrainInfo 中
  243. /// </summary>
  244. public void SetTerrainCell(int index, byte type, int[] cellData)
  245. {
  246. if (type == 1) //顶部墙壁
  247. {
  248. var terrainBit = IndexToTerrainBit(index, type);
  249. if (terrainBit != TerrainPeering.None)
  250. {
  251. T[terrainBit] = cellData;
  252. }
  253. }
  254. else if (type == 2) //侧方墙壁
  255. {
  256. switch (index)
  257. {
  258. case 0: M[0] = cellData; break;
  259. case 1: M[1] = cellData; break;
  260. case 2: M[2] = cellData; break;
  261. case 3: M[3] = cellData; break;
  262. }
  263. }
  264. else if (type == 3) //地板
  265. {
  266. F[0] = cellData;
  267. }
  268. }
  269.  
  270. /// <summary>
  271. /// 移除地形掩码
  272. /// </summary>
  273. public void RemoveTerrainCell(int index, byte type)
  274. {
  275. if (type == 1) //顶部墙壁
  276. {
  277. var terrainBit = IndexToTerrainBit(index, type);
  278. if (terrainBit != TerrainPeering.None)
  279. {
  280. T.Remove(terrainBit);
  281. }
  282. }
  283. else if (type == 2) //侧方墙壁
  284. {
  285. switch (index)
  286. {
  287. case 0: M.Remove(0); break;
  288. case 1: M.Remove(1); break;
  289. case 2: M.Remove(2); break;
  290. case 3: M.Remove(3); break;
  291. }
  292. }
  293. else if (type == 3) //地板
  294. {
  295. F.Remove(0);
  296. }
  297. }
  298. /// <summary>
  299. /// 获取指定索引的地形掩码存储的数据
  300. /// </summary>
  301. public int[] GetTerrainCell(int index, byte type)
  302. {
  303. if (type == 1) //顶部墙壁
  304. {
  305. var terrainBit = IndexToTerrainBit(index, type);
  306. if (terrainBit != TerrainPeering.None)
  307. {
  308. if (T.TryGetValue(terrainBit, out var cellData))
  309. {
  310. return cellData;
  311. }
  312. }
  313. }
  314. else if (type == 2) //侧方墙壁
  315. {
  316. switch (index)
  317. {
  318. case 0:
  319. {
  320. if (M.TryGetValue(0, out var cellData)) return cellData;
  321. }
  322. break;
  323. case 1:
  324. {
  325. if (M.TryGetValue(1, out var cellData)) return cellData;
  326. }
  327. break;
  328. case 2:
  329. {
  330. if (M.TryGetValue(2, out var cellData)) return cellData;
  331. }
  332. break;
  333. case 3:
  334. {
  335. if (M.TryGetValue(3, out var cellData)) return cellData;
  336. }
  337. break;
  338. }
  339. }
  340. else if (type == 3) //地板
  341. {
  342. if (F.TryGetValue(0, out var cellData)) return cellData;
  343. }
  344.  
  345. return null;
  346. }
  347. }