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