diff --git a/DungeonShooting_Godot/src/framework/map/AffiliationArea.cs b/DungeonShooting_Godot/src/framework/map/AffiliationArea.cs
index e627e82..e056bbf 100644
--- a/DungeonShooting_Godot/src/framework/map/AffiliationArea.cs
+++ b/DungeonShooting_Godot/src/framework/map/AffiliationArea.cs
@@ -4,7 +4,7 @@
using Godot;
///
-/// 归属区域
+/// 房间归属区域
///
public partial class AffiliationArea : Area2D, IDestroy
{
@@ -89,7 +89,7 @@
//如果是玩家
if (activityObject == Player.Current)
{
- OnPlayerEnterRoom();
+ OnPlayerInsertRoom();
}
}
@@ -251,7 +251,7 @@
}
//玩家进入房间
- private void OnPlayerEnterRoom()
+ private void OnPlayerInsertRoom()
{
if (IsFirstEnterFlag)
{
diff --git a/DungeonShooting_Godot/src/framework/map/DungeonGenerator.cs b/DungeonShooting_Godot/src/framework/map/DungeonGenerator.cs
index ba37303..8dcc1a8 100644
--- a/DungeonShooting_Godot/src/framework/map/DungeonGenerator.cs
+++ b/DungeonShooting_Godot/src/framework/map/DungeonGenerator.cs
@@ -560,6 +560,7 @@
var roomDoor = new RoomDoorInfo();
var nextRoomDoor = new RoomDoorInfo();
roomDoor.RoomInfo = roomInfo;
+ roomDoor.IsForward = true;
nextRoomDoor.RoomInfo = nextRoomInfo;
roomDoor.ConnectRoom = nextRoomInfo;
roomDoor.ConnectDoor = nextRoomDoor;
diff --git a/DungeonShooting_Godot/src/framework/map/fog/AisleFogArea.cs b/DungeonShooting_Godot/src/framework/map/fog/AisleFogArea.cs
new file mode 100644
index 0000000..f52c690
--- /dev/null
+++ b/DungeonShooting_Godot/src/framework/map/fog/AisleFogArea.cs
@@ -0,0 +1,93 @@
+
+using Godot;
+
+///
+/// 过道迷雾区域碰撞器, 用于检测玩家是否进入过道
+///
+public partial class AisleFogArea : Area2D, IDestroy
+{
+ public bool IsDestroyed { get; private set; }
+
+ ///
+ /// 所属连接的门 (起始门)
+ ///
+ public RoomDoorInfo RoomDoorInfo { get; private set; }
+
+ private bool _init = false;
+ private RectangleShape2D _shape;
+
+ ///
+ /// 根据矩形区域初始化归属区域
+ ///
+ public void Init(RoomDoorInfo doorInfo, Rect2I rect2)
+ {
+ if (_init)
+ {
+ return;
+ }
+
+ _init = true;
+
+ RoomDoorInfo = doorInfo;
+ var collisionShape = new CollisionShape2D();
+ collisionShape.GlobalPosition = rect2.Position + rect2.Size / 2;
+ var shape = new RectangleShape2D();
+ _shape = shape;
+ shape.Size = rect2.Size;
+ collisionShape.Shape = shape;
+ AddChild(collisionShape);
+ _Init();
+ }
+
+ private void _Init()
+ {
+ Monitoring = true;
+ Monitorable = false;
+ CollisionLayer = PhysicsLayer.None;
+ CollisionMask = PhysicsLayer.Player;
+
+ BodyEntered += OnBodyEntered;
+ //BodyExited += OnBodyExited;
+ }
+
+ public void Destroy()
+ {
+ if (IsDestroyed)
+ {
+ return;
+ }
+
+ IsDestroyed = true;
+ QueueFree();
+ }
+
+ private void OnBodyEntered(Node2D body)
+ {
+ if (body == Player.Current)
+ {
+ //注意需要延时调用
+ CallDeferred(nameof(InsertItem));
+ }
+ }
+
+ // private void OnBodyExited(Node2D body)
+ // {
+ // if (body == Player.Current)
+ // {
+ // //注意需要延时调用
+ // CallDeferred(nameof(LeavePlayer));
+ // }
+ // }
+
+ private void InsertItem()
+ {
+ //GD.Print("玩家进入过道");
+ RoomDoorInfo.ClearFog();
+ }
+
+ // private void LeavePlayer()
+ // {
+ // //GD.Print("玩家离开过道");
+ // //RoomDoorInfo.DarkFog();
+ // }
+}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/framework/map/fog/FogMask.cs b/DungeonShooting_Godot/src/framework/map/fog/FogMask.cs
index 40758cb..b80dc10 100644
--- a/DungeonShooting_Godot/src/framework/map/fog/FogMask.cs
+++ b/DungeonShooting_Godot/src/framework/map/fog/FogMask.cs
@@ -1,4 +1,6 @@
+using System;
+using System.Collections;
using Godot;
///
@@ -29,6 +31,7 @@
private static bool _initSprite = false;
+ private long _cid = -1;
private static void InitSprite()
{
if (_initSprite)
@@ -105,9 +108,26 @@
/// 过渡时间
public void TransitionAlpha(float targetAlpha, float time)
{
- var tween = CreateTween();
- tween.TweenProperty(this, "color", new Color(1, 1, 1, targetAlpha), time);
- tween.Play();
+ if (_cid >= 0)
+ {
+ World.Current.StopCoroutine(_cid);
+ }
+
+ _cid = World.Current.StartCoroutine(RunTransitionAlpha(targetAlpha, time));
+ }
+
+ private IEnumerator RunTransitionAlpha(float targetAlpha, float time)
+ {
+ var originColor = Color;
+ var a = originColor.A;
+ var delta = Mathf.Abs(a - targetAlpha) / time;
+ while (Math.Abs(a - targetAlpha) > 0.001f)
+ {
+ a = Mathf.MoveToward(a, targetAlpha, delta * (float)World.Current.GetProcessDeltaTime());
+ Color = new Color(1, 1, 1, a);
+ yield return null;
+ }
+ _cid = -1;
}
public void Destroy()
diff --git a/DungeonShooting_Godot/src/framework/map/room/RoomDoorInfo.cs b/DungeonShooting_Godot/src/framework/map/room/RoomDoorInfo.cs
index 58365e0..ebe9183 100644
--- a/DungeonShooting_Godot/src/framework/map/room/RoomDoorInfo.cs
+++ b/DungeonShooting_Godot/src/framework/map/room/RoomDoorInfo.cs
@@ -8,13 +8,18 @@
public class RoomDoorInfo : IDestroy
{
public bool IsDestroyed { get; private set; }
-
+
///
/// 所在墙面方向
///
public DoorDirection Direction;
///
+ /// 是否是正向的门
+ ///
+ public bool IsForward;
+
+ ///
/// 所在的房间
///
public RoomInfo RoomInfo;
@@ -60,6 +65,16 @@
public FogMask FogMask;
///
+ /// 过道迷雾区域
+ ///
+ public AisleFogArea AisleFogArea;
+
+ ///
+ /// 当前门连接的过道是否探索过
+ ///
+ public bool IsExplored { get; private set; } = false;
+
+ ///
/// 世界坐标下的原点坐标, 单位: 像素
///
public Vector2I GetWorldOriginPosition()
@@ -221,5 +236,36 @@
{
FogMask.Destroy();
}
+
+ if (AisleFogArea != null)
+ {
+ AisleFogArea.Destroy();
+ }
+ }
+
+ ///
+ /// 清除过道迷雾
+ ///
+ public void ClearFog()
+ {
+ IsExplored = true;
+ ConnectDoor.IsExplored = true;
+ if (FogMask != null && Math.Abs(FogMask.Color.A - 1f) > 0.001f)
+ {
+ FogMask.TransitionAlpha(1, 0.3f);
+ }
+ }
+
+ ///
+ /// 将过道迷雾变暗
+ ///
+ public void DarkFog()
+ {
+ IsExplored = true;
+ ConnectDoor.IsExplored = true;
+ if (FogMask != null && Math.Abs(FogMask.Color.A - GameConfig.DarkFogAlpha) > 0.001f)
+ {
+ FogMask.TransitionAlpha(GameConfig.DarkFogAlpha, 0.3f);
+ }
}
}
\ 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 5d0c04e..fe7f2f7 100644
--- a/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs
+++ b/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs
@@ -1,4 +1,5 @@
+using System;
using System.Collections.Generic;
using Godot;
@@ -329,12 +330,6 @@
return;
}
- //清除迷雾
- if (FogMask != null && FogMask.Color.A < 1)
- {
- FogMask.TransitionAlpha(1, 0.3f);
- }
-
//房间内有敌人, 或者会刷新敌人才会关门
var hasEnemy = false;
if (AffiliationArea.ExistEnterItem(activityObject => activityObject.CollisionWithMask(PhysicsLayer.Enemy))) //先判断房间里面是否有敌人
@@ -398,17 +393,14 @@
foreach (var doorInfo in Doors)
{
doorInfo.Door.OpenDoor();
- }
-
- //清除过道的迷雾
- foreach (var roomDoorInfo in GetForwardDoors())
- {
- if (roomDoorInfo.FogMask != null && roomDoorInfo.FogMask.Color.A < 1)
+
+ //过道迷雾
+ doorInfo.AisleFogArea.Monitoring = true;
+ if (doorInfo.IsExplored)
{
- roomDoorInfo.FogMask.TransitionAlpha(1, 0.3f);
+ doorInfo.ClearFog();
}
}
-
}
///
@@ -425,18 +417,26 @@
foreach (var doorInfo in Doors)
{
doorInfo.Door.CloseDoor();
+
+ //过道迷雾
+ doorInfo.AisleFogArea.Monitoring = false;
+ if (doorInfo.IsExplored)
+ {
+ doorInfo.DarkFog();
+ }
}
}
///
- /// 获取该房间所有正向的门,nextRoom.id > this.id
+ /// 获取该房间所有正向的门
///
public RoomDoorInfo[] GetForwardDoors()
{
var temp = new List();
foreach (var doorInfo in Doors)
{
- if (doorInfo.ConnectRoom.Id > Id)
+ if (doorInfo.IsForward)
+ //if (doorInfo.ConnectRoom.Id > Id)
{
temp.Add(doorInfo);
}
@@ -444,4 +444,26 @@
return temp.ToArray();
}
+
+ ///
+ /// 清除迷雾
+ ///
+ public void ClearFog()
+ {
+ if (FogMask != null && Math.Abs(FogMask.Color.A - 1) > 0.001f)
+ {
+ FogMask.TransitionAlpha(1, 0.3f);
+ }
+ }
+
+ ///
+ /// 将迷雾变暗
+ ///
+ public void DarkFog()
+ {
+ if (FogMask != null && Math.Abs(FogMask.Color.A - GameConfig.DarkFogAlpha) > 0.001f)
+ {
+ FogMask.TransitionAlpha(GameConfig.DarkFogAlpha, 0.3f);
+ }
+ }
}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/GameConfig.cs b/DungeonShooting_Godot/src/game/GameConfig.cs
index 756b76b..046c27a 100644
--- a/DungeonShooting_Godot/src/game/GameConfig.cs
+++ b/DungeonShooting_Godot/src/game/GameConfig.cs
@@ -77,4 +77,9 @@
/// 预览图大小
///
public const int PreviewImageSize = 196;
+
+ ///
+ /// 变暗迷雾的透明度值
+ ///
+ public const float DarkFogAlpha = 0.2f;
}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/room/DungeonManager.cs b/DungeonShooting_Godot/src/game/room/DungeonManager.cs
index 20d3ab6..5801dfc 100644
--- a/DungeonShooting_Godot/src/game/room/DungeonManager.cs
+++ b/DungeonShooting_Godot/src/game/room/DungeonManager.cs
@@ -57,6 +57,8 @@
//用于检查房间敌人的计时器
private float _checkEnemyTimer = 0;
+ //用于记录玩家上一个所在区域
+ private AffiliationArea _affiliationAreaFlag;
public DungeonManager()
@@ -450,9 +452,12 @@
//生成通道迷雾
foreach (var roomDoorInfo in roomDoorInfos)
{
+ Rect2I calcRect;
+ Rect2I fogAreaRect;
if (!roomDoorInfo.HasCross)
{
- var calcRect = roomDoorInfo.GetAisleRect();
+ calcRect = roomDoorInfo.GetAisleRect();
+ fogAreaRect = calcRect;
if (roomDoorInfo.Direction == DoorDirection.E || roomDoorInfo.Direction == DoorDirection.W)
{
calcRect.Position += new Vector2I(2, 0);
@@ -463,61 +468,64 @@
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();
+ calcRect = aisleRect.CalcAisleRect();
+ fogAreaRect = calcRect;
switch (roomDoorInfo.Direction)
{
case DoorDirection.E:
- calcAisleRect.Position += new Vector2I(2, 0);
- calcAisleRect.Size -= new Vector2I(2, 0);
+ calcRect.Position += new Vector2I(2, 0);
+ calcRect.Size -= new Vector2I(2, 0);
break;
case DoorDirection.W:
- calcAisleRect.Size -= new Vector2I(2, 0);
+ calcRect.Size -= new Vector2I(2, 0);
break;
case DoorDirection.S:
- calcAisleRect.Position += new Vector2I(0, 2);
- calcAisleRect.Size -= new Vector2I(0, 2);
+ calcRect.Position += new Vector2I(0, 2);
+ calcRect.Size -= new Vector2I(0, 2);
break;
case DoorDirection.N:
- calcAisleRect.Size -= new Vector2I(0, 2);
+ calcRect.Size -= new Vector2I(0, 2);
break;
}
switch (roomDoorInfo.ConnectDoor.Direction)
{
case DoorDirection.E:
- calcAisleRect.Position += new Vector2I(2, 0);
- calcAisleRect.Size -= new Vector2I(2, 0);
+ calcRect.Position += new Vector2I(2, 0);
+ calcRect.Size -= new Vector2I(2, 0);
break;
case DoorDirection.W:
- calcAisleRect.Size -= new Vector2I(2, 0);
+ calcRect.Size -= new Vector2I(2, 0);
break;
case DoorDirection.S:
- calcAisleRect.Position += new Vector2I(0, 2);
- calcAisleRect.Size -= new Vector2I(0, 2);
+ calcRect.Position += new Vector2I(0, 2);
+ calcRect.Size -= new Vector2I(0, 2);
break;
case DoorDirection.N:
- calcAisleRect.Size -= new Vector2I(0, 2);
+ calcRect.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;
}
+
+ //过道迷雾遮罩
+ var aisleFog = new FogMask();
+ aisleFog.BlendMode = Light2D.BlendModeEnum.Mix;
+ aisleFog.InitFog(calcRect.Position, calcRect.Size);
+ World.FogMaskRoot.AddChild(aisleFog);
+ roomDoorInfo.FogMask = aisleFog;
+ roomDoorInfo.ConnectDoor.FogMask = aisleFog;
+
+ //过道迷雾区域
+ var fogArea = new AisleFogArea();
+ fogArea.Init(roomDoorInfo, new Rect2I(fogAreaRect.Position * GameConfig.TileCellSize, fogAreaRect.Size * GameConfig.TileCellSize));
+ roomDoorInfo.AisleFogArea = fogArea;
+ roomDoorInfo.ConnectDoor.AisleFogArea = fogArea;
+ World.AffiliationAreaRoot.AddChild(fogArea);
}
}
@@ -551,6 +559,26 @@
///
private void OnPlayerEnterRoom(object o)
{
+ var roomInfo = (RoomInfo)o;
+ if (_affiliationAreaFlag != roomInfo.AffiliationArea)
+ {
+ if (_affiliationAreaFlag != null)
+ {
+ if (!_affiliationAreaFlag.IsDestroyed)
+ {
+ //上一个房间变暗
+ _affiliationAreaFlag.RoomInfo.DarkFog();
+ }
+ }
+
+ if (!roomInfo.AffiliationArea.IsDestroyed)
+ {
+ //当前房间变亮
+ roomInfo.ClearFog();
+ }
+
+ _affiliationAreaFlag = roomInfo.AffiliationArea;
+ }
}
///
diff --git a/DungeonShooting_Godot/src/game/room/World.cs b/DungeonShooting_Godot/src/game/room/World.cs
index 159ba87..00ca2eb 100644
--- a/DungeonShooting_Godot/src/game/room/World.cs
+++ b/DungeonShooting_Godot/src/game/room/World.cs
@@ -8,6 +8,11 @@
public partial class World : CanvasModulate, ICoroutine
{
///
+ /// 当前的游戏世界对象
+ ///
+ public static World Current => GameApplication.Instance.World;
+
+ ///
/// //对象根节点
///
[Export] public Node2D NormalLayer;