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