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