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