diff --git a/DungeonShooting_Godot/scene/World.tscn b/DungeonShooting_Godot/scene/World.tscn index cb92956..fb30eb5 100644 --- a/DungeonShooting_Godot/scene/World.tscn +++ b/DungeonShooting_Godot/scene/World.tscn @@ -3,13 +3,15 @@ [ext_resource type="Script" path="res://src/game/room/World.cs" id="1_kt3mm"] [ext_resource type="TileSet" uid="uid://b00g22o1cqhe8" path="res://resource/map/tileSet/TileSet1.tres" id="2_p6iui"] -[node name="World" type="CanvasModulate" node_paths=PackedStringArray("NormalLayer", "YSortLayer", "TileRoot", "StaticSpriteRoot", "AffiliationAreaRoot")] +[node name="World" type="CanvasModulate" node_paths=PackedStringArray("NormalLayer", "YSortLayer", "TileRoot", "StaticSpriteRoot", "AffiliationAreaRoot", "FogMaskRoot")] +color = Color(0, 0, 0, 1) script = ExtResource("1_kt3mm") NormalLayer = NodePath("NormalLayer") YSortLayer = NodePath("YSortLayer") TileRoot = NodePath("TileRoot") StaticSpriteRoot = NodePath("StaticSpriteRoot") AffiliationAreaRoot = NodePath("AffiliationAreaRoot") +FogMaskRoot = NodePath("FogMaskRoot") metadata/_edit_vertical_guides_ = [] [node name="TileRoot" type="TileMap" parent="."] @@ -50,3 +52,5 @@ y_sort_enabled = true [node name="AffiliationAreaRoot" type="Node2D" parent="."] + +[node name="FogMaskRoot" type="Node2D" parent="."] diff --git a/DungeonShooting_Godot/scene/test/TestRoomFog.tscn b/DungeonShooting_Godot/scene/test/TestRoomFog.tscn index 32caf1e..87a0c1e 100644 --- a/DungeonShooting_Godot/scene/test/TestRoomFog.tscn +++ b/DungeonShooting_Godot/scene/test/TestRoomFog.tscn @@ -6,15 +6,26 @@ [node name="TestRoomFog" type="Node2D"] [node name="PointLight2D" type="PointLight2D" parent="."] -position = Vector2(369, 280) -scale = Vector2(5, 5) +position = Vector2(705, -196) +scale = Vector2(50, 50) +color = Color(1, 1, 1, 0.180392) +blend_mode = 2 +range_item_cull_mask = 3 +texture = ExtResource("1_bty2r") + +[node name="PointLight2D2" type="PointLight2D" parent="."] +position = Vector2(372, 65) +scale = Vector2(50, 50) +blend_mode = 2 texture = ExtResource("1_bty2r") [node name="CanvasModulate" type="CanvasModulate" parent="."] +light_mask = 3 position = Vector2(-16, 33) -color = Color(0.352941, 0.352941, 0.352941, 1) +color = Color(0, 0, 0, 1) [node name="Sprite2D" type="Sprite2D" parent="CanvasModulate"] -position = Vector2(368, 326) -scale = Vector2(9.17187, 8.46875) +light_mask = 3 +position = Vector2(117, 318) +scale = Vector2(50, 46.168) texture = ExtResource("1_d62vx") diff --git a/DungeonShooting_Godot/src/framework/map/AffiliationArea.cs b/DungeonShooting_Godot/src/framework/map/AffiliationArea.cs index a2cb922..e627e82 100644 --- a/DungeonShooting_Godot/src/framework/map/AffiliationArea.cs +++ b/DungeonShooting_Godot/src/framework/map/AffiliationArea.cs @@ -37,7 +37,7 @@ /// /// 根据矩形区域初始化归属区域 /// - public void Init(RoomInfo roomInfo, Rect2 rect2) + public void Init(RoomInfo roomInfo, Rect2I rect2) { if (_init) { diff --git a/DungeonShooting_Godot/src/framework/map/DungeonTileMap.cs b/DungeonShooting_Godot/src/framework/map/DungeonTileMap.cs index 4e0addf..2439326 100644 --- a/DungeonShooting_Godot/src/framework/map/DungeonTileMap.cs +++ b/DungeonShooting_Godot/src/framework/map/DungeonTileMap.cs @@ -1,4 +1,5 @@ +using System.Collections; using System.Collections.Generic; using System.Linq; using Godot; @@ -33,23 +34,23 @@ } /// - /// 根据 startRoom 和 config 数据自动填充 tileMap 参数中的地图数据 + /// 根据 startRoom 和 config 数据自动填充 tileMap 参数中的地图数据, 该函数为协程函数 /// - public void AutoFillRoomTile(AutoTileConfig config, RoomInfo startRoomInfo, SeedRandom random) + public IEnumerator AutoFillRoomTile(AutoTileConfig config, RoomInfo startRoomInfo, SeedRandom random) { _connectNavigationItemList.Clear(); - _AutoFillRoomTile(config, startRoomInfo, random); + yield return _AutoFillRoomTile(config, startRoomInfo, random); } - private void _AutoFillRoomTile(AutoTileConfig config, RoomInfo roomInfo, SeedRandom random) + private IEnumerator _AutoFillRoomTile(AutoTileConfig config, RoomInfo roomInfo, SeedRandom random) { foreach (var info in roomInfo.Next) { - _AutoFillRoomTile(config, info, random); + yield return _AutoFillRoomTile(config, info, random); } //铺房间 - if (roomInfo.RoomSplit == null) + if (roomInfo.RoomSplit == null) //自动填充的矩形房间, 现已经弃用 { FillRect(GameConfig.FloorMapLayer, config.Floor, roomInfo.Position + Vector2.One, roomInfo.Size - new Vector2(2, 2)); @@ -79,6 +80,7 @@ //填充tile操作 var tileInfo = roomInfo.RoomSplit.TileInfo; + //底层 for (var i = 0; i < tileInfo.Floor.Count; i += 5) { var posX = tileInfo.Floor[i]; @@ -89,6 +91,7 @@ var pos = new Vector2I(roomInfo.Position.X + posX - rectPos.X, roomInfo.Position.Y + posY - rectPos.Y); _tileRoot.SetCell(GameConfig.FloorMapLayer, pos, sourceId, new Vector2I(atlasCoordsX, atlasCoordsY)); } + //中层 for (var i = 0; i < tileInfo.Middle.Count; i += 5) { var posX = tileInfo.Middle[i]; @@ -99,6 +102,7 @@ var pos = new Vector2I(roomInfo.Position.X + posX - rectPos.X, roomInfo.Position.Y + posY - rectPos.Y); _tileRoot.SetCell(GameConfig.MiddleMapLayer, pos, sourceId, new Vector2I(atlasCoordsX, atlasCoordsY)); } + //顶层 for (var i = 0; i < tileInfo.Top.Count; i += 5) { var posX = tileInfo.Top[i]; @@ -109,6 +113,7 @@ var pos = new Vector2I(roomInfo.Position.X + posX - rectPos.X, roomInfo.Position.Y + posY - rectPos.Y); _tileRoot.SetCell(GameConfig.TopMapLayer, pos, sourceId, new Vector2I(atlasCoordsX, atlasCoordsY)); } + //随机选择预设 RoomPreinstallInfo preinstallInfo; if (EditorPlayManager.IsPlay && roomInfo.RoomType == GameApplication.Instance.DungeonManager.CurrConfig.DesignatedType) //编辑器模式, 指定预设 @@ -188,7 +193,7 @@ // { // // 在 Godot 4.0 中使用以下这段代码区分层级, 会导致游戏关闭时有概率报错卡死, 目前尚不清楚原因 // //获取自定义层级 - // // var customData = tileInstance.GetCellTileData(0, coords).GetCustomData(CustomTileLayerName); + // // var customData = tileInstance.GetCellSourceId(0, coords).GetCustomData(CustomTileLayerName); // // var layer = customData.AsInt32(); // // layer = Mathf.Clamp(layer, GameConfig.FloorMapLayer, GameConfig.TopMapLayer); // @@ -467,6 +472,83 @@ } } + /// + /// 给TileMap添加轮廓, 该函数为协程函数 + /// + /// 描轮廓的Tile + public IEnumerator AddOutlineTile(TileCellInfo tileCellInfo) + { + var c = 0; + var rect = _tileRoot.GetUsedRect(); + var endX = rect.End.X + 1; + var endY = rect.End.Y + 1; + for (int x = rect.Position.X; x <= endX; x++) + { + for (int y = rect.Position.Y; y <= endY; y++) + { + if (c++ > 1000) //份帧处理, 不要挤在一帧 + { + c = 0; + yield return 0; + } + var pos = new Vector2I(x, y); + var flag1 = _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, pos) != -1 || + _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, pos) != -1 || + _tileRoot.GetCellSourceId(GameConfig.AisleFloorMapLayer, pos) != -1 || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, pos) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, pos) != tileCellInfo.AutoTileCoord); + if (!flag1) //空地 + { + var posDown = new Vector2I(pos.X, pos.Y + 1); + var posTop = new Vector2I(pos.X, pos.Y - 1); + var posLeft = new Vector2I(pos.X - 1, pos.Y); + var posRight = new Vector2I(pos.X + 1, pos.Y); + + var posLD = new Vector2I(pos.X - 1, pos.Y + 1); + var posLT = new Vector2I(pos.X - 1, pos.Y - 1); + var posRD = new Vector2I(pos.X + 1, pos.Y + 1); + var posRT = new Vector2I(pos.X + 1, pos.Y - 1); + + var flag2 = _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posDown) != -1 || + _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posDown) != -1 || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posDown) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posDown) != tileCellInfo.AutoTileCoord) || + + _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posTop) != -1 || + _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posTop) != -1 || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posTop) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posTop) != tileCellInfo.AutoTileCoord) || + + _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posLeft) != -1 || + _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posLeft) != -1 || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posLeft) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posLeft) != tileCellInfo.AutoTileCoord) || + + _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posRight) != -1 || + _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posRight) != -1 || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posRight) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posRight) != tileCellInfo.AutoTileCoord) || + // + _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posLD) != -1 || + _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posLD) != -1 || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posLD) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posLD) != tileCellInfo.AutoTileCoord) || + + _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posLT) != -1 || + _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posLT) != -1 || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posLT) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posLT) != tileCellInfo.AutoTileCoord) || + + _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posRD) != -1 || + _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posRD) != -1 || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posRD) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posRD) != tileCellInfo.AutoTileCoord) || + + _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posRT) != -1 || + _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posRT) != -1 || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posRT) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posRT) != tileCellInfo.AutoTileCoord); + + if (flag2) //非空地, 那么说明这个点需要填充 WALL_BLOCK + { + _tileRoot.SetCell(GameConfig.TopMapLayer, pos, tileCellInfo.Id, tileCellInfo.AutoTileCoord); + } + } + } + } + } + //填充tile区域 private void FillRect(int layer, TileCellInfo info, Vector2 pos, Vector2 size) { @@ -824,7 +906,7 @@ { if (_floorAtlasCoords == null || _floorAtlasCoords.Count == 0) { - return _tileRoot.GetCellTileData(layer, new Vector2I(x, y)) != null; + return _tileRoot.GetCellSourceId(layer, new Vector2I(x, y)) != -1; } var result = _tileRoot.GetCellAtlasCoords(layer, new Vector2I(x, y)); diff --git a/DungeonShooting_Godot/src/framework/map/TileCellInfo.cs b/DungeonShooting_Godot/src/framework/map/TileCellInfo.cs index b892d38..bd120a6 100644 --- a/DungeonShooting_Godot/src/framework/map/TileCellInfo.cs +++ b/DungeonShooting_Godot/src/framework/map/TileCellInfo.cs @@ -13,7 +13,7 @@ } /// - /// 在TileSet中的图块id + /// 在TileSet中的图块id, 也就是sourceId /// public int Id; diff --git a/DungeonShooting_Godot/src/framework/map/fog/RoomFogMask.cs b/DungeonShooting_Godot/src/framework/map/fog/RoomFogMask.cs new file mode 100644 index 0000000..82aff05 --- /dev/null +++ b/DungeonShooting_Godot/src/framework/map/fog/RoomFogMask.cs @@ -0,0 +1,33 @@ + +using Godot; + +public partial class RoomFogMask : PointLight2D, IDestroy +{ + public bool IsDestroyed { get; private set; } + private bool _init = false; + + public void Init(RoomInfo roomInfo, Rect2I rect2) + { + if (_init) + { + return; + } + GlobalPosition = rect2.Position + rect2.Size / 2; + + //创建光纹理 + var img = Image.Create(rect2.Size.X, rect2.Size.Y, false, Image.Format.Rgba8); + img.Fill(Colors.White); + Texture = ImageTexture.CreateFromImage(img); + } + + public void Destroy() + { + if (IsDestroyed) + { + return; + } + + IsDestroyed = true; + QueueFree(); + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs b/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs index 1d3b34a..317a424 100644 --- a/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs +++ b/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs @@ -80,6 +80,16 @@ public RoomStaticImageCanvas StaticImageCanvas; /// + /// 房间迷雾 + /// + public RoomFogMask RoomFogMask; + + /// + /// 房间算上连接通道所占用的区域 + /// + public Rect2I OuterRange { get; private set; } + + /// /// 是否处于闭关状态, 也就是房间门没有主动打开 /// public bool IsSeclusion { get; private set; } = false; @@ -94,6 +104,96 @@ //private List _currActivityMarks = new List(); /// + /// 重新计算占用的区域 + /// + public void CalcOuterRange() + { + var worldPos = GetWorldPosition(); + var pos = new Vector2I((int)worldPos.X, (int)worldPos.Y); + int minX = pos.X; + int minY = pos.Y; + int maxX = minX + GetWidth(); + int maxY = minY + GetHeight(); + + //遍历每一个连接的门, 计算计算canvas覆盖范围 + foreach (var doorInfo in Doors) + { + var connectDoor = doorInfo.ConnectDoor; + switch (connectDoor.Direction) + { + case DoorDirection.E: + case DoorDirection.W: + { + var (px1, py1) = connectDoor.GetWorldOriginPosition(); + var py2 = py1 + 4 * GameConfig.TileCellSize; + if (px1 < minX) + { + minX = px1; + } + else if (px1 > maxX) + { + maxX = px1; + } + + if (py1 < minY) + { + minY = py1; + } + else if (py1 > maxY) + { + maxY = py1; + } + + if (py2 < minY) + { + minY = py2; + } + else if (py2 > maxY) + { + maxY = py2; + } + } + break; + case DoorDirection.S: + case DoorDirection.N: + { + var (px1, py1) = connectDoor.GetWorldOriginPosition(); + var px2 = px1 + 4 * GameConfig.TileCellSize; + if (px1 < minX) + { + minX = px1; + } + else if (px1 > maxX) + { + maxX = px1; + } + + if (py1 < minY) + { + minY = py1; + } + else if (py1 > maxY) + { + maxY = py1; + } + + if (px2 < minX) + { + minX = px2; + } + else if (px2 > maxX) + { + maxX = px2; + } + } + break; + } + } + + OuterRange = new Rect2I(minX, minY, maxX - minX, maxY - minY); + } + + /// /// 获取房间的全局坐标, 单位: 像素 /// public Vector2I GetWorldPosition() @@ -186,6 +286,11 @@ StaticImageCanvas.Destroy(); } + if (RoomFogMask != null) + { + RoomFogMask.Destroy(); + } + if (AffiliationArea != null) { AffiliationArea.Destroy(); diff --git a/DungeonShooting_Godot/src/game/room/AutoTileConfig.cs b/DungeonShooting_Godot/src/game/room/AutoTileConfig.cs index 07bcf9d..968d8f3 100644 --- a/DungeonShooting_Godot/src/game/room/AutoTileConfig.cs +++ b/DungeonShooting_Godot/src/game/room/AutoTileConfig.cs @@ -22,6 +22,8 @@ public TileCellInfo OUT_RT = new TileCellInfo(0, new Vector2I(3, 2)); public TileCellInfo OUT_RB = new TileCellInfo(0, new Vector2I(3, 7)); + public TileCellInfo WALL_BLOCK = new TileCellInfo(0, new Vector2I(2, 3)); + private List _middleLayerAtlasCoords = new List() { new Vector2I(1, 6), diff --git a/DungeonShooting_Godot/src/game/room/DungeonManager.cs b/DungeonShooting_Godot/src/game/room/DungeonManager.cs index 64e7742..cd013f9 100644 --- a/DungeonShooting_Godot/src/game/room/DungeonManager.cs +++ b/DungeonShooting_Godot/src/game/room/DungeonManager.cs @@ -200,8 +200,8 @@ //填充地牢 _autoTileConfig = new AutoTileConfig(); _dungeonTileMap = new DungeonTileMap(World.TileRoot); - _dungeonTileMap.AutoFillRoomTile(_autoTileConfig, _dungeonGenerator.StartRoomInfo, _dungeonGenerator.Random); - yield return 0; + yield return _dungeonTileMap.AutoFillRoomTile(_autoTileConfig, _dungeonGenerator.StartRoomInfo, _dungeonGenerator.Random); + yield return _dungeonTileMap.AddOutlineTile(_autoTileConfig.WALL_BLOCK); //生成寻路网格, 这一步操作只生成过道的导航 _dungeonTileMap.GenerateNavigationPolygon(GameConfig.AisleFloorMapLayer); @@ -218,7 +218,6 @@ yield return 0; //初始化所有房间 yield return _dungeonGenerator.EachRoomCoroutine(InitRoom); - yield return 0; //播放bgm //SoundManager.PlayMusic(ResourcePath.resource_sound_bgm_Intro_ogg, -17f); @@ -309,6 +308,7 @@ // 初始化房间 private void InitRoom(RoomInfo roomInfo) { + roomInfo.CalcOuterRange(); //挂载房间导航区域 MountNavFromRoomInfo(roomInfo); //创建门 @@ -318,7 +318,7 @@ //创建静态精灵画布 CreateRoomStaticSpriteCanvas(roomInfo); //创建迷雾遮罩 - + CreateRoomFogMask(roomInfo); } //挂载房间导航区域 @@ -393,8 +393,8 @@ { var affiliation = new AffiliationArea(); affiliation.Name = "AffiliationArea" + roomInfo.Id; - affiliation.Init(roomInfo, new Rect2( - roomInfo.GetWorldPosition() + new Vector2(GameConfig.TileCellSize, GameConfig.TileCellSize), + affiliation.Init(roomInfo, new Rect2I( + roomInfo.GetWorldPosition() + GameConfig.TileCellSizeVector2I, (roomInfo.Size - new Vector2I(2, 2)) * GameConfig.TileCellSize)); roomInfo.AffiliationArea = affiliation; @@ -405,92 +405,13 @@ private void CreateRoomStaticSpriteCanvas(RoomInfo roomInfo) { var worldPos = roomInfo.GetWorldPosition(); - var pos = new Vector2I((int)worldPos.X, (int)worldPos.Y); - - int minX = pos.X; - int minY = pos.Y; - int maxX = minX + roomInfo.GetWidth(); - int maxY = minY + roomInfo.GetHeight(); + var rect = roomInfo.OuterRange; - //遍历每一个连接的门, 计算计算canvas覆盖范围 - foreach (var doorInfo in roomInfo.Doors) - { - var connectDoor = doorInfo.ConnectDoor; - switch (connectDoor.Direction) - { - case DoorDirection.E: - case DoorDirection.W: - { - var (px1, py1) = connectDoor.GetWorldOriginPosition(); - var py2 = py1 + 4 * GameConfig.TileCellSize; - if (px1 < minX) - { - minX = px1; - } - else if (px1 > maxX) - { - maxX = px1; - } + int minX = rect.Position.X - GameConfig.TileCellSize; + int minY = rect.Position.Y - GameConfig.TileCellSize; + int maxX = rect.End.X + GameConfig.TileCellSize; + int maxY = rect.End.Y + GameConfig.TileCellSize; - if (py1 < minY) - { - minY = py1; - } - else if (py1 > maxY) - { - maxY = py1; - } - - if (py2 < minY) - { - minY = py2; - } - else if (py2 > maxY) - { - maxY = py2; - } - } - break; - case DoorDirection.S: - case DoorDirection.N: - { - var (px1, py1) = connectDoor.GetWorldOriginPosition(); - var px2 = px1 + 4 * GameConfig.TileCellSize; - if (px1 < minX) - { - minX = px1; - } - else if (px1 > maxX) - { - maxX = px1; - } - - if (py1 < minY) - { - minY = py1; - } - else if (py1 > maxY) - { - maxY = py1; - } - - if (px2 < minX) - { - minX = px2; - } - else if (px2 > maxX) - { - maxX = px2; - } - } - break; - } - } - - minX -= GameConfig.TileCellSize; - minY -= GameConfig.TileCellSize; - maxX += GameConfig.TileCellSize; - maxY += GameConfig.TileCellSize; var staticSpriteCanvas = new RoomStaticImageCanvas( World.StaticSpriteRoot, new Vector2I(minX, minY), @@ -500,6 +421,18 @@ roomInfo.StaticImageCanvas = staticSpriteCanvas; } + //创建迷雾遮罩 + private void CreateRoomFogMask(RoomInfo roomInfo) + { + var roomFog = new RoomFogMask(); + roomFog.Name = "FogMask" + roomFog.IsDestroyed; + roomInfo.RoomFogMask = roomFog; + roomFog.Init(roomInfo, new Rect2I( + roomInfo.GetWorldPosition() - GameConfig.TileCellSizeVector2I, + (roomInfo.Size + new Vector2I(2, 2)) * GameConfig.TileCellSize)); + World.FogMaskRoot.AddChild(roomFog); + } + /// /// 玩家第一次进入某个房间回调 /// diff --git a/DungeonShooting_Godot/src/game/room/World.cs b/DungeonShooting_Godot/src/game/room/World.cs index c44799f..650d3da 100644 --- a/DungeonShooting_Godot/src/game/room/World.cs +++ b/DungeonShooting_Godot/src/game/room/World.cs @@ -24,6 +24,7 @@ [Export] public Node2D StaticSpriteRoot; [Export] public Node2D AffiliationAreaRoot; + [Export] public Node2D FogMaskRoot; /// /// 是否暂停