diff --git a/DungeonShooting_Godot/scene/Main.tscn b/DungeonShooting_Godot/scene/Main.tscn
index aff7b6d..35a4274 100644
--- a/DungeonShooting_Godot/scene/Main.tscn
+++ b/DungeonShooting_Godot/scene/Main.tscn
@@ -24,6 +24,7 @@
[node name="Main" type="Node2D"]
script = ExtResource( 3 )
+Debug = true
CursorPack = ExtResource( 4 )
RoomPath = NodePath("ViewCanvas/ViewportContainer/Viewport/Room")
ViewportPath = NodePath("ViewCanvas/ViewportContainer/Viewport")
diff --git a/DungeonShooting_Godot/src/game/GameApplication.cs b/DungeonShooting_Godot/src/game/GameApplication.cs
index 6bb09c1..f53ca90 100644
--- a/DungeonShooting_Godot/src/game/GameApplication.cs
+++ b/DungeonShooting_Godot/src/game/GameApplication.cs
@@ -5,6 +5,11 @@
{
public static GameApplication Instance { get; private set; }
+ ///
+ /// 是否开启调试
+ ///
+ [Export] public bool Debug = false;
+
[Export] public PackedScene CursorPack;
[Export] public NodePath RoomPath;
diff --git a/DungeonShooting_Godot/src/game/role/PathSign.cs b/DungeonShooting_Godot/src/game/role/PathSign.cs
index 0b7f03e..3925315 100644
--- a/DungeonShooting_Godot/src/game/role/PathSign.cs
+++ b/DungeonShooting_Godot/src/game/role/PathSign.cs
@@ -4,24 +4,68 @@
///
/// 寻路标记, 记录下Role移动过的位置, 用于Ai寻路
///
-public class PathSign : Node2D
+public class PathSign : Node2D, IDestroy
{
+ public bool IsDestroyed { get; private set; }
+
///
- /// 是否启用
+ /// 当前标记在整个链上的索引
///
- public bool Enable { get; set; }
+ public int Index { get; }
+
+ ///
+ /// 监视的对象
+ ///
+ public Role Target { get; }
+
+ ///
+ /// 视野半径
+ ///
+ public float ViewRadius { get; }
+
+ ///
+ /// 射线对象
+ ///
+ public RayCast2D RayCast { get; }
+
+ ///
+ /// 连接的上一个 PathSign
+ ///
+ public PathSign Prev { get; set; }
+
+ ///
+ /// 连接的下一个 PathSign
+ ///
+ public PathSign Next { get; set; }
+
+ private Vector2 _prevTargetPos;
///
/// 创建标记
///
/// 坐标
- /// 用于debug, 显示箭头
- public PathSign(Vector2 pos, bool debug = false)
+ /// 视野半径
+ /// 监视对象
+ public PathSign(Vector2 pos, float viewRadius, Role target) : this(pos, viewRadius, target, 0, null)
{
+ }
+
+ private PathSign(Vector2 pos, float viewRadius, Role target, int index, PathSign prev)
+ {
+ Index = index;
+ Prev = prev;
+ Target = target;
+ ViewRadius = viewRadius;
GameApplication.Instance.Room.GetRoot(false).AddChild(this);
GlobalPosition = pos;
- if (debug)
+ //目前只检测墙壁碰撞
+ RayCast = new RayCast2D();
+ RayCast.CollisionMask = PhysicsLayer.Wall;
+ AddChild(RayCast);
+
+ //绘制箭头
+ if (GameApplication.Instance.Debug)
{
var sprite = new Sprite();
sprite.Texture = ResourceManager.Load(ResourcePath.resource_effects_debug_arrows_png);
@@ -29,4 +73,63 @@
AddChild(sprite);
}
}
+
+ public override void _Process(float delta)
+ {
+ base._Process(delta);
+ if (GameApplication.Instance.Debug)
+ {
+ Update();
+ }
+ }
+
+ public override void _PhysicsProcess(float delta)
+ {
+ if (Next == null)
+ {
+ //监视目标
+ var targetPos = Target.GlobalPosition;
+ if (GlobalPosition.DistanceSquaredTo(targetPos) <= ViewRadius * ViewRadius) //在视野范围内
+ {
+ RayCast.Enabled = true;
+ RayCast.CastTo = RayCast.ToLocal(targetPos);
+ RayCast.ForceRaycastUpdate();
+
+ if (RayCast.IsColliding())
+ {
+ Next = new PathSign(_prevTargetPos, ViewRadius, Target, Index + 1, this);
+ }
+ RayCast.Enabled = false;
+ _prevTargetPos = targetPos;
+ }
+ }
+ }
+
+ public void Destroy()
+ {
+ if (IsDestroyed)
+ {
+ return;
+ }
+
+ IsDestroyed = true;
+
+ if (Next != null)
+ {
+ Next.Destroy();
+ }
+
+ QueueFree();
+ }
+
+ public override void _Draw()
+ {
+ if (GameApplication.Instance.Debug)
+ {
+ if (Next != null)
+ {
+ DrawLine(Vector2.Zero,ToLocal(Next.GlobalPosition), Colors.Red);
+ }
+ }
+ }
}
diff --git a/DungeonShooting_Godot/src/game/role/Player.cs b/DungeonShooting_Godot/src/game/role/Player.cs
index 5e0d434..0671568 100644
--- a/DungeonShooting_Godot/src/game/role/Player.cs
+++ b/DungeonShooting_Godot/src/game/role/Player.cs
@@ -14,15 +14,6 @@
///
public float Friction { get; set; } = 800f;
- //----------------------- 寻路相关 ----------------------------
-
- //路径标记点总个数
- private int _signLength = 15;
- //存放所有路径点
- private readonly List _pathSignList = new List();
-
- //-------------------------------------------------------------
-
public Player(): base(ResourcePath.prefab_role_Player_tscn)
{
AttackLayer = PhysicsLayer.Wall | PhysicsLayer.Props | PhysicsLayer.Enemy;
@@ -212,7 +203,7 @@
CalcMove(delta);
}
-
+
// 播放动画
private void PlayAnim()
{
diff --git a/DungeonShooting_Godot/src/game/role/Role.cs b/DungeonShooting_Godot/src/game/role/Role.cs
index 7720549..24ecc4c 100644
--- a/DungeonShooting_Godot/src/game/role/Role.cs
+++ b/DungeonShooting_Godot/src/game/role/Role.cs
@@ -302,6 +302,28 @@
}
///
+ /// 使角色看向指定的坐标,
+ /// 注意, 调用该函数会清空 LookTarget, 因为拥有 LookTarget 会每帧更新玩家视野位置
+ ///
+ ///
+ public void LookTargetPosition(Vector2 pos)
+ {
+ LookTarget = null;
+ //脸的朝向
+ var gPos = GlobalPosition;
+ if (pos.x > gPos.x && Face == FaceDirection.Left)
+ {
+ Face = FaceDirection.Right;
+ }
+ else if (pos.x < gPos.x && Face == FaceDirection.Right)
+ {
+ Face = FaceDirection.Left;
+ }
+ //枪口跟随目标
+ MountPoint.SetLookAt(pos);
+ }
+
+ ///
/// 判断指定坐标是否在角色视野方向
///
public bool IsPositionInForward(Vector2 pos)
diff --git a/DungeonShooting_Godot/src/game/role/enemy/Enemy.cs b/DungeonShooting_Godot/src/game/role/enemy/Enemy.cs
index e293d65..1a93b89 100644
--- a/DungeonShooting_Godot/src/game/role/enemy/Enemy.cs
+++ b/DungeonShooting_Godot/src/game/role/enemy/Enemy.cs
@@ -39,6 +39,15 @@
///
public RayCast2D ViewRay { get; }
+ //------------------- 寻路相关 ---------------------------
+
+
+ private PathSign _pathSign;
+ //上一帧玩家位置
+ private Vector2 _prevPlayerPos;
+
+ //-------------------------------------------------------
+
public Enemy() : base(ResourcePath.prefab_role_Enemy_tscn)
{
StateController = new StateController();
@@ -59,6 +68,15 @@
StateController.ChangeState(StateEnum.Idle);
}
+ public override void _Process(float delta)
+ {
+ base._Process(delta);
+ if (GameApplication.Instance.Debug)
+ {
+ Update();
+ }
+ }
+
public override void _PhysicsProcess(float delta)
{
base._PhysicsProcess(delta);
@@ -83,24 +101,46 @@
ViewRay.CastTo = localPos;
ViewRay.ForceRaycastUpdate();
- if (ViewRay.IsColliding())
+ if (ViewRay.IsColliding()) //在视野范围内, 但是碰到墙壁
{
+ if (_pathSign == null) //路径标记
+ {
+ _pathSign = new PathSign(_prevPlayerPos, ViewRange, player);
+ }
LookTarget = null;
StateController.ChangeState(StateEnum.Idle);
}
- else
+ else //视野无阻
{
+ if (_pathSign != null) //删除路径标记
+ {
+ _pathSign.Destroy();
+ _pathSign = null;
+ }
+
LookTarget = player;
StateController.ChangeState(StateEnum.Run);
}
ViewRay.Enabled = false;
}
- else
+ else //超出视野半径
{
LookTarget = null;
StateController.ChangeState(StateEnum.Idle);
}
+ _prevPlayerPos = playerPos;
+ }
+ }
+
+ public override void _Draw()
+ {
+ if (GameApplication.Instance.Debug)
+ {
+ if (_pathSign != null)
+ {
+ DrawLine(Vector2.Zero,ToLocal(_pathSign.GlobalPosition), Colors.Red);
+ }
}
}
}