diff --git a/DungeonShooting_Godot/src/framework/map/fog/FogMask.cs b/DungeonShooting_Godot/src/framework/map/fog/FogMask.cs index 61f2f87..40758cb 100644 --- a/DungeonShooting_Godot/src/framework/map/fog/FogMask.cs +++ b/DungeonShooting_Godot/src/framework/map/fog/FogMask.cs @@ -64,35 +64,50 @@ _inRightTopTransition = temp3.GetImage(); _inRightTopTransition.Rotate180(); } - + /// - /// 初始化房间迷雾遮罩 + /// 初始化迷雾遮罩 /// - /// 房间对象 - /// 迷雾所占区域 - public void InitRoomFog(RoomInfo roomInfo, Rect2I rect2) + /// 起始位置, 单位: 格 + /// 大小, 单位: 格 + /// 透明度 + public void InitFog(Vector2I position, Vector2I size, float alpha = 0) { if (_init) { return; } InitSprite(); - GlobalPosition = rect2.Position + rect2.Size / 2; + GlobalPosition = new Vector2( + (position.X + size.X / 2f) * GameConfig.TileCellSize, + (position.Y + size.Y / 2f) * GameConfig.TileCellSize + ); //创建光纹理 - Width = rect2.Size.X; - Height = rect2.Size.Y; + Width = (size.X + 2) * GameConfig.TileCellSize; + Height = (size.Y + 2) * GameConfig.TileCellSize; var img = Image.Create(Width, Height, false, Image.Format.Rgba8); img.Fill(Colors.White); //处理边缘过渡 - HandlerTransition(roomInfo, img); + HandlerTransition(position, size, img); Texture = ImageTexture.CreateFromImage(img); + + var c = Color; + c.A = alpha; + Color = c; } - public void InitAisleFog() + /// + /// 使颜色的 alpha 通道过渡到指定的值 + /// + /// 透明度值 + /// 过渡时间 + public void TransitionAlpha(float targetAlpha, float time) { - + var tween = CreateTween(); + tween.TweenProperty(this, "color", new Color(1, 1, 1, targetAlpha), time); + tween.Play(); } public void Destroy() @@ -106,13 +121,13 @@ QueueFree(); } - private void HandlerTransition(RoomInfo roomInfo, Image image) + private void HandlerTransition(Vector2I position, Vector2I size, Image image) { var tileMap = GameApplication.Instance.World.TileRoot; var autoConfig = GameApplication.Instance.DungeonManager.AutoTileConfig; var wallCoord = autoConfig.WALL_BLOCK.AutoTileCoord; - var (x, y) = roomInfo.Position; - var (width, height) = roomInfo.Size; + var (x, y) = position; + var (width, height) = size; x -= 1; y -= 1; width += 2; diff --git a/DungeonShooting_Godot/src/framework/map/room/CrossAisleRectData.cs b/DungeonShooting_Godot/src/framework/map/room/CrossAisleRectData.cs index f047fd8..385fc6e 100644 --- a/DungeonShooting_Godot/src/framework/map/room/CrossAisleRectData.cs +++ b/DungeonShooting_Godot/src/framework/map/room/CrossAisleRectData.cs @@ -9,13 +9,43 @@ /// /// 第一道门连接的过道区域 /// - public Rect2 Rect1; + public Rect2I Rect1; /// /// 交叉点区域 /// - public Rect2 Cross; + public Rect2I Cross; /// /// 第二道门连接的过道区域 /// - public Rect2 Rect2; + public Rect2I Rect2; + + /// + /// 计算并返回过道所占矩形大小 + /// + public Rect2I CalcAisleRect() + { + int x, y, w, h; + if (Rect1.Position.X < Rect2.Position.X) + { + x = Rect1.Position.X; + w = Rect2.Position.X - Rect1.Position.X + Rect2.Size.X; + } + else + { + x = Rect2.Position.X; + w = Rect1.Position.X - Rect2.Position.X + Rect1.Size.X; + } + if (Rect1.Position.Y < Rect2.Position.Y) + { + y = Rect1.Position.Y; + h = Rect2.Position.Y - Rect1.Position.Y + Rect2.Size.Y; + } + else + { + y = Rect2.Position.Y; + h = Rect1.Position.Y - Rect2.Position.Y + Rect1.Size.Y; + } + + return new Rect2I(x, y, w, h); + } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/map/room/RoomDoorInfo.cs b/DungeonShooting_Godot/src/framework/map/room/RoomDoorInfo.cs index 02601ba..58365e0 100644 --- a/DungeonShooting_Godot/src/framework/map/room/RoomDoorInfo.cs +++ b/DungeonShooting_Godot/src/framework/map/room/RoomDoorInfo.cs @@ -5,8 +5,10 @@ /// /// 房间的门 /// -public class RoomDoorInfo +public class RoomDoorInfo : IDestroy { + public bool IsDestroyed { get; private set; } + /// /// 所在墙面方向 /// @@ -53,6 +55,11 @@ public RoomDoor Door; /// + /// 过道的迷雾 + /// + public FogMask FogMask; + + /// /// 世界坐标下的原点坐标, 单位: 像素 /// public Vector2I GetWorldOriginPosition() @@ -110,14 +117,14 @@ throw new Exception("当前门连接的过道不包含交叉点, 请改用 GetAisleRect() 函数!"); } - Rect2 rect; - Rect2 rect2; + Rect2I rect; + Rect2I rect2; //计算范围 switch (Direction) { case DoorDirection.E: //→ - rect = new Rect2( + rect = new Rect2I( OriginPosition.X, OriginPosition.Y, Cross.X - OriginPosition.X, @@ -125,7 +132,7 @@ ); break; case DoorDirection.W: //← - rect = new Rect2( + rect = new Rect2I( Cross.X + GameConfig.CorridorWidth, Cross.Y, OriginPosition.X - (Cross.X + GameConfig.CorridorWidth), @@ -133,7 +140,7 @@ ); break; case DoorDirection.S: //↓ - rect = new Rect2( + rect = new Rect2I( OriginPosition.X, OriginPosition.Y, GameConfig.CorridorWidth, @@ -141,7 +148,7 @@ ); break; case DoorDirection.N: //↑ - rect = new Rect2( + rect = new Rect2I( Cross.X, Cross.Y + GameConfig.CorridorWidth, GameConfig.CorridorWidth, @@ -149,14 +156,14 @@ ); break; default: - rect = new Rect2(); + rect = new Rect2I(); break; } switch (ConnectDoor.Direction) { case DoorDirection.E: //→ - rect2 = new Rect2( + rect2 = new Rect2I( ConnectDoor.OriginPosition.X, ConnectDoor.OriginPosition.Y, Cross.X - ConnectDoor.OriginPosition.X, @@ -164,7 +171,7 @@ ); break; case DoorDirection.W: //← - rect2 = new Rect2( + rect2 = new Rect2I( Cross.X + GameConfig.CorridorWidth, Cross.Y, ConnectDoor.OriginPosition.X - @@ -173,7 +180,7 @@ ); break; case DoorDirection.S: //↓ - rect2 = new Rect2( + rect2 = new Rect2I( ConnectDoor.OriginPosition.X, ConnectDoor.OriginPosition.Y, GameConfig.CorridorWidth, @@ -181,7 +188,7 @@ ); break; case DoorDirection.N: //↑ - rect2 = new Rect2( + rect2 = new Rect2I( Cross.X, Cross.Y + GameConfig.CorridorWidth, GameConfig.CorridorWidth, @@ -190,7 +197,7 @@ ); break; default: - rect2 = new Rect2(); + rect2 = new Rect2I(); break; } @@ -198,7 +205,21 @@ { Rect1 = rect, Rect2 = rect2, - Cross = new Rect2(Cross + Vector2.One, new Vector2(GameConfig.CorridorWidth - 2, GameConfig.CorridorWidth - 2)) + Cross = new Rect2I(Cross + Vector2I.One, new Vector2I(GameConfig.CorridorWidth - 2, GameConfig.CorridorWidth - 2)) }; } + + public void Destroy() + { + if (IsDestroyed) + { + return; + } + + IsDestroyed = true; + if (FogMask != null) + { + FogMask.Destroy(); + } + } } \ 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 618abc4..5d0c04e 100644 --- a/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs +++ b/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs @@ -270,27 +270,39 @@ } IsDestroyed = true; + //递归销毁下一个房间 foreach (var nextRoom in Next) { nextRoom.Destroy(); } Next.Clear(); + + //销毁连接的门 + foreach (var roomDoorInfo in Doors) + { + roomDoorInfo.Destroy(); + } + + //销毁预设 if (RoomPreinstall != null) { RoomPreinstall.Destroy(); RoomPreinstall = null; } + //销毁画布 if (StaticImageCanvas != null) { StaticImageCanvas.Destroy(); } + //销毁迷雾 if (FogMask != null) { FogMask.Destroy(); } + //销毁所属区域对象 if (AffiliationArea != null) { AffiliationArea.Destroy(); @@ -317,6 +329,12 @@ return; } + //清除迷雾 + if (FogMask != null && FogMask.Color.A < 1) + { + FogMask.TransitionAlpha(1, 0.3f); + } + //房间内有敌人, 或者会刷新敌人才会关门 var hasEnemy = false; if (AffiliationArea.ExistEnterItem(activityObject => activityObject.CollisionWithMask(PhysicsLayer.Enemy))) //先判断房间里面是否有敌人 @@ -381,6 +399,16 @@ { doorInfo.Door.OpenDoor(); } + + //清除过道的迷雾 + foreach (var roomDoorInfo in GetForwardDoors()) + { + if (roomDoorInfo.FogMask != null && roomDoorInfo.FogMask.Color.A < 1) + { + roomDoorInfo.FogMask.TransitionAlpha(1, 0.3f); + } + } + } /// diff --git a/DungeonShooting_Godot/src/game/room/DungeonManager.cs b/DungeonShooting_Godot/src/game/room/DungeonManager.cs index 3138e80..20d3ab6 100644 --- a/DungeonShooting_Godot/src/game/room/DungeonManager.cs +++ b/DungeonShooting_Godot/src/game/room/DungeonManager.cs @@ -197,7 +197,7 @@ World = GameApplication.Instance.CreateNewWorld(); yield return 0; //生成地牢房间 - var random = new SeedRandom(2); + var random = new SeedRandom(); _dungeonGenerator = new DungeonGenerator(CurrConfig, random); _dungeonGenerator.Generate(); yield return 0; @@ -429,47 +429,94 @@ private void CreateRoomFogMask(RoomInfo roomInfo) { var roomFog = new FogMask(); - // - //roomFog.BlendMode = Light2D.BlendModeEnum.Mix; + roomFog.BlendMode = Light2D.BlendModeEnum.Mix; roomFog.Name = "FogMask" + roomFog.IsDestroyed; - roomInfo.FogMask = roomFog; - roomFog.InitRoomFog(roomInfo, new Rect2I( - roomInfo.GetWorldPosition() - GameConfig.TileCellSizeVector2I, - (roomInfo.Size + new Vector2I(2, 2)) * GameConfig.TileCellSize) - ); + float alpha; + if (roomInfo.RoomType == DungeonRoomType.Inlet) //起始房间没有迷雾 + { + alpha = 1; + } + else + { + alpha = 0; + } + roomFog.InitFog(roomInfo.Position, roomInfo.Size, alpha); + World.FogMaskRoot.AddChild(roomFog); + roomInfo.FogMask = roomFog; //正向门 var roomDoorInfos = roomInfo.GetForwardDoors(); //生成通道迷雾 foreach (var roomDoorInfo in roomDoorInfos) { - // var p1 = roomDoorInfo.GetWorldOriginPosition(); - // var p2 = roomDoorInfo.ConnectDoor.GetWorldOriginPosition(); - // var calcRect = Utils.CalcRect(p1.X, p1.Y, p2.X, p2.Y); - // if (calcRect.Size.X == 0) - // { - // calcRect.Size += new Vector2I(4 * GameConfig.TileCellSize, 0); - // } - // else if (calcRect.Size.Y == 0) - // { - // calcRect.Size += new Vector2I(0, 4 * GameConfig.TileCellSize); - // } if (!roomDoorInfo.HasCross) { var calcRect = roomDoorInfo.GetAisleRect(); - calcRect.Size *= GameConfig.TileCellSize; - calcRect.Position *= GameConfig.TileCellSize; + if (roomDoorInfo.Direction == DoorDirection.E || roomDoorInfo.Direction == DoorDirection.W) + { + calcRect.Position += new Vector2I(2, 0); + calcRect.Size -= new Vector2I(4, 0); + } + else + { + calcRect.Position += new Vector2I(0, 2); + calcRect.Size -= new Vector2I(0, 4); + } + var aisleFog = new FogMask(); + aisleFog.BlendMode = Light2D.BlendModeEnum.Mix; + aisleFog.InitFog(calcRect.Position, calcRect.Size, alpha); + World.FogMaskRoot.AddChild(aisleFog); + roomDoorInfo.FogMask = aisleFog; + roomDoorInfo.ConnectDoor.FogMask = aisleFog; + } + else + { + var aisleRect = roomDoorInfo.GetCrossAisleRect(); + var calcAisleRect = aisleRect.CalcAisleRect(); + + switch (roomDoorInfo.Direction) + { + case DoorDirection.E: + calcAisleRect.Position += new Vector2I(2, 0); + calcAisleRect.Size -= new Vector2I(2, 0); + break; + case DoorDirection.W: + calcAisleRect.Size -= new Vector2I(2, 0); + break; + case DoorDirection.S: + calcAisleRect.Position += new Vector2I(0, 2); + calcAisleRect.Size -= new Vector2I(0, 2); + break; + case DoorDirection.N: + calcAisleRect.Size -= new Vector2I(0, 2); + break; + } - var calcRectSize = calcRect.Size; - var image = Image.Create(calcRectSize.X, calcRectSize.Y, false, Image.Format.Rgba8); - image.Fill(Colors.White); - var sprite2D = new FogMask(); - // - //sprite2D.BlendMode = Light2D.BlendModeEnum.Mix; - sprite2D.Texture = ImageTexture.CreateFromImage(image); - sprite2D.Position = calcRect.Position + calcRect.Size / 2; - World.FogMaskRoot.AddChild(sprite2D); + switch (roomDoorInfo.ConnectDoor.Direction) + { + case DoorDirection.E: + calcAisleRect.Position += new Vector2I(2, 0); + calcAisleRect.Size -= new Vector2I(2, 0); + break; + case DoorDirection.W: + calcAisleRect.Size -= new Vector2I(2, 0); + break; + case DoorDirection.S: + calcAisleRect.Position += new Vector2I(0, 2); + calcAisleRect.Size -= new Vector2I(0, 2); + break; + case DoorDirection.N: + calcAisleRect.Size -= new Vector2I(0, 2); + break; + } + + var aisleFog = new FogMask(); + aisleFog.BlendMode = Light2D.BlendModeEnum.Mix; + aisleFog.InitFog(calcAisleRect.Position, calcAisleRect.Size, alpha); + World.FogMaskRoot.AddChild(aisleFog); + roomDoorInfo.FogMask = aisleFog; + roomDoorInfo.ConnectDoor.FogMask = aisleFog; } } }