diff --git a/DungeonShooting_Godot/DungeonShooting.sln.DotSettings.user b/DungeonShooting_Godot/DungeonShooting.sln.DotSettings.user
index 5ef2d60..66f7988 100644
--- a/DungeonShooting_Godot/DungeonShooting.sln.DotSettings.user
+++ b/DungeonShooting_Godot/DungeonShooting.sln.DotSettings.user
@@ -1,2 +1,5 @@
- WARNING
\ No newline at end of file
+ WARNING
+ <AssemblyExplorer>
+ <Assembly Path="D:\GameProject\DungeonShooting\DungeonShooting_Godot\.mono\assemblies\Debug\GodotSharp.dll" />
+</AssemblyExplorer>
\ No newline at end of file
diff --git a/DungeonShooting_Godot/prefab/role/Player.tscn b/DungeonShooting_Godot/prefab/role/Player.tscn
index 7154560..7bfb950 100644
--- a/DungeonShooting_Godot/prefab/role/Player.tscn
+++ b/DungeonShooting_Godot/prefab/role/Player.tscn
@@ -24,4 +24,4 @@
[node name="AnimatedSprite" parent="." index="2"]
material = SubResource( 2 )
-frame = 1
+frame = 3
diff --git a/DungeonShooting_Godot/src/game/GameApplication.cs b/DungeonShooting_Godot/src/game/GameApplication.cs
index 587b2f2..c2aec78 100644
--- a/DungeonShooting_Godot/src/game/GameApplication.cs
+++ b/DungeonShooting_Godot/src/game/GameApplication.cs
@@ -61,6 +61,7 @@
public override void _EnterTree()
{
+ GD.Randomize();
ActivityObject.IsDebug = Debug;
GlobalNodeRoot = GetNode(GlobalNodeRootPath);
diff --git a/DungeonShooting_Godot/src/game/role/StateBase.cs b/DungeonShooting_Godot/src/game/role/StateBase.cs
index d2a7586..c4d2d17 100644
--- a/DungeonShooting_Godot/src/game/role/StateBase.cs
+++ b/DungeonShooting_Godot/src/game/role/StateBase.cs
@@ -49,7 +49,7 @@
}
///
- /// 是否允许切换至下一个状态
+ /// 是否允许切换至下一个状态, 该函数由状态机控制器调用, 不需要手动调用
///
/// 下一个状态类型
public virtual bool CanChangeState(S next)
diff --git a/DungeonShooting_Godot/src/game/role/enemy/Enemy.cs b/DungeonShooting_Godot/src/game/role/enemy/Enemy.cs
index dc0bfb4..98940e9 100644
--- a/DungeonShooting_Godot/src/game/role/enemy/Enemy.cs
+++ b/DungeonShooting_Godot/src/game/role/enemy/Enemy.cs
@@ -18,7 +18,6 @@
///
public class Enemy : Role
{
-
///
/// 敌人身上的状态机控制器
///
@@ -109,13 +108,19 @@
///
/// 调用视野检测, 如果被墙壁和其它物体遮挡, 则返回被挡住视野的物体对象, 视野无阻则返回 null
///
- public Godot.Object TestViewRayCast(Vector2 target)
+ public bool TestViewRayCast(Vector2 target)
{
ViewRay.Enabled = true;
ViewRay.CastTo = ViewRay.ToLocal(target);
ViewRay.ForceRaycastUpdate();
- var collObj = ViewRay.GetCollider();
+ return ViewRay.IsColliding();
+ }
+
+ ///
+ /// 调用视野检测完毕后, 需要调用 TestViewRayCastOver() 来关闭视野检测射线
+ ///
+ public void TestViewRayCastOver()
+ {
ViewRay.Enabled = false;
- return collObj;
}
}
diff --git a/DungeonShooting_Godot/src/game/role/enemy/state/AiNormalState.cs b/DungeonShooting_Godot/src/game/role/enemy/state/AiNormalState.cs
index 8eb006b..03a0d35 100644
--- a/DungeonShooting_Godot/src/game/role/enemy/state/AiNormalState.cs
+++ b/DungeonShooting_Godot/src/game/role/enemy/state/AiNormalState.cs
@@ -6,21 +6,76 @@
///
public class AiNormalState : StateBase
{
+ //是否发现玩家
+ private bool _isFindPlayer;
+ //下一个运动的角度
+ private Vector2 _nextPos;
+ //是否移动结束
+ private bool _isMoveOver;
+
public AiNormalState() : base(AIStateEnum.AINormal)
{
}
-
+
+ public override void Enter(AIStateEnum prev, params object[] args)
+ {
+ _isFindPlayer = false;
+ _isMoveOver = true;
+ }
+
public override void PhysicsProcess(float delta)
{
- //检测玩家
- var player = GameApplication.Instance.Room.Player;
- //玩家中心点坐标
- var playerPos = player.MountPoint.GlobalPosition;
- if (Master.IsInViewRange(playerPos) && Master.TestViewRayCast(playerPos) == null)
+ if (_isFindPlayer) //已经找到玩家了
{
- //发现玩家
+ //现临时处理, 直接切换状态
ChangeStateLate(AIStateEnum.AITailAfter);
}
+ else //没有找到玩家
+ {
+ //检测玩家
+ var player = GameApplication.Instance.Room.Player;
+ //玩家中心点坐标
+ var playerPos = player.MountPoint.GlobalPosition;
+
+ if (Master.IsInViewRange(playerPos) && !Master.TestViewRayCast(playerPos)) //发现玩家
+ {
+ //发现玩家
+ _isFindPlayer = true;
+ }
+ else if (_isMoveOver) //没发现玩家, 且已经移动完成
+ {
+ var angle = Utils.RandRange(0, Mathf.Pi * 2f);
+ var len = Utils.RandRangeInt(50, 500);
+ _nextPos = new Vector2(len, 0).Rotated(angle);
+ //获取射线碰到的坐标
+ if (Master.TestViewRayCast(_nextPos)) //碰到墙壁
+ {
+ _nextPos = Master.ViewRay.GetCollisionPoint();
+ }
+ Master.NavigationAgent2D.SetTargetLocation(_nextPos);
+ _isMoveOver = false;
+ }
+ else //移动中
+ {
+ //计算移动
+ var nextPos = Master.NavigationAgent2D.GetNextLocation();
+ Master.LookTargetPosition(_nextPos);
+ Master.AnimatedSprite.Animation = AnimatorNames.Run;
+ Master.Velocity = (nextPos - Master.GlobalPosition - Master.NavigationPoint.Position).Normalized() * Master.MoveSpeed;
+ Master.CalcMove(delta);
+
+ if (Master.NavigationAgent2D.IsNavigationFinished())
+ {
+ _isMoveOver = true;
+ }
+ }
+ Master.TestViewRayCastOver();
+ }
+ }
+
+ public override void DebugDraw()
+ {
+ Master.DrawLine(Vector2.Zero, Master.ToLocal(_nextPos), Colors.Green);
}
}
diff --git a/DungeonShooting_Godot/src/game/role/enemy/state/AiTailAfterState.cs b/DungeonShooting_Godot/src/game/role/enemy/state/AiTailAfterState.cs
index 07396bc..5ff99ac 100644
--- a/DungeonShooting_Godot/src/game/role/enemy/state/AiTailAfterState.cs
+++ b/DungeonShooting_Godot/src/game/role/enemy/state/AiTailAfterState.cs
@@ -26,12 +26,11 @@
public override void PhysicsProcess(float delta)
{
- var master = Master;
- if (master.NavigationAgent2D.IsNavigationFinished())
+ if (Master.NavigationAgent2D.IsNavigationFinished())
{
return;
}
- var masterPos = master.GlobalPosition;
+ var masterPos = Master.GlobalPosition;
var playerPos = GameApplication.Instance.Room.Player.GlobalPosition;
//更新玩家位置
@@ -39,9 +38,9 @@
{
//每隔一段时间秒更改目标位置
_navigationUpdateTimer = _navigationInterval;
- if (master.NavigationAgent2D.GetTargetLocation() != playerPos)
+ if (Master.NavigationAgent2D.GetTargetLocation() != playerPos)
{
- master.NavigationAgent2D.SetTargetLocation(playerPos);
+ Master.NavigationAgent2D.SetTargetLocation(playerPos);
}
}
else
@@ -50,14 +49,14 @@
}
//计算移动
- var nextPos = master.NavigationAgent2D.GetNextLocation();
- master.LookTargetPosition(playerPos);
- master.AnimatedSprite.Animation = AnimatorNames.Run;
- master.Velocity = (nextPos - master.GlobalPosition - master.NavigationPoint.Position).Normalized() * master.MoveSpeed;
- master.CalcMove(delta);
+ var nextPos = Master.NavigationAgent2D.GetNextLocation();
+ Master.LookTargetPosition(playerPos);
+ Master.AnimatedSprite.Animation = AnimatorNames.Run;
+ Master.Velocity = (nextPos - Master.GlobalPosition - Master.NavigationPoint.Position).Normalized() * Master.MoveSpeed;
+ Master.CalcMove(delta);
//检测玩家是否在视野内, 此时视野可穿墙, 直接检测距离即可
- _isInView = masterPos.DistanceSquaredTo(playerPos) <= master.TailAfterViewRange * master.TailAfterViewRange;
+ _isInView = masterPos.DistanceSquaredTo(playerPos) <= Master.TailAfterViewRange * Master.TailAfterViewRange;
if (_isInView)
{
_viewTimer = 0;
diff --git a/DungeonShooting_Godot/src/game/room/RoomManager.cs b/DungeonShooting_Godot/src/game/room/RoomManager.cs
index 10ca35c..9a39e41 100644
--- a/DungeonShooting_Godot/src/game/room/RoomManager.cs
+++ b/DungeonShooting_Godot/src/game/room/RoomManager.cs
@@ -13,6 +13,11 @@
///
public Role Player { get; private set; }
+ ///
+ /// 导航区域形状
+ ///
+ public NavigationPolygonInstance NavigationPolygon { get; private set; }
+
//对象根节点
private Node2D _objectRoot;
@@ -21,8 +26,6 @@
private Node2D _mapRoot;
- private NavigationPolygonInstance _navigationPolygon;
-
//可行走区域的tileId
private List _wayIds = new List(new[] { 129 });
@@ -32,6 +35,8 @@
//导航区域数据
private List _polygonDataList = new List();
+ private TileMap _tileMap;
+
public override void _EnterTree()
{
Input.MouseMode = Input.MouseModeEnum.Hidden;
@@ -39,13 +44,14 @@
_sortRoot = GetNode("SortRoot");
_objectRoot = GetNode("ObjectRoot");
- //_navigationPolygon = GetNode("NavigationPolygonInstance");
- _navigationPolygon = new NavigationPolygonInstance();
- AddChild(_navigationPolygon);
+ NavigationPolygon = new NavigationPolygonInstance();
+ AddChild(NavigationPolygon);
//初始化地图
_mapRoot = GetNode("MapRoot");
- var node = _mapRoot.GetChild(0).GetNode("Config");
+ var child = _mapRoot.GetChild(0);
+ _tileMap = child.GetNode("Wall");
+ var node = child.GetNode("Config");
Color color = (Color)node.GetMeta("ClearColor");
VisualServer.SetDefaultClearColor(color);
@@ -69,7 +75,7 @@
polygon.AddOutline(polygonData.Points.ToArray());
}
polygon.MakePolygonsFromOutlines();
- _navigationPolygon.Navpoly = polygon;
+ NavigationPolygon.Navpoly = polygon;
//播放bgm
SoundManager.PlayMusic(ResourcePath.resource_sound_bgm_Intro_ogg, -17f);
@@ -132,14 +138,31 @@
}
///
+ /// 返回指定位置的Tile是否为可以行走
+ ///
+ public bool IsWayTile(int x, int y)
+ {
+ var cellId = _tileMap.GetCell(x, y);
+ return cellId != -1 && _wayIds.Contains(cellId);
+ }
+
+ ///
+ /// 返回指定坐标下对应的Tile是否为可以行走
+ ///
+ public bool IsWayPosition(float x, float y)
+ {
+ var tileMapCellSize = _tileMap.CellSize;
+ return IsWayTile((int)(x / tileMapCellSize.x), (int)(y / tileMapCellSize.y));
+ }
+
+ ///
/// 自动生成导航区域
///
private void GenerateNavigationPolygon()
{
- var tileMap = _mapRoot.GetChild(0).GetNode("Wall");
- var size = tileMap.CellSize;
+ var size = _tileMap.CellSize;
- var rect = tileMap.GetUsedRect();
+ var rect = _tileMap.GetUsedRect();
var x = (int)rect.Position.x;
var y = (int)rect.Position.y;
@@ -150,20 +173,19 @@
{
for (int i = x; i < w; i++)
{
- var tileId = tileMap.GetCell(i, j);
- if (IsWayCell(tileId))
+ if (IsWayTile(i, j))
{
if (!_usePoints.Contains(new Vector2(i, j)))
{
NavigationPolygonData polygonData = null;
- if (!IsWayCell(tileMap.GetCell(i, j - 1)))
+ if (!IsWayTile(i, j - 1))
{
- polygonData = CalcOutline(i, j, tileMap, size);
+ polygonData = CalcOutline(i, j, _tileMap, size);
}
- else if (!IsWayCell(tileMap.GetCell(i, j + 1)))
+ else if (!IsWayTile(i, j + 1))
{
- polygonData = CalcInline(i, j, tileMap, size);
+ polygonData = CalcInline(i, j, _tileMap, size);
}
if (polygonData != null)
@@ -196,7 +218,7 @@
{
case 0: //右
{
- if (IsWayCell(tileMap.GetCell(tempI, tempJ - 1))) //先向上找
+ if (IsWayTile(tempI, tempJ - 1)) //先向上找
{
dir = 3;
@@ -212,7 +234,7 @@
tempJ--;
break;
}
- else if (IsWayCell(tileMap.GetCell(tempI + 1, tempJ))) //再向右找
+ else if (IsWayTile(tempI + 1, tempJ)) //再向右找
{
if (points.Count == 0)
{
@@ -229,7 +251,7 @@
tempI++;
break;
}
- else if (IsWayCell(tileMap.GetCell(tempI, tempJ + 1))) //向下找
+ else if (IsWayTile(tempI, tempJ + 1)) //向下找
{
dir = 1;
@@ -250,7 +272,7 @@
}
case 1: //下
{
- if (IsWayCell(tileMap.GetCell(tempI + 1, tempJ))) //先向右找
+ if (IsWayTile(tempI + 1, tempJ)) //先向右找
{
dir = 0;
@@ -266,7 +288,7 @@
tempI++;
break;
}
- else if (IsWayCell(tileMap.GetCell(tempI, tempJ + 1))) //再向下找
+ else if (IsWayTile(tempI, tempJ + 1)) //再向下找
{
if (points.Count == 0)
{
@@ -283,7 +305,7 @@
tempJ++;
break;
}
- else if (IsWayCell(tileMap.GetCell(tempI - 1, tempJ))) //向左找
+ else if (IsWayTile(tempI - 1, tempJ)) //向左找
{
dir = 2;
@@ -304,7 +326,7 @@
}
case 2: //左
{
- if (IsWayCell(tileMap.GetCell(tempI, tempJ + 1))) //先向下找
+ if (IsWayTile(tempI, tempJ + 1)) //先向下找
{
dir = 1;
@@ -320,7 +342,7 @@
tempJ++;
break;
}
- else if (IsWayCell(tileMap.GetCell(tempI - 1, tempJ))) //再向左找
+ else if (IsWayTile(tempI - 1, tempJ)) //再向左找
{
if (points.Count == 0)
{
@@ -337,7 +359,7 @@
tempI--;
break;
}
- else if (IsWayCell(tileMap.GetCell(tempI, tempJ - 1))) //向上找
+ else if (IsWayTile(tempI, tempJ - 1)) //向上找
{
dir = 3;
@@ -358,7 +380,7 @@
}
case 3: //上
{
- if (IsWayCell(tileMap.GetCell(tempI - 1, tempJ))) //先向左找
+ if (IsWayTile(tempI - 1, tempJ)) //先向左找
{
dir = 2;
@@ -374,7 +396,7 @@
tempI--;
break;
}
- else if (IsWayCell(tileMap.GetCell(tempI, tempJ - 1))) //再向上找
+ else if (IsWayTile(tempI, tempJ - 1)) //再向上找
{
if (points.Count == 0)
{
@@ -391,7 +413,7 @@
tempJ--;
break;
}
- else if (IsWayCell(tileMap.GetCell(tempI + 1, tempJ))) //向右找
+ else if (IsWayTile(tempI + 1, tempJ)) //向右找
{
dir = 0;
@@ -434,7 +456,7 @@
{
case 0: //右
{
- if (IsWayCell(tileMap.GetCell(tempI, tempJ + 1))) //向下找
+ if (IsWayTile(tempI, tempJ + 1)) //向下找
{
dir = 1;
@@ -450,7 +472,7 @@
tempJ++;
break;
}
- else if (IsWayCell(tileMap.GetCell(tempI + 1, tempJ))) //再向右找
+ else if (IsWayTile(tempI + 1, tempJ)) //再向右找
{
if (points.Count == 0)
{
@@ -467,7 +489,7 @@
tempI++;
break;
}
- else if (IsWayCell(tileMap.GetCell(tempI, tempJ - 1))) //先向上找
+ else if (IsWayTile(tempI, tempJ - 1)) //先向上找
{
dir = 3;
@@ -488,7 +510,7 @@
}
case 1: //下
{
- if (IsWayCell(tileMap.GetCell(tempI - 1, tempJ))) //向左找
+ if (IsWayTile(tempI - 1, tempJ)) //向左找
{
dir = 2;
@@ -504,7 +526,7 @@
tempI--;
break;
}
- else if (IsWayCell(tileMap.GetCell(tempI, tempJ + 1))) //再向下找
+ else if (IsWayTile(tempI, tempJ + 1)) //再向下找
{
if (points.Count == 0)
{
@@ -521,7 +543,7 @@
tempJ++;
break;
}
- else if (IsWayCell(tileMap.GetCell(tempI + 1, tempJ))) //先向右找
+ else if (IsWayTile(tempI + 1, tempJ)) //先向右找
{
dir = 0;
@@ -542,7 +564,7 @@
}
case 2: //左
{
- if (IsWayCell(tileMap.GetCell(tempI, tempJ - 1))) //向上找
+ if (IsWayTile(tempI, tempJ - 1)) //向上找
{
dir = 3;
@@ -558,7 +580,7 @@
tempJ--;
break;
}
- else if (IsWayCell(tileMap.GetCell(tempI - 1, tempJ))) //再向左找
+ else if (IsWayTile(tempI - 1, tempJ)) //再向左找
{
if (points.Count == 0)
{
@@ -575,7 +597,7 @@
tempI--;
break;
}
- else if (IsWayCell(tileMap.GetCell(tempI, tempJ + 1))) //先向下找
+ else if (IsWayTile(tempI, tempJ + 1)) //先向下找
{
dir = 1;
@@ -596,7 +618,7 @@
}
case 3: //上
{
- if (IsWayCell(tileMap.GetCell(tempI + 1, tempJ))) //向右找
+ if (IsWayTile(tempI + 1, tempJ)) //向右找
{
dir = 0;
@@ -612,7 +634,7 @@
tempI++;
break;
}
- else if (IsWayCell(tileMap.GetCell(tempI, tempJ - 1))) //再向上找
+ else if (IsWayTile(tempI, tempJ - 1)) //再向上找
{
if (points.Count == 0)
{
@@ -629,7 +651,7 @@
tempJ--;
break;
}
- else if (IsWayCell(tileMap.GetCell(tempI - 1, tempJ))) //先向左找
+ else if (IsWayTile(tempI - 1, tempJ)) //先向左找
{
dir = 2;
@@ -661,9 +683,4 @@
_usePoints.Add(pos);
}
-
- private bool IsWayCell(int cellId)
- {
- return cellId != -1 && _wayIds.Contains(cellId);
- }
}
\ No newline at end of file