Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / map / serialize / tileSet / TileSetTerrainInfo.cs
@小李xl 小李xl on 15 Feb 2024 18 KB 地牢编辑器2格墙壁支持
  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. /// 侧方墙壁 (8块) 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 == 8 && 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 < 8)
  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 < 8)
  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. case 4: M[4] = cellData; break;
  350. case 5: M[5] = cellData; break;
  351. case 6: M[6] = cellData; break;
  352. case 7: M[7] = cellData; break;
  353. }
  354. }
  355. else if (type == FloorLayerType) //地板
  356. {
  357. F[0] = cellData;
  358. }
  359. }
  360.  
  361. /// <summary>
  362. /// 移除地形掩码
  363. /// </summary>
  364. public void RemoveTerrainCell(int index, byte type)
  365. {
  366. if (type == TerrainLayerType) //顶部墙壁
  367. {
  368. var terrainBit = IndexToTerrainBit(index, type);
  369. if (terrainBit != None)
  370. {
  371. T.Remove(terrainBit);
  372. }
  373. }
  374. else if (type == MiddleLayerType) //侧方墙壁
  375. {
  376. switch (index)
  377. {
  378. case 0: M.Remove(0); break;
  379. case 1: M.Remove(1); break;
  380. case 2: M.Remove(2); break;
  381. case 3: M.Remove(3); break;
  382. case 4: M.Remove(4); break;
  383. case 5: M.Remove(5); break;
  384. case 6: M.Remove(6); break;
  385. case 7: M.Remove(7); break;
  386. }
  387. }
  388. else if (type == FloorLayerType) //地板
  389. {
  390. F.Remove(0);
  391. }
  392. }
  393. /// <summary>
  394. /// 获取指定索引的地形掩码存储的数据
  395. /// </summary>
  396. public int[] GetTerrainCell(int index, byte type)
  397. {
  398. if (type == TerrainLayerType) //顶部墙壁
  399. {
  400. var terrainBit = IndexToTerrainBit(index, type);
  401. if (terrainBit != None)
  402. {
  403. if (T.TryGetValue(terrainBit, out var cellData))
  404. {
  405. return cellData;
  406. }
  407. }
  408. }
  409. else if (type == MiddleLayerType) //侧方墙壁
  410. {
  411. switch (index)
  412. {
  413. case 0:
  414. {
  415. if (M.TryGetValue(0, out var cellData)) return cellData;
  416. }
  417. break;
  418. case 1:
  419. {
  420. if (M.TryGetValue(1, out var cellData)) return cellData;
  421. }
  422. break;
  423. case 2:
  424. {
  425. if (M.TryGetValue(2, out var cellData)) return cellData;
  426. }
  427. break;
  428. case 3:
  429. {
  430. if (M.TryGetValue(3, out var cellData)) return cellData;
  431. }
  432.  
  433. break;
  434. case 4:
  435. {
  436. if (M.TryGetValue(4, out var cellData)) return cellData;
  437. }
  438. break;
  439. case 5:
  440. {
  441. if (M.TryGetValue(5, out var cellData)) return cellData;
  442. }
  443. break;
  444. case 6:
  445. {
  446. if (M.TryGetValue(6, out var cellData)) return cellData;
  447. }
  448. break;
  449. case 7:
  450. {
  451. if (M.TryGetValue(7, out var cellData)) return cellData;
  452. }
  453. break;
  454. }
  455. }
  456. else if (type == FloorLayerType) //地板
  457. {
  458. if (F.TryGetValue(0, out var cellData)) return cellData;
  459. }
  460.  
  461. return null;
  462. }
  463. }