diff --git a/DungeonShooting_Godot/addons/dungeonShooting_plugin/ActivityObjectTemplate.cs b/DungeonShooting_Godot/addons/dungeonShooting_plugin/ActivityObjectTemplate.cs index 8ef405b..4f13314 100644 --- a/DungeonShooting_Godot/addons/dungeonShooting_plugin/ActivityObjectTemplate.cs +++ b/DungeonShooting_Godot/addons/dungeonShooting_plugin/ActivityObjectTemplate.cs @@ -35,6 +35,7 @@ public override void _Ready() { +#if TOOLS // 在工具模式下创建的 template 节点自动创建对应的必要子节点 if (Engine.EditorHint) { @@ -127,6 +128,7 @@ } } } +#endif } } } \ No newline at end of file diff --git a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs index f56c18f..1ebb968 100644 --- a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs +++ b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs @@ -50,5 +50,5 @@ }*/ } -#endif } +#endif diff --git a/DungeonShooting_Godot/export_presets.cfg b/DungeonShooting_Godot/export_presets.cfg index b17065f..f80e572 100644 --- a/DungeonShooting_Godot/export_presets.cfg +++ b/DungeonShooting_Godot/export_presets.cfg @@ -1,72 +1,5 @@ [preset.0] -name="UWP" -platform="UWP" -runnable=true -custom_features="" -export_filter="all_resources" -include_filter="" -exclude_filter="" -export_path="" -script_export_mode=1 -script_encryption_key="" - -[preset.0.options] - -custom_template/debug="" -custom_template/release="" -architecture/target=1 -command_line/extra_args="" -package/display_name="" -package/short_name="" -package/unique_name="" -package/description="" -package/publisher="" -package/publisher_display_name="" -identity/product_guid="" -identity/publisher_guid="" -signing/certificate="" -signing/password="" -signing/algorithm=2 -version/major=1 -version/minor=0 -version/build=0 -version/revision=0 -orientation/landscape=true -orientation/portrait=true -orientation/landscape_flipped=true -orientation/portrait_flipped=true -images/background_color="transparent" -tiles/show_name_on_square150x150=false -tiles/show_name_on_wide310x150=false -tiles/show_name_on_square310x310=false -capabilities/allJoyn=false -capabilities/codeGeneration=false -capabilities/internetClient=false -capabilities/internetClientServer=false -capabilities/privateNetworkClientServer=false -capabilities/appointments=false -capabilities/blockedChatMessages=false -capabilities/chat=false -capabilities/contacts=false -capabilities/enterpriseAuthentication=false -capabilities/musicLibrary=false -capabilities/objects3D=false -capabilities/picturesLibrary=false -capabilities/phoneCall=false -capabilities/removableStorage=false -capabilities/sharedUserCertificates=false -capabilities/userAccountInformation=false -capabilities/videosLibrary=false -capabilities/voipCall=false -capabilities/bluetooth=false -capabilities/location=false -capabilities/microphone=false -capabilities/proximity=false -capabilities/webcam=false - -[preset.1] - name="Android" platform="Android" runnable=true @@ -78,7 +11,7 @@ script_export_mode=1 script_encryption_key="" -[preset.1.options] +[preset.0.options] custom_template/debug="" custom_template/release="" @@ -271,7 +204,7 @@ permissions/write_sync_settings=false permissions/write_user_dictionary=false -[preset.2] +[preset.1] name="Windows Desktop" platform="Windows Desktop" @@ -280,11 +213,11 @@ export_filter="all_resources" include_filter="" exclude_filter="" -export_path="" +export_path="../../export/test/test.exe" script_export_mode=1 script_encryption_key="" -[preset.2.options] +[preset.1.options] custom_template/debug="" custom_template/release="" @@ -314,7 +247,7 @@ application/copyright="" application/trademarks="" -[preset.3] +[preset.2] name="iOS" platform="iOS" @@ -327,7 +260,7 @@ script_export_mode=1 script_encryption_key="" -[preset.3.options] +[preset.2.options] custom_template/debug="" custom_template/release="" diff --git a/DungeonShooting_Godot/prefab/role/Enemy.tscn b/DungeonShooting_Godot/prefab/role/Enemy.tscn index ae7b5d5..39588f5 100644 --- a/DungeonShooting_Godot/prefab/role/Enemy.tscn +++ b/DungeonShooting_Godot/prefab/role/Enemy.tscn @@ -36,3 +36,5 @@ position = Vector2( 0, -5 ) [node name="NavigationAgent2D" type="NavigationAgent2D" parent="NavigationPoint" index="0"] +avoidance_enabled = true +radius = 20.0 diff --git a/DungeonShooting_Godot/src/game/event/EventEnum.cs b/DungeonShooting_Godot/src/game/event/EventEnum.cs index 7e59f96..ec25a87 100644 --- a/DungeonShooting_Godot/src/game/event/EventEnum.cs +++ b/DungeonShooting_Godot/src/game/event/EventEnum.cs @@ -4,8 +4,5 @@ /// public enum EventEnum { - /// - /// 敌人发现玩家 - /// - OnEnemyFindPlayer, + Test, } diff --git a/DungeonShooting_Godot/src/game/role/Characters/CPlusPlus.cs b/DungeonShooting_Godot/src/game/role/Characters/CPlusPlus.cs index 6b8a91d..b963240 100644 --- a/DungeonShooting_Godot/src/game/role/Characters/CPlusPlus.cs +++ b/DungeonShooting_Godot/src/game/role/Characters/CPlusPlus.cs @@ -14,7 +14,7 @@ // 每个角色都应该有对应的被动 属性 专属武器 #endregion -public class CPlusPlus : Role +public class CPlusPlus : Player { diff --git a/DungeonShooting_Godot/src/game/role/Player.cs b/DungeonShooting_Godot/src/game/role/Player.cs index 19836f6..8f08799 100644 --- a/DungeonShooting_Godot/src/game/role/Player.cs +++ b/DungeonShooting_Godot/src/game/role/Player.cs @@ -1,8 +1,16 @@ using System.Collections.Generic; using Godot; + +/// +/// 玩家角色基类, 所有角色都必须继承该类 +/// public class Player : Role { + /// + /// 获取当前操作的角色 + /// + public static Player Current => GameApplication.Instance.Room.Player; /// /// 移动加速度 diff --git a/DungeonShooting_Godot/src/game/role/enemy/Enemy.cs b/DungeonShooting_Godot/src/game/role/enemy/Enemy.cs index 3d9a920..0d21d27 100644 --- a/DungeonShooting_Godot/src/game/role/enemy/Enemy.cs +++ b/DungeonShooting_Godot/src/game/role/enemy/Enemy.cs @@ -21,9 +21,14 @@ { /// - /// 公共属性, 是否找到玩家, 如果找到玩家, 则所有敌人都会知道玩家的位置 + /// 公共属性, 是否找到目标, 如果找到目标, 则所有敌人都会知道玩家的位置 /// - public static bool IsFindPlayer { get; set; } + public static bool IsFindTarget { get; private set; } + + /// + /// 找到的目标的位置, 如果目标在视野内, 则一直更新 + /// + public static Vector2 FindTargetPosition { get; private set; } private static readonly List _enemies = new List(); @@ -63,7 +68,6 @@ public Position2D NavigationPoint { get; } private float _enemyAttackTimer = 0; - private EventBinder _eventBinder; public Enemy() : base(ResourcePath.prefab_role_Enemy_tscn) { @@ -96,6 +100,9 @@ public override void _Ready() { base._Ready(); + //防撞速度计算 + NavigationAgent2D.Connect("velocity_computed", this, nameof(OnVelocityComputed)); + //默认状态 StateController.ChangeState(AiStateEnum.AiNormal); @@ -108,14 +115,11 @@ { _enemies.Add(this); } - _eventBinder = EventManager.AddEventListener(EventEnum.OnEnemyFindPlayer, OnEnemyFindPlayer); } public override void _ExitTree() { _enemies.Remove(this); - _eventBinder.RemoveEventListener(); - _eventBinder = null; } public override void _PhysicsProcess(float delta) @@ -130,11 +134,15 @@ /// public static void UpdateEnemiesView() { + IsFindTarget = false; for (var i = 0; i < _enemies.Count; i++) { var enemy = _enemies[i]; - - //enemy.StateController.GetState() + if (enemy.StateController.CurrState == AiStateEnum.AiTargetInView) //目标在视野内 + { + IsFindTarget = true; + FindTargetPosition = Player.Current.GetCenterPosition(); + } } } @@ -213,15 +221,9 @@ { ViewRay.Enabled = false; } - - //其他敌人发现玩家 - private void OnEnemyFindPlayer(object obj) + + private void OnVelocityComputed(Vector2 velocity) { - var state = StateController.CurrState; - if (state != AiStateEnum.AiLeaveFor && state != AiStateEnum.AiTailAfter && state != AiStateEnum.AiTargetInView) - { - //前往指定地点 - StateController.ChangeStateLate(AiStateEnum.AiLeaveFor, GameApplication.Instance.Room.Player.GetCenterPosition()); - } + GD.Print("velocity: " + velocity); } } diff --git a/DungeonShooting_Godot/src/game/role/enemy/state/AiLeaveForState.cs b/DungeonShooting_Godot/src/game/role/enemy/state/AiLeaveForState.cs index 6cb48a9..23cce4e 100644 --- a/DungeonShooting_Godot/src/game/role/enemy/state/AiLeaveForState.cs +++ b/DungeonShooting_Godot/src/game/role/enemy/state/AiLeaveForState.cs @@ -6,29 +6,46 @@ /// public class AiLeaveForState : StateBase { - private Vector2 _targetPosition; - + //导航目标点刷新计时器 + private float _navigationUpdateTimer = 0; + private float _navigationInterval = 0.3f; + public AiLeaveForState() : base(AiStateEnum.AiLeaveFor) { } public override void Enter(AiStateEnum prev, params object[] args) { - if (args.Length > 0 && args[0] is Vector2 pos) + if (Enemy.IsFindTarget) { - UpdateTargetPosition(pos); + Master.NavigationAgent2D.SetTargetLocation(Enemy.FindTargetPosition); } else { - ChangeState(AiStateEnum.AiNormal); + ChangeStateLate(prev); } } public override void PhysicsProcess(float delta) { + //更新玩家位置 + if (_navigationUpdateTimer <= 0) + { + //每隔一段时间秒更改目标位置 + _navigationUpdateTimer = _navigationInterval; + if (Master.NavigationAgent2D.GetTargetLocation() != Enemy.FindTargetPosition) + { + Master.NavigationAgent2D.SetTargetLocation(Enemy.FindTargetPosition); + } + } + else + { + _navigationUpdateTimer -= delta; + } + //计算移动 var nextPos = Master.NavigationAgent2D.GetNextLocation(); - Master.LookTargetPosition(_targetPosition); + Master.LookTargetPosition(Enemy.FindTargetPosition); Master.AnimatedSprite.Animation = AnimatorNames.Run; Master.Velocity = (nextPos - Master.GlobalPosition - Master.NavigationPoint.Position).Normalized() * Master.MoveSpeed; @@ -44,8 +61,6 @@ Master.TestViewRayCastOver(); //切换成发现目标状态 ChangeStateLate(AiStateEnum.AiTargetInView); - //派发发现玩家事件 - EventManager.EmitEvent(EventEnum.OnEnemyFindPlayer); return; } else @@ -62,9 +77,8 @@ } } - public void UpdateTargetPosition(Vector2 pos) + public override void DebugDraw() { - _targetPosition = pos; - Master.NavigationAgent2D.SetTargetLocation(pos); + Master.DrawLine(Vector2.Zero, Master.ToLocal(Master.NavigationAgent2D.GetTargetLocation()), Colors.Yellow); } } diff --git a/DungeonShooting_Godot/src/game/role/enemy/state/AiNormalState.cs b/DungeonShooting_Godot/src/game/role/enemy/state/AiNormalState.cs index 9e51c18..3752b51 100644 --- a/DungeonShooting_Godot/src/game/role/enemy/state/AiNormalState.cs +++ b/DungeonShooting_Godot/src/game/role/enemy/state/AiNormalState.cs @@ -39,7 +39,13 @@ public override void PhysicsProcess(float delta) { - + //其他敌人发现玩家 + if (Enemy.IsFindTarget) + { + ChangeStateLate(AiStateEnum.AiLeaveFor); + return; + } + if (_isFindPlayer) //已经找到玩家了 { //现临时处理, 直接切换状态 diff --git a/DungeonShooting_Godot/src/game/role/enemy/state/AiProbeState.cs b/DungeonShooting_Godot/src/game/role/enemy/state/AiProbeState.cs index 9e610d1..ba9c11d 100644 --- a/DungeonShooting_Godot/src/game/role/enemy/state/AiProbeState.cs +++ b/DungeonShooting_Godot/src/game/role/enemy/state/AiProbeState.cs @@ -7,4 +7,14 @@ public AiProbeState() : base(AiStateEnum.AiProbe) { } + + public override void PhysicsProcess(float delta) + { + //其他敌人发现玩家 + if (Enemy.IsFindTarget) + { + ChangeStateLate(AiStateEnum.AiLeaveFor); + return; + } + } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/role/enemy/state/AiTailAfterState.cs b/DungeonShooting_Godot/src/game/role/enemy/state/AiTailAfterState.cs index 1bd0e91..5e140d3 100644 --- a/DungeonShooting_Godot/src/game/role/enemy/state/AiTailAfterState.cs +++ b/DungeonShooting_Godot/src/game/role/enemy/state/AiTailAfterState.cs @@ -64,8 +64,6 @@ Master.TestViewRayCastOver(); //切换成发现目标状态 ChangeStateLate(AiStateEnum.AiTargetInView); - //派发发现玩家事件 - EventManager.EmitEvent(EventEnum.OnEnemyFindPlayer); return; } else diff --git a/DungeonShooting_Godot/src/game/room/RoomManager.cs b/DungeonShooting_Godot/src/game/room/RoomManager.cs index 9643006..8fca170 100644 --- a/DungeonShooting_Godot/src/game/room/RoomManager.cs +++ b/DungeonShooting_Godot/src/game/room/RoomManager.cs @@ -11,7 +11,7 @@ /// /// 玩家对象 /// - public Role Player { get; private set; } + public Player Player { get; private set; } /// /// 导航区域形状 @@ -112,6 +112,7 @@ public override void _Process(float delta) { + Enemy.UpdateEnemiesView(); if (GameApplication.Instance.Debug) { Update();