Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / map / DungeonTileMap.cs
@小李xl 小李xl on 18 Feb 2024 9 KB 2格高墙壁, 开发中
  1.  
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using Godot;
  6.  
  7. /// <summary>
  8. /// 地牢地砖管理类, 提供一些操作 TileMap 和计算导航的接口
  9. /// </summary>
  10. public class DungeonTileMap
  11. {
  12. //----------------------------------------------------
  13. private TileMap _tileRoot;
  14.  
  15. public DungeonTileMap(TileMap tileRoot)
  16. {
  17. _tileRoot = tileRoot;
  18. }
  19.  
  20. /// <summary>
  21. /// 根据 startRoom 和 config 数据自动填充 tileMap 参数中的房间数据, 该函数为协程函数
  22. /// </summary>
  23. public IEnumerator AutoFillRoomTile(AutoTileConfig config, RoomInfo startRoomInfo, World world)
  24. {
  25. yield return _AutoFillRoomTile(config, startRoomInfo, world);
  26. }
  27. /// <summary>
  28. /// 根据 startRoom 和 config 数据自动填充 tileMap 参数中的过道数据, 该函数为协程函数
  29. /// </summary>
  30. public IEnumerator AutoFillAisleTile(AutoTileConfig config, RoomInfo roomInfo, World world)
  31. {
  32. yield return _AutoFillAisleTile(config, roomInfo, world);
  33. }
  34. private IEnumerator _AutoFillRoomTile(AutoTileConfig config, RoomInfo roomInfo, World world)
  35. {
  36. foreach (var info in roomInfo.Next)
  37. {
  38. yield return _AutoFillRoomTile(config, info, world);
  39. }
  40. //铺房间
  41. var rectPos = roomInfo.RoomSplit.RoomInfo.Position.AsVector2I();
  42. var tileInfo = roomInfo.RoomSplit.TileInfo;
  43. //---------------------- 生成房间小地图预览 ----------------------
  44. //先计算范围
  45. var x = int.MaxValue;
  46. var y = int.MaxValue;
  47. var x2 = int.MinValue;
  48. var y2 = int.MinValue;
  49. for (var i = 0; i < tileInfo.Floor.Count; i += 4)
  50. {
  51. var posX = tileInfo.Floor[i];
  52. var posY = tileInfo.Floor[i + 1];
  53. x = Mathf.Min(x, posX);
  54. x2 = Mathf.Max(x2, posX);
  55. y = Mathf.Min(y, posY);
  56. y2 = Mathf.Max(y2, posY);
  57. }
  58. //创建image, 这里留两个像素宽高用于描边
  59. var image = Image.Create(x2 - x + 3, y2 - y + 3, false, Image.Format.Rgba8);
  60. //image.Fill(Colors.Green);
  61. //填充像素点
  62. for (var i = 0; i < tileInfo.Floor.Count; i += 4)
  63. {
  64. var posX = tileInfo.Floor[i] - x + 1;
  65. var posY = tileInfo.Floor[i + 1] - y + 1;
  66. image.SetPixel(posX, posY, new Color(0, 0, 0, 0.5882353F));
  67. }
  68. //创建texture
  69. var imageTexture = ImageTexture.CreateFromImage(image);
  70. roomInfo.PreviewTexture = imageTexture;
  71.  
  72. //---------------------- 填充tile操作 ----------------------
  73. var terrainInfo = config.TerrainInfo;
  74. SetAutoLayerDataFromList(MapLayer.AutoFloorLayer, config.SourceId, roomInfo, tileInfo.Floor, rectPos, terrainInfo);
  75. SetCustomLayerDataFromList(MapLayer.CustomFloorLayer1, roomInfo, tileInfo.CustomFloor1, rectPos);
  76. SetCustomLayerDataFromList(MapLayer.CustomFloorLayer2, roomInfo, tileInfo.CustomFloor2, rectPos);
  77. SetCustomLayerDataFromList(MapLayer.CustomFloorLayer3, roomInfo, tileInfo.CustomFloor3, rectPos);
  78. SetCustomLayerDataFromList(MapLayer.CustomMiddleLayer1, roomInfo, tileInfo.CustomMiddle1, rectPos);
  79. SetCustomLayerDataFromList(MapLayer.CustomMiddleLayer2, roomInfo, tileInfo.CustomMiddle2, rectPos);
  80. SetCustomLayerDataFromList(MapLayer.CustomTopLayer, roomInfo, tileInfo.CustomTop, rectPos);
  81. //寻找可用传送点
  82. var maxCount = (roomInfo.Size.X - 2) * (roomInfo.Size.Y - 2);
  83. var startPosition = roomInfo.Position + roomInfo.Size / 2;
  84. for (int i = 0; i < maxCount; i++)
  85. {
  86. var pos = SpiralUtil.Screw(i) + startPosition;
  87. if (IsWayTile(MapLayer.AutoFloorLayer, pos.X, pos.Y))
  88. {
  89. roomInfo.Waypoints = pos;
  90. break;
  91. }
  92. }
  93. //---------------------- 随机选择预设 ----------------------
  94. RoomPreinstallInfo preinstallInfo;
  95. if (EditorPlayManager.IsPlay && roomInfo.RoomType == GameApplication.Instance.DungeonManager.CurrConfig.DesignatedType) //编辑器模式, 指定预设
  96. {
  97. preinstallInfo = EditorTileMapManager.SelectPreinstall;
  98. }
  99. else //普通模式
  100. {
  101. if (roomInfo.RoomSplit.Preinstall.Count == 1)
  102. {
  103. preinstallInfo = roomInfo.RoomSplit.Preinstall[0];
  104. }
  105. else
  106. {
  107. var weights = roomInfo.RoomSplit.Preinstall.Select(info => info.Weight).ToArray();
  108. var index = world.Random.RandomWeight(weights);
  109. preinstallInfo = roomInfo.RoomSplit.Preinstall[index];
  110. }
  111. }
  112. var roomPreinstall = new RoomPreinstall(roomInfo, preinstallInfo);
  113. roomInfo.RoomPreinstall = roomPreinstall;
  114. //执行预处理操作
  115. roomPreinstall.Pretreatment(world);
  116. }
  117.  
  118. private IEnumerator _AutoFillAisleTile(AutoTileConfig config, RoomInfo roomInfo, World world)
  119. {
  120. foreach (var info in roomInfo.Next)
  121. {
  122. yield return _AutoFillAisleTile(config, info, world);
  123. }
  124. // yield break;
  125. //铺过道
  126. foreach (var doorInfo in roomInfo.Doors)
  127. {
  128. //必须是正向门
  129. if (!doorInfo.IsForward)
  130. {
  131. continue;
  132. }
  133.  
  134. //铺过道
  135. if (doorInfo.AisleFloorCell != null)
  136. {
  137. yield return 0;
  138.  
  139. //创建image, 这里留两个像素宽高用于描边
  140. var aisleImage = Image.Create(doorInfo.AisleFloorRect.Size.X, doorInfo.AisleFloorRect.Size.Y, false, Image.Format.Rgba8);
  141. //image.Fill(new Color(0, 1, 0, 0.2f));
  142. //填充像素点
  143. foreach (var p in doorInfo.AisleFloorCell)
  144. {
  145. _tileRoot.SetCell(MapLayer.AutoFloorLayer, p, config.Floor.SourceId, config.Floor.AutoTileCoords);
  146. //_tileRoot.SetCell(MapLayer.CustomTopLayer, p, config.Auto_000_010_000.SourceId, config.Auto_000_010_000.AutoTileCoords);
  147. aisleImage.SetPixel(p.X - doorInfo.AisleFloorRect.Position.X, p.Y - doorInfo.AisleFloorRect.Position.Y, new Color(1, 1, 1, 0.5882353F));
  148. }
  149. //创建texture
  150. var aisleImageTexture = ImageTexture.CreateFromImage(aisleImage);
  151. doorInfo.AislePreviewTexture = aisleImageTexture;
  152. doorInfo.ConnectDoor.AislePreviewTexture = aisleImageTexture;
  153. }
  154. }
  155. }
  156.  
  157.  
  158. public void GenerateWallAndNavigation(World world, AutoTileConfig config)
  159. {
  160. var navigation = new NavigationRegion2D();
  161. navigation.Name = "Navigation";
  162. world.NavigationRoot.AddChild(navigation);
  163. TileMapUtils.GenerateTerrain(_tileRoot, navigation, config);
  164. }
  165. //设置自动地形层的数据
  166. private void SetAutoLayerDataFromList(int layer, int sourceId, RoomInfo roomInfo, List<int> data, Vector2I rectPos, TileSetTerrainInfo terrainInfo)
  167. {
  168. for (var i = 0; i < data.Count; i += 4)
  169. {
  170. var posX = data[i];
  171. var posY = data[i + 1];
  172. var pos = new Vector2I(roomInfo.Position.X + posX - rectPos.X, roomInfo.Position.Y + posY - rectPos.Y);
  173. var bit = (uint)data[i + 2];
  174. var type = (byte)data[i + 3];
  175. var index = terrainInfo.TerrainBitToIndex(bit, type);
  176. var terrainCell = terrainInfo.GetTerrainCell(index, type);
  177. var atlasCoords = terrainInfo.GetPosition(terrainCell);
  178. _tileRoot.SetCell(layer, pos, sourceId, atlasCoords);
  179. }
  180. }
  181. //设置自定义层的数据
  182. private void SetCustomLayerDataFromList(int layer, RoomInfo roomInfo, List<int> data, Vector2I rectPos)
  183. {
  184. for (var i = 0; i < data.Count; i += 5)
  185. {
  186. var posX = data[i];
  187. var posY = data[i + 1];
  188. var sourceId = data[i + 2];
  189. var atlasCoordsX = data[i + 3];
  190. var atlasCoordsY = data[i + 4];
  191. var pos = new Vector2I(roomInfo.Position.X + posX - rectPos.X, roomInfo.Position.Y + posY - rectPos.Y);
  192. _tileRoot.SetCell(layer, pos, sourceId, new Vector2I(atlasCoordsX, atlasCoordsY));
  193. }
  194. }
  195. //填充tile区域
  196. private void FillRect(int layer, TileCellData data, Vector2 pos, Vector2 size)
  197. {
  198. for (int i = 0; i < size.X; i++)
  199. {
  200. for (int j = 0; j < size.Y; j++)
  201. {
  202. var p = new Vector2I((int)pos.X + i, (int)pos.Y + j);
  203. _tileRoot.SetCell(layer, p, data.SourceId, data.AutoTileCoords);
  204. }
  205. }
  206. }
  207.  
  208. //清除tile区域
  209. private void ClearRect(int layer, Vector2 pos, Vector2 size)
  210. {
  211. for (int i = 0; i < size.X; i++)
  212. {
  213. for (int j = 0; j < size.Y; j++)
  214. {
  215. var p = new Vector2I((int)pos.X + i, (int)pos.Y + j);
  216. _tileRoot.SetCell(layer, p, 0);
  217. }
  218. }
  219. }
  220. /// <summary>
  221. /// 返回指定位置的Tile是否为可以行走
  222. /// </summary>
  223. private bool IsWayTile(int layer, int x, int y)
  224. {
  225. return _tileRoot.GetCellSourceId(layer, new Vector2I(x, y)) != -1;
  226. }
  227. }