Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / map / fog / RoomFogMask.cs
@小李xl 小李xl on 23 Sep 2023 9 KB 完善房间迷雾边缘过渡处理
  1.  
  2. using Godot;
  3.  
  4. /// <summary>
  5. /// 迷雾遮罩
  6. /// </summary>
  7. public partial class RoomFogMask : PointLight2D, IDestroy
  8. {
  9. public int Width { get; private set; }
  10. public int Height { get; private set; }
  11. public bool IsDestroyed { get; private set; }
  12. private bool _init = false;
  13.  
  14. private static Image _leftTransition;
  15. private static Image _rightTransition;
  16. private static Image _topTransition;
  17. private static Image _downTransition;
  18. private static Image _leftTopTransition;
  19. private static Image _rightTopTransition;
  20. private static Image _leftDownTransition;
  21. private static Image _rightDownTransition;
  22. private static Image _inLeftTopTransition;
  23. private static Image _inRightTopTransition;
  24. private static Image _inLeftDownTransition;
  25. private static Image _inRightDownTransition;
  26. private static bool _initSprite = false;
  27.  
  28. private static void InitSprite()
  29. {
  30. if (_initSprite)
  31. {
  32. return;
  33. }
  34. _initSprite = false;
  35.  
  36. var temp = ResourceManager.Load<Texture2D>(ResourcePath.resource_sprite_map_WallTransition1_png, false);
  37. _leftTransition = temp.GetImage();
  38. _rightTransition = temp.GetImage();
  39. _rightTransition.Rotate180();
  40. _topTransition = temp.GetImage();
  41. _topTransition.Rotate90(ClockDirection.Clockwise);
  42. _downTransition = temp.GetImage();
  43. _downTransition.Rotate90(ClockDirection.Counterclockwise);
  44. var temp2 = ResourceManager.Load<Texture2D>(ResourcePath.resource_sprite_map_WallTransition2_png, false);
  45. _leftDownTransition = temp2.GetImage();
  46. _leftTopTransition = temp2.GetImage();
  47. _leftTopTransition.Rotate90(ClockDirection.Clockwise);
  48. _rightDownTransition = temp2.GetImage();
  49. _rightDownTransition.Rotate90(ClockDirection.Counterclockwise);
  50. _rightTopTransition = temp2.GetImage();
  51. _rightTopTransition.Rotate180();
  52. var temp3 = ResourceManager.Load<Texture2D>(ResourcePath.resource_sprite_map_WallTransition3_png, false);
  53. _inLeftDownTransition = temp3.GetImage();
  54. _inLeftTopTransition = temp3.GetImage();
  55. _inLeftTopTransition.Rotate90(ClockDirection.Clockwise);
  56. _inRightDownTransition = temp3.GetImage();
  57. _inRightDownTransition.Rotate90(ClockDirection.Counterclockwise);
  58. _inRightTopTransition = temp3.GetImage();
  59. _inRightTopTransition.Rotate180();
  60. }
  61. /// <summary>
  62. /// 初始化贩房间迷雾遮罩
  63. /// </summary>
  64. /// <param name="roomInfo">房间对象</param>
  65. /// <param name="rect2">迷雾所占区域</param>
  66. public void Init(RoomInfo roomInfo, Rect2I rect2)
  67. {
  68. if (_init)
  69. {
  70. return;
  71. }
  72. InitSprite();
  73. GlobalPosition = rect2.Position + rect2.Size / 2;
  74. //创建光纹理
  75. Width = rect2.Size.X;
  76. Height = rect2.Size.Y;
  77. var img = Image.Create(Width, Height, false, Image.Format.Rgba8);
  78. img.Fill(Colors.White);
  79. //处理边缘过渡
  80. HandlerTransition(roomInfo, img);
  81. Texture = ImageTexture.CreateFromImage(img);
  82. }
  83. public void Destroy()
  84. {
  85. if (IsDestroyed)
  86. {
  87. return;
  88. }
  89.  
  90. IsDestroyed = true;
  91. QueueFree();
  92. }
  93.  
  94. private void HandlerTransition(RoomInfo roomInfo, Image image)
  95. {
  96. var tileMap = GameApplication.Instance.World.TileRoot;
  97. var autoConfig = GameApplication.Instance.DungeonManager.AutoTileConfig;
  98. var wallCoord = autoConfig.WALL_BLOCK.AutoTileCoord;
  99. var (x, y) = roomInfo.Position;
  100. var (width, height) = roomInfo.Size;
  101. x -= 1;
  102. y -= 1;
  103. width += 2;
  104. height += 2;
  105. for (int i = 0; i < width; i++)
  106. {
  107. for (int j = 0; j < height; j++)
  108. {
  109. var pos = new Vector2I(i + x, j + y);
  110. //说明是外层墙壁
  111. if (tileMap.GetCellAtlasCoords(GameConfig.TopMapLayer, pos) == wallCoord)
  112. {
  113. var left = IsEmptyCell(tileMap, new Vector2I(pos.X - 1, pos.Y));
  114. var right = IsEmptyCell(tileMap, new Vector2I(pos.X + 1, pos.Y));
  115. var top = IsEmptyCell(tileMap, new Vector2I(pos.X, pos.Y - 1));
  116. var down = IsEmptyCell(tileMap, new Vector2I(pos.X, pos.Y + 1));
  117. var leftTop = IsEmptyCell(tileMap, new Vector2I(pos.X - 1, pos.Y - 1));
  118. var leftDown = IsEmptyCell(tileMap, new Vector2I(pos.X - 1, pos.Y + 1));
  119. var rightTop = IsEmptyCell(tileMap, new Vector2I(pos.X + 1, pos.Y - 1));
  120. var rightDown = IsEmptyCell(tileMap, new Vector2I(pos.X + 1, pos.Y + 1));
  121.  
  122. if (!left && !right && !top && !down && !leftTop && !leftDown && !rightTop && !rightDown)
  123. {
  124. continue;
  125. }
  126. else if (leftTop && left && top) //外轮廓, 左上
  127. {
  128. FillTransitionImage(i, j, image, _leftTopTransition);
  129. }
  130. else if (leftDown && left && down) //外轮廓, 左下
  131. {
  132. FillTransitionImage(i, j, image, _leftDownTransition);
  133. }
  134. else if (rightTop && right && top) //外轮廓, 右上
  135. {
  136. FillTransitionImage(i, j, image, _rightTopTransition);
  137. }
  138. else if (rightDown && right && down) //外轮廓, 右下
  139. {
  140. FillTransitionImage(i, j, image, _rightDownTransition);
  141. }
  142. //-------------------------
  143. else if (left) //左
  144. {
  145. FillTransitionImage(i, j, image, _leftTransition);
  146. }
  147. else if (right) //右
  148. {
  149. FillTransitionImage(i, j, image, _rightTransition);
  150. }
  151. else if (top) //上
  152. {
  153. FillTransitionImage(i, j, image, _topTransition);
  154. }
  155. else if (down) //下
  156. {
  157. FillTransitionImage(i, j, image, _downTransition);
  158. }
  159. //--------------------------
  160. else if (leftTop) //内轮廓, 左上
  161. {
  162. FillTransitionImage(i, j, image, _inLeftTopTransition);
  163. }
  164. else if (leftDown) //内轮廓, 左下
  165. {
  166. FillTransitionImage(i, j, image, _inLeftDownTransition);
  167. }
  168. else if (rightTop) //内轮廓, 右上
  169. {
  170. FillTransitionImage(i, j, image, _inRightTopTransition);
  171. }
  172. else if (rightDown) //内轮廓, 右下
  173. {
  174. FillTransitionImage(i, j, image, _inRightDownTransition);
  175. }
  176. //------------------------
  177. else //全黑
  178. {
  179. FillBlock(i, j, image);
  180. }
  181. }
  182. }
  183. }
  184. }
  185.  
  186. //填充一个16*16像素的区域
  187. private void FillBlock(int x, int y, Image image)
  188. {
  189. var endX = (x + 1) * GameConfig.TileCellSize;
  190. var endY = (y + 1) * GameConfig.TileCellSize;
  191. for (int i = x * GameConfig.TileCellSize; i < endX; i++)
  192. {
  193. for (int j = y * GameConfig.TileCellSize; j < endY; j++)
  194. {
  195. image.SetPixel(i, j, new Color(1, 1, 1, 0));
  196. }
  197. }
  198. }
  199.  
  200. private void FillTransitionImage(int x, int y, Image image, Image transitionImage)
  201. {
  202. image.BlitRect(transitionImage,
  203. new Rect2I(Vector2I.Zero, 16, 16),
  204. new Vector2I(x * GameConfig.TileCellSize, y * GameConfig.TileCellSize)
  205. );
  206. }
  207.  
  208. private bool IsEmptyCell(TileMap tileMap, Vector2I pos)
  209. {
  210. return tileMap.GetCellSourceId(GameConfig.TopMapLayer, pos) == -1 &&
  211. tileMap.GetCellSourceId(GameConfig.MiddleMapLayer, pos) == -1;
  212. }
  213. //判断是否是墙壁
  214. private bool IsNotWallCell(TileMap tileMap, Vector2I pos, Vector2I wallCoord)
  215. {
  216. return tileMap.GetCellAtlasCoords(GameConfig.TopMapLayer, pos) != wallCoord &&
  217. tileMap.GetCellAtlasCoords(GameConfig.MiddleMapLayer, pos) != wallCoord &&
  218. (tileMap.GetCellSourceId(GameConfig.TopMapLayer, pos) != -1 ||
  219. tileMap.GetCellSourceId(GameConfig.MiddleMapLayer, pos) != -1);
  220. }
  221.  
  222. //判断是否是任意类型的图块
  223. private bool IsAnyCell(TileMap tileMap, Vector2I pos)
  224. {
  225. return tileMap.GetCellSourceId(GameConfig.FloorMapLayer, pos) != -1 ||
  226. tileMap.GetCellSourceId(GameConfig.MiddleMapLayer, pos) != -1 ||
  227. tileMap.GetCellSourceId(GameConfig.TopMapLayer, pos) != -1 ||
  228. tileMap.GetCellSourceId(GameConfig.AisleFloorMapLayer, pos) != -1;
  229. }
  230. }