diff --git a/DungeonShooting_Godot/excel/excelFile/ActivityBase.xlsx b/DungeonShooting_Godot/excel/excelFile/ActivityBase.xlsx index bd6a11a..818426b 100644 --- a/DungeonShooting_Godot/excel/excelFile/ActivityBase.xlsx +++ b/DungeonShooting_Godot/excel/excelFile/ActivityBase.xlsx Binary files differ diff --git a/DungeonShooting_Godot/excel/excelFile/ActivityMaterial.xlsx b/DungeonShooting_Godot/excel/excelFile/ActivityMaterial.xlsx index e5d3df5..8f9e321 100644 --- a/DungeonShooting_Godot/excel/excelFile/ActivityMaterial.xlsx +++ b/DungeonShooting_Godot/excel/excelFile/ActivityMaterial.xlsx Binary files differ diff --git a/DungeonShooting_Godot/excel/excelFile/AiAttackAttr.xlsx b/DungeonShooting_Godot/excel/excelFile/AiAttackAttr.xlsx index 424da67..7491120 100644 --- a/DungeonShooting_Godot/excel/excelFile/AiAttackAttr.xlsx +++ b/DungeonShooting_Godot/excel/excelFile/AiAttackAttr.xlsx Binary files differ diff --git a/DungeonShooting_Godot/excel/excelFile/BulletBase.xlsx b/DungeonShooting_Godot/excel/excelFile/BulletBase.xlsx index afd438c..eb1663d 100644 --- a/DungeonShooting_Godot/excel/excelFile/BulletBase.xlsx +++ b/DungeonShooting_Godot/excel/excelFile/BulletBase.xlsx Binary files differ diff --git a/DungeonShooting_Godot/excel/excelFile/Sound.xlsx b/DungeonShooting_Godot/excel/excelFile/Sound.xlsx index 6bd1742..18536a3 100644 --- a/DungeonShooting_Godot/excel/excelFile/Sound.xlsx +++ b/DungeonShooting_Godot/excel/excelFile/Sound.xlsx Binary files differ diff --git a/DungeonShooting_Godot/excel/excelFile/WeaponBase.xlsx b/DungeonShooting_Godot/excel/excelFile/WeaponBase.xlsx index 88e9e65..def9693 100644 --- a/DungeonShooting_Godot/excel/excelFile/WeaponBase.xlsx +++ b/DungeonShooting_Godot/excel/excelFile/WeaponBase.xlsx Binary files differ diff --git a/DungeonShooting_Godot/prefab/role/Enemy0002.tscn b/DungeonShooting_Godot/prefab/role/Enemy0002.tscn index 3fe20e2..bebc437 100644 --- a/DungeonShooting_Godot/prefab/role/Enemy0002.tscn +++ b/DungeonShooting_Godot/prefab/role/Enemy0002.tscn @@ -27,7 +27,7 @@ shader_parameter/outline_rainbow = false shader_parameter/outline_use_blend = true -[sub_resource type="Animation" id="Animation_wn6ao"] +[sub_resource type="Animation" id="Animation_g3he5"] resource_name = "attack" length = 0.6 tracks/0/type = "value" @@ -37,10 +37,10 @@ tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/keys = { -"times": PackedFloat32Array(0, 0.6), -"transitions": PackedFloat32Array(1, 1), +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), "update": 1, -"values": [&"attack", &"idle"] +"values": [&"attack"] } tracks/1/type = "value" tracks/1/imported = false @@ -65,11 +65,11 @@ "transitions": PackedFloat32Array(1), "values": [{ "args": [], -"method": &"ShootBullet" +"method": &"Attack" }] } -[sub_resource type="Animation" id="Animation_0iqth"] +[sub_resource type="Animation" id="Animation_4j2gl"] length = 0.001 tracks/0/type = "value" tracks/0/imported = false @@ -93,22 +93,21 @@ "times": PackedFloat32Array(0), "transitions": PackedFloat32Array(1), "update": 1, -"values": [5] +"values": [0] } -[sub_resource type="AnimationLibrary" id="AnimationLibrary_wxs4x"] +[sub_resource type="AnimationLibrary" id="AnimationLibrary_oris7"] _data = { -"RESET": SubResource("Animation_0iqth"), -"attack": SubResource("Animation_wn6ao") +"RESET": SubResource("Animation_4j2gl"), +"attack": SubResource("Animation_g3he5") } -[node name="Enemy0002" node_paths=PackedStringArray("ViewRay", "NavigationAgent2D", "NavigationPoint", "FirePoint", "AnimationPlayer", "HurtArea", "HurtCollision", "InteractiveArea", "InteractiveCollision", "ShadowSprite", "AnimatedSprite", "Collision") instance=ExtResource("1_rikvp")] +[node name="Enemy0002" node_paths=PackedStringArray("ViewRay", "NavigationAgent2D", "NavigationPoint", "FirePoint", "HurtArea", "HurtCollision", "InteractiveArea", "InteractiveCollision", "ShadowSprite", "AnimatedSprite", "Collision", "AnimationPlayer") instance=ExtResource("1_rikvp")] script = ExtResource("2_wjtfl") ViewRay = NodePath("ViewRay") NavigationAgent2D = NodePath("NavigationPoint/NavigationAgent2D") NavigationPoint = NodePath("NavigationPoint") FirePoint = NodePath("AnimatedSprite/FirePoint") -AnimationPlayer = NodePath("AnimationPlayer") HurtArea = NodePath("HurtArea") HurtCollision = NodePath("HurtArea/HurtCollision") InteractiveArea = NodePath("InteractiveArea") @@ -116,6 +115,7 @@ ShadowSprite = NodePath("ShadowSprite") AnimatedSprite = NodePath("AnimatedSprite") Collision = NodePath("Collision") +AnimationPlayer = NodePath("AnimationPlayer") [node name="ShadowSprite" parent="." index="0"] material = SubResource("ShaderMaterial_7theg") @@ -125,12 +125,11 @@ position = Vector2(0, -10) sprite_frames = ExtResource("4_ehtyi") animation = &"attack" -frame = 5 [node name="FirePoint" type="Marker2D" parent="AnimatedSprite" index="0"] position = Vector2(9, 4) [node name="AnimationPlayer" type="AnimationPlayer" parent="." index="7"] libraries = { -"": SubResource("AnimationLibrary_wxs4x") +"": SubResource("AnimationLibrary_oris7") } diff --git a/DungeonShooting_Godot/resource/config/AiAttackAttr.json b/DungeonShooting_Godot/resource/config/AiAttackAttr.json index 3d27a46..251daae 100644 --- a/DungeonShooting_Godot/resource/config/AiAttackAttr.json +++ b/DungeonShooting_Godot/resource/config/AiAttackAttr.json @@ -2,6 +2,7 @@ { "Id": "0001", "Remark": "", + "LockingStand": true, "FiringStand": true, "ShowSubline": false, "LockingTime": 1, @@ -13,6 +14,7 @@ { "Id": "0002", "Remark": "", + "LockingStand": true, "FiringStand": true, "ShowSubline": false, "LockingTime": 2, @@ -24,6 +26,7 @@ { "Id": "0003", "Remark": "", + "LockingStand": true, "FiringStand": true, "ShowSubline": false, "LockingTime": 1, @@ -35,6 +38,7 @@ { "Id": "0004", "Remark": "\u79FB\u52A8\u5C04\u51FB", + "LockingStand": false, "FiringStand": false, "ShowSubline": false, "LockingTime": 0.7, @@ -46,6 +50,7 @@ { "Id": "0005", "Remark": "\u4F7F\u7528\u8FDC\u8DDD\u79BB\u6B66\u5668", + "LockingStand": true, "FiringStand": true, "ShowSubline": true, "LockingTime": 1.5, @@ -57,6 +62,7 @@ { "Id": "0006", "Remark": "", + "LockingStand": true, "FiringStand": true, "ShowSubline": false, "LockingTime": 0.5, @@ -68,6 +74,7 @@ { "Id": "0007", "Remark": "\u6FC0\u5149\u6B66\u5668", + "LockingStand": true, "FiringStand": true, "ShowSubline": true, "LockingTime": 1.5, @@ -79,6 +86,7 @@ { "Id": "0008", "Remark": "\u69B4\u5F39\u70AE", + "LockingStand": true, "FiringStand": true, "ShowSubline": false, "LockingTime": 1.5, diff --git a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preinstall.json b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preinstall.json index c401b01..09e0c14 100644 --- a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preinstall.json +++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preinstall.json @@ -1 +1 @@ -[{"Name":"test1","Weight":100,"Remark":"","WaveList":[[{"Position":{"X":19,"Y":2},"Size":{"X":0,"Y":0},"SpecialMarkType":1,"DelayTime":0,"MarkList":[]},{"Position":{"X":24,"Y":-14},"Size":{"X":0,"Y":0},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0001","Weight":100,"Attr":{"CurrAmmon":"30","ResidueAmmo":"210"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":6,"Y":34},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0002","Weight":100,"Attr":{"CurrAmmon":"7","ResidueAmmo":"70"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-42,"Y":9},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0004","Weight":100,"Attr":{"CurrAmmon":"180","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-63,"Y":-18},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0005","Weight":100,"Attr":{"CurrAmmon":"10","ResidueAmmo":"40"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-31,"Y":-16},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0003","Weight":100,"Attr":{"CurrAmmon":"12","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-47,"Y":32},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0006","Weight":100,"Attr":{"CurrAmmon":"20","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":2,"Y":-25},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0007","Weight":100,"Attr":{"CurrAmmon":"60","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-80,"Y":14},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0008","Weight":100,"Attr":{"CurrAmmon":"10","ResidueAmmo":"120"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-75,"Y":47},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0009","Weight":100,"Attr":{"CurrAmmon":"1","ResidueAmmo":"25"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":46,"Y":1},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0011","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":36,"Y":49},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0012","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-90,"Y":-23},"Size":{"X":3,"Y":6},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0013","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-91,"Y":-6},"Size":{"X":0,"Y":0},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0014","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]}],[{"Position":{"X":57,"Y":56},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0003","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":67,"Y":28},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0.5,"MarkList":[{"Id":"prop5000","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":60,"Y":-19},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1,"MarkList":[{"Id":"prop5001","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":34,"Y":23},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1.5,"MarkList":[{"Id":"prop0002","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-11,"Y":8},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0010","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-20,"Y":33},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0010","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]}]]}] \ No newline at end of file +[{"Name":"test1","Weight":100,"Remark":"","WaveList":[[{"Position":{"X":19,"Y":2},"Size":{"X":0,"Y":0},"SpecialMarkType":1,"DelayTime":0,"MarkList":[]},{"Position":{"X":24,"Y":-14},"Size":{"X":0,"Y":0},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0001","Weight":100,"Attr":{"CurrAmmon":"30","ResidueAmmo":"210"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":6,"Y":34},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0002","Weight":100,"Attr":{"CurrAmmon":"7","ResidueAmmo":"70"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-42,"Y":9},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0004","Weight":100,"Attr":{"CurrAmmon":"180","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-63,"Y":-18},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0005","Weight":100,"Attr":{"CurrAmmon":"10","ResidueAmmo":"40"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-31,"Y":-16},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0003","Weight":100,"Attr":{"CurrAmmon":"12","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-47,"Y":32},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0006","Weight":100,"Attr":{"CurrAmmon":"20","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":2,"Y":-25},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0007","Weight":100,"Attr":{"CurrAmmon":"60","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-80,"Y":14},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0008","Weight":100,"Attr":{"CurrAmmon":"10","ResidueAmmo":"120"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-75,"Y":47},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0009","Weight":100,"Attr":{"CurrAmmon":"1","ResidueAmmo":"25"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":46,"Y":1},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0011","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":36,"Y":49},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0012","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-90,"Y":-23},"Size":{"X":3,"Y":6},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0013","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-91,"Y":-6},"Size":{"X":0,"Y":0},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0014","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]}],[{"Position":{"X":57,"Y":56},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0003","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":67,"Y":28},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0.5,"MarkList":[{"Id":"prop5000","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":60,"Y":-19},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1,"MarkList":[{"Id":"prop5001","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":34,"Y":23},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1.5,"MarkList":[{"Id":"prop0002","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-11,"Y":8},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0010","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-20,"Y":33},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0010","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":8,"Y":12},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"enemy0002","Weight":100,"Attr":{"Face":"0","Weapon":null},"Altitude":0,"VerticalSpeed":0}]}]]}] \ No newline at end of file diff --git a/DungeonShooting_Godot/resource/spriteFrames/role/Enemy0002.tres b/DungeonShooting_Godot/resource/spriteFrames/role/Enemy0002.tres index 2851e22..76aae0b 100644 --- a/DungeonShooting_Godot/resource/spriteFrames/role/Enemy0002.tres +++ b/DungeonShooting_Godot/resource/spriteFrames/role/Enemy0002.tres @@ -126,7 +126,7 @@ }], "loop": false, "name": &"attack", -"speed": 8.0 +"speed": 15.0 }, { "frames": [{ "duration": 1.0, @@ -160,7 +160,7 @@ }], "loop": true, "name": &"idle", -"speed": 8.0 +"speed": 10.0 }, { "frames": [{ "duration": 1.0, diff --git a/DungeonShooting_Godot/src/config/ExcelConfig_AiAttackAttr.cs b/DungeonShooting_Godot/src/config/ExcelConfig_AiAttackAttr.cs index 0dceead..c3c734c 100644 --- a/DungeonShooting_Godot/src/config/ExcelConfig_AiAttackAttr.cs +++ b/DungeonShooting_Godot/src/config/ExcelConfig_AiAttackAttr.cs @@ -20,6 +20,12 @@ public string Remark; /// + /// 锁定目标时是否站立不动 + /// + [JsonInclude] + public bool LockingStand; + + /// /// 开火时是否站立不动 /// [JsonInclude] @@ -75,6 +81,7 @@ var inst = new AiAttackAttr(); inst.Id = Id; inst.Remark = Remark; + inst.LockingStand = LockingStand; inst.FiringStand = FiringStand; inst.ShowSubline = ShowSubline; inst.LockingTime = LockingTime; diff --git a/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs b/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs index 109eb8e..c88e33f 100644 --- a/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs +++ b/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs @@ -59,6 +59,12 @@ /// [Export, ExportFillNode] public CollisionShape2D Collision { get; set; } + + /// + /// 动画播放器 + /// + [Export, ExportFillNode] + public AnimationPlayer AnimationPlayer { get; set; } /// /// 是否调用过 Destroy() 函数 diff --git a/DungeonShooting_Godot/src/framework/activity/components/StateController.cs b/DungeonShooting_Godot/src/framework/activity/components/StateController.cs index d33027c..f1b035c 100644 --- a/DungeonShooting_Godot/src/framework/activity/components/StateController.cs +++ b/DungeonShooting_Godot/src/framework/activity/components/StateController.cs @@ -135,6 +135,7 @@ } else if (CurrStateBase.CanChangeState(next)) { + // Debug.Log($"changeState: {CurrState} => {next}"); _isChangeState = !late; var prev = CurrStateBase.State; CurrStateBase.Exit(next); diff --git a/DungeonShooting_Godot/src/game/GameApplication.cs b/DungeonShooting_Godot/src/game/GameApplication.cs index 23d0fa6..4496067 100644 --- a/DungeonShooting_Godot/src/game/GameApplication.cs +++ b/DungeonShooting_Godot/src/game/GameApplication.cs @@ -104,7 +104,7 @@ //随机化种子 //GD.Randomize(); //固定帧率 - //Engine.MaxFps = TargetFps; + Engine.MaxFps = TargetFps; //调试绘制开关 ActivityObject.IsDebug = true; //Engine.TimeScale = 0.2f; diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs index cf69f1e..22ae399 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs @@ -67,7 +67,7 @@ /// /// Ai攻击状态, 调用 Attack() 函数后会刷新 /// - public AiAttackState AttackState { get; private set; } + public AiAttackEnum AttackState { get; private set; } /// /// 当前敌人所看向的对象, 也就是枪口指向的对象 @@ -193,7 +193,7 @@ _lockTargetTime = 0; } - if (AttackState == AiAttackState.LockingTime) //锁定玩家状态 + if (AttackState == AiAttackEnum.LockingTime) //锁定玩家状态 { var aiLockRemainderTime = GetLockRemainderTime(); MountLookTarget = aiLockRemainderTime >= weapon.Attribute.AiAttackAttr.LockAngleTime; @@ -224,7 +224,7 @@ SubLine.Enable = false; } - if (AttackState == AiAttackState.Attack || AttackState == AiAttackState.AttackInterval) + if (AttackState == AiAttackEnum.Attack || AttackState == AiAttackEnum.AttackInterval) { if (weapon.Attribute.AiAttackAttr.AttackLockAngle) //开火时锁定枪口角度 { @@ -391,7 +391,7 @@ } else //没有武器 { - AttackState = AiAttackState.NoWeapon; + AttackState = AiAttackEnum.NoWeapon; } } diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/AiAttackEnum.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/AiAttackEnum.cs new file mode 100644 index 0000000..f8e8b89 --- /dev/null +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/AiAttackEnum.cs @@ -0,0 +1,43 @@ + +/// +/// 调用 Enemy.EnemyAttack() 函数返回的结果 +/// +public enum AiAttackEnum +{ + /// + /// 未触发 EnemyAttack() + /// + None, + /// + /// 触发切换武器 + /// + ExchangeWeapon, + /// + /// 没有弹药了 + /// + NoAmmo, + /// + /// 换弹中 + /// + Reloading, + /// + /// 触发换弹 + /// + TriggerReload, + /// + /// 没有武器 + /// + NoWeapon, + /// + /// 正在锁定目标中 + /// + LockingTime, + /// + /// 攻击间隙时间 + /// + AttackInterval, + /// + /// 成功触发攻击 + /// + Attack, +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/AiAttackState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/AiAttackState.cs deleted file mode 100644 index 62bc132..0000000 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/AiAttackState.cs +++ /dev/null @@ -1,43 +0,0 @@ - -/// -/// 调用 Enemy.EnemyAttack() 函数返回的结果 -/// -public enum AiAttackState -{ - /// - /// 未触发 EnemyAttack() - /// - None, - /// - /// 触发切换武器 - /// - ExchangeWeapon, - /// - /// 没有弹药了 - /// - NoAmmo, - /// - /// 换弹中 - /// - Reloading, - /// - /// 触发换弹 - /// - TriggerReload, - /// - /// 没有武器 - /// - NoWeapon, - /// - /// 正在锁定目标中 - /// - LockingTime, - /// - /// 攻击间隙时间 - /// - AttackInterval, - /// - /// 成功触发攻击 - /// - Attack, -} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs index 4d2e634..b6f69a0 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs @@ -41,11 +41,6 @@ public float AttackRange { get; set; } = 200; /// - /// 开火时是否站立不动 - /// - public bool FiringStand { get; set; } = true; - - /// /// 视野检测射线, 朝玩家打射线, 检测是否碰到墙 /// [Export, ExportFillNode] @@ -70,25 +65,20 @@ public Marker2D FirePoint { get; private set; } /// - /// Ai攻击状态, 调用 Attack() 函数后会刷新 - /// - public AiAttackState AttackState { get; private set; } - - /// /// 攻击时间间隔 /// - public float AttackInterval { get; set; } = 3; - - /// - /// 锁定目标需要消耗的时间 - /// - public float LockingTime { get; set; } = 2; + public float AttackInterval { get; set; } = 5; /// /// 当前敌人所看向的对象, 也就是枪口指向的对象 /// public ActivityObject LookTarget { get; set; } + /// + /// Ai 攻击属性 + /// + public ExcelConfig.AiAttackAttr AttackAttribute { get; private set; } + //锁定目标时间 private float _lockTargetTime = 0; //攻击冷却计时器 @@ -97,6 +87,7 @@ public override void OnInit() { base.OnInit(); + AttackAttribute = ExcelConfig.AiAttackAttr_Map["0001"]; IsAi = true; StateController = AddComponent>(); @@ -113,6 +104,8 @@ StateController.Register(new AiTailAfterState()); StateController.Register(new AiFollowUpState()); StateController.Register(new AiSurroundState()); + StateController.Register(new AiLeaveForState()); + StateController.Register(new AiAttackState()); StateController.ChangeState(AINormalStateEnum.AiNormal); } @@ -131,20 +124,8 @@ public override void Attack() { - if (_attackTimer > 0) //开火间隙 - { - AttackState = AiAttackState.AttackInterval; - } - else if (GetLockRemainderTime() > 0) //锁定目标时间 - { - AttackState = AiAttackState.LockingTime; - } - else //正常攻击 - { - AttackState = AiAttackState.Attack; - _attackTimer = AttackInterval; - OnAttack(); - } + _attackTimer = AttackInterval; + OnAttack(); } /// @@ -188,16 +169,9 @@ } //目标在视野内的时间 var currState = StateController.CurrState; - if (currState == AINormalStateEnum.AiSurround || currState == AINormalStateEnum.AiFollowUp) + if (currState == AINormalStateEnum.AiAttack && _attackTimer <= 0) //必须在可以开火时记录时间 { - if (_attackTimer <= 0) //必须在可以开火时记录时间 - { - _lockTargetTime += delta; - } - else - { - _lockTargetTime = 0; - } + _lockTargetTime += delta; } else { @@ -324,7 +298,7 @@ /// public float GetLockRemainderTime() { - return LockingTime - _lockTargetTime; + return AttackAttribute.LockingTime - _lockTargetTime; } /// @@ -353,4 +327,32 @@ LookTarget = null; base.LookTargetPosition(pos); } + + /// + /// 获取攻击冷却计时时间, 小于等于 0 表示冷却完成 + /// + public float GetAttackTimer() + { + return _attackTimer; + } + + /// + /// 执行移动操作 + /// + public void DoMove() + { + AnimatedSprite.Play(AnimatorNames.Run); + //计算移动 + var nextPos = NavigationAgent2D.GetNextPathPosition(); + BasisVelocity = (nextPos - Position - NavigationPoint.Position).Normalized() * RoleState.MoveSpeed; + } + + /// + /// 执行站立操作 + /// + public void DoIdle() + { + AnimatedSprite.Play(AnimatorNames.Idle); + BasisVelocity = Vector2.Zero; + } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFollowUpState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFollowUpState.cs index 86bbe98..ae6ee0d 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFollowUpState.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFollowUpState.cs @@ -73,7 +73,7 @@ if (!Master.NavigationAgent2D.IsNavigationFinished()) { if (weapon == null || !weapon.Attribute.AiAttackAttr.FiringStand || - (Master.AttackState != AiAttackState.LockingTime && Master.AttackState != AiAttackState.Attack)) + (Master.AttackState != AiAttackEnum.LockingTime && Master.AttackState != AiAttackEnum.Attack)) { //计算移动 var nextPos = Master.NavigationAgent2D.GetNextPathPosition(); @@ -105,7 +105,7 @@ } //在视野中, 或者锁敌状态下, 或者攻击状态下, 继续保持原本逻辑 - if (Master.TargetInView || Master.AttackState == AiAttackState.LockingTime || Master.AttackState == AiAttackState.Attack) + if (Master.TargetInView || Master.AttackState == AiAttackEnum.LockingTime || Master.AttackState == AiAttackEnum.Attack) { if (inAttackRange) //在攻击范围内 { diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiSurroundState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiSurroundState.cs index 07dc504..fc5578a 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiSurroundState.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiSurroundState.cs @@ -70,7 +70,7 @@ //在视野中, 或者锁敌状态下, 或者攻击状态下, 继续保持原本逻辑 if (Master.TargetInView || (weapon != null && weapon.Attribute.AiAttackAttr.FiringStand && - (Master.AttackState == AiAttackState.LockingTime || Master.AttackState == AiAttackState.Attack) + (Master.AttackState == AiAttackEnum.LockingTime || Master.AttackState == AiAttackEnum.Attack) )) { if (_pauseTimer >= 0) @@ -111,7 +111,6 @@ } else { - var pos = masterPosition; var lastSlideCollision = Master.GetLastSlideCollision(); if (lastSlideCollision != null && lastSlideCollision.GetCollider() is AdvancedRole) //碰到其他角色 { @@ -124,12 +123,12 @@ { //判断开火状态, 进行移动 if (weapon == null || !weapon.Attribute.AiAttackAttr.FiringStand || - (Master.AttackState != AiAttackState.LockingTime && Master.AttackState != AiAttackState.Attack)) + (Master.AttackState != AiAttackEnum.LockingTime && Master.AttackState != AiAttackEnum.Attack)) { //正常移动 //计算移动 var nextPos = Master.NavigationAgent2D.GetNextPathPosition(); Master.AnimatedSprite.Play(AnimatorNames.Run); - Master.BasisVelocity = (nextPos - pos - Master.NavigationPoint.Position).Normalized() * + Master.BasisVelocity = (nextPos - masterPosition - Master.NavigationPoint.Position).Normalized() * Master.RoleState.MoveSpeed; } else //站立不动 @@ -139,13 +138,14 @@ } } - if (_prevPos.DistanceSquaredTo(pos) <= 1 * delta) + if (_prevPos.DistanceSquaredTo(masterPosition) <= 1 * delta) { _lockTimer += delta; } else { - _prevPos = pos; + _lockTimer = 0; + _prevPos = masterPosition; } } diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiTailAfterState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiTailAfterState.cs index 96fc91c..b24319a 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiTailAfterState.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiTailAfterState.cs @@ -67,7 +67,7 @@ { var weapon = Master.WeaponPack.ActiveItem; if (weapon == null || !weapon.Attribute.AiAttackAttr.FiringStand || - (Master.AttackState != AiAttackState.LockingTime && Master.AttackState != AiAttackState.Attack)) + (Master.AttackState != AiAttackEnum.LockingTime && Master.AttackState != AiAttackEnum.Attack)) { //计算移动 var nextPos = Master.NavigationAgent2D.GetNextPathPosition(); diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AINormalStateEnum.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AINormalStateEnum.cs index 447e4e6..9b8fe24 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AINormalStateEnum.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AINormalStateEnum.cs @@ -6,10 +6,6 @@ /// Ai 状态, 正常, 未发现目标 /// AiNormal, - // /// - // /// 发现目标, 但不知道在哪 - // /// - // AiProbe, /// /// 找到玩家,准备通知其他敌人 /// @@ -30,4 +26,8 @@ /// 距离足够近, 在目标附近随机移动 /// AiSurround, + /// + /// 攻击状态 + /// + AiAttack, } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiAttackState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiAttackState.cs new file mode 100644 index 0000000..b6f9f92 --- /dev/null +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiAttackState.cs @@ -0,0 +1,68 @@ +using Godot; + +namespace NnormalState; + +public class AiAttackState : StateBase +{ + //上一个状态 + public AINormalStateEnum PrevState; + //攻击步骤, 0.锁定目标, 1.执行攻击, 2.攻击完成 + private byte _attackStep = 0; + + public AiAttackState() : base(AINormalStateEnum.AiAttack) + { + } + + public override void Enter(AINormalStateEnum prev, params object[] args) + { + if (Master.GetAttackTimer() > 0) + { + Debug.LogError("攻击冷却还未完成就进入了 AINormalStateEnum.AiAttack 状态!"); + ChangeState(prev); + } + _attackStep = 0; + PrevState = prev; + Master.AnimationPlayer.AnimationFinished += OnAnimationFinished; + } + + public override void Exit(AINormalStateEnum next) + { + Master.AnimationPlayer.AnimationFinished -= OnAnimationFinished; + } + + public override void Process(float delta) + { + if (_attackStep == 0) //锁定目标步骤 + { + if (Master.GetLockRemainderTime() > 0) //锁定目标时间 + { + if (!Master.AttackAttribute.FiringStand && !Master.NavigationAgent2D.IsNavigationFinished()) + { + //移动 + Master.DoMove(); + } + else + { + //站立 + Master.DoIdle(); + } + } + else + { + _attackStep = 1; + } + } + else if (_attackStep == 1) //攻击步骤 + { + Master.BasisVelocity = Vector2.Zero; + Master.AnimationPlayer.Play(AnimatorNames.Attack); + _attackStep = 2; + } + + } + + public void OnAnimationFinished(StringName name) + { + ChangeState(PrevState); + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiFollowUpState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiFollowUpState.cs index b0185de..5fe2add 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiFollowUpState.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiFollowUpState.cs @@ -37,9 +37,8 @@ { _navigationUpdateTimer -= delta; } - - var masterPosition = Master.GlobalPosition; - var distanceSquared = masterPosition.DistanceSquaredTo(playerPos); + + var distanceSquared = Master.GlobalPosition.DistanceSquaredTo(playerPos); //是否在攻击范围内 var inAttackRange = distanceSquared <= Mathf.Pow(Master.GetAttackRange(), 2); @@ -48,23 +47,13 @@ if (!Master.NavigationAgent2D.IsNavigationFinished()) { - if (Master.AttackState != AiAttackState.LockingTime && Master.AttackState != AiAttackState.Attack) - { - //计算移动 - var nextPos = Master.NavigationAgent2D.GetNextPathPosition(); - Master.AnimatedSprite.Play(AnimatorNames.Run); - Master.BasisVelocity = (nextPos - masterPosition - Master.NavigationPoint.Position).Normalized() * - Master.RoleState.MoveSpeed; - } - else - { - Master.AnimatedSprite.Play(AnimatorNames.Idle); - Master.BasisVelocity = Vector2.Zero; - } + //移动 + Master.DoMove(); } else { - Master.BasisVelocity = Vector2.Zero; + //站立 + Master.DoIdle(); } //检测玩家是否在视野内 @@ -79,20 +68,20 @@ Master.TargetInView = false; } - //在视野中, 或者锁敌状态下, 或者攻击状态下, 继续保持原本逻辑 - if (Master.TargetInView || Master.AttackState == AiAttackState.LockingTime || Master.AttackState == AiAttackState.Attack) + //在视野中 + if (Master.TargetInView) { if (inAttackRange) //在攻击范围内 { - //发起攻击 - //Master.AnimatedSprite.Play(AnimatorNames.Attack); - Master.Attack(); - //距离够近, 可以切换到环绕模式 if (distanceSquared <= Mathf.Pow(Master.GetAttackRange() * 0.7f, 2) * 0.7f) { ChangeState(AINormalStateEnum.AiSurround); } + else if (Master.GetAttackTimer() <= 0) //攻击 + { + ChangeState(AINormalStateEnum.AiAttack); + } } } else //不在视野中 diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiLeaveForState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiLeaveForState.cs new file mode 100644 index 0000000..9cd1c49 --- /dev/null +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiLeaveForState.cs @@ -0,0 +1,89 @@ + +using Godot; + +namespace NnormalState; + +/// +/// 收到其他敌人通知, 前往发现目标的位置 +/// +public class AiLeaveForState : StateBase +{ + //导航目标点刷新计时器 + private float _navigationUpdateTimer = 0; + private float _navigationInterval = 0.3f; + + public AiLeaveForState() : base(AINormalStateEnum.AiLeaveFor) + { + } + + public override void Enter(AINormalStateEnum prev, params object[] args) + { + if (Master.World.Enemy_IsFindTarget) + { + Master.NavigationAgent2D.TargetPosition = Master.World.Enemy_FindTargetPosition; + } + else + { + ChangeState(prev); + } + } + + public override void Process(float delta) + { + //这个状态下不会有攻击事件, 所以没必要每一帧检查是否弹药耗尽 + + //更新玩家位置 + if (_navigationUpdateTimer <= 0) + { + //每隔一段时间秒更改目标位置 + _navigationUpdateTimer = _navigationInterval; + Master.NavigationAgent2D.TargetPosition = Master.World.Enemy_FindTargetPosition; + } + else + { + _navigationUpdateTimer -= delta; + } + + if (!Master.NavigationAgent2D.IsNavigationFinished()) + { + Master.LookTargetPosition(Master.World.Enemy_FindTargetPosition); + //移动 + Master.DoMove(); + } + else + { + //站立 + Master.DoIdle(); + } + + var playerPos = Player.Current.GetCenterPosition(); + //检测玩家是否在视野内, 如果在, 则切换到 AiTargetInView 状态 + if (Master.IsInTailAfterViewRange(playerPos)) + { + if (!Master.TestViewRayCast(playerPos)) //看到玩家 + { + //关闭射线检测 + Master.TestViewRayCastOver(); + //切换成发现目标状态 + ChangeState(AINormalStateEnum.AiFollowUp); + return; + } + else + { + //关闭射线检测 + Master.TestViewRayCastOver(); + } + } + + //移动到目标掉了, 还没发现目标 + if (Master.NavigationAgent2D.IsNavigationFinished()) + { + ChangeState(AINormalStateEnum.AiNormal); + } + } + + public override void DebugDraw() + { + Master.DrawLine(Vector2.Zero, Master.ToLocal(Master.NavigationAgent2D.TargetPosition), Colors.Yellow); + } +} diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiNormalState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiNormalState.cs index e991e00..c2f2a32 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiNormalState.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiNormalState.cs @@ -94,37 +94,31 @@ _pauseTimer = Utils.Random.RandomRangeFloat(0.3f, 2f); _isMoveOver = true; _moveFlag = false; - Master.BasisVelocity = Vector2.Zero; + Master.DoIdle(); } else if (!_moveFlag) { _moveFlag = true; - var pos = Master.GlobalPosition; - //计算移动 - var nextPos = Master.NavigationAgent2D.GetNextPathPosition(); - Master.AnimatedSprite.Play(AnimatorNames.Run); - Master.BasisVelocity = (nextPos - pos - Master.NavigationPoint.Position).Normalized() * - Master.RoleState.MoveSpeed; + var pos = Master.Position; + //移动 + Master.DoMove(); _prevPos = pos; } else { - var pos = Master.GlobalPosition; + var pos = Master.Position; var lastSlideCollision = Master.GetLastSlideCollision(); if (lastSlideCollision != null && lastSlideCollision.GetCollider() is AdvancedRole) //碰到其他角色 { _pauseTimer = Utils.Random.RandomRangeFloat(0.1f, 0.5f); _isMoveOver = true; _moveFlag = false; - Master.BasisVelocity = Vector2.Zero; + Master.DoIdle(); } else { //计算移动 - var nextPos = Master.NavigationAgent2D.GetNextPathPosition(); - Master.AnimatedSprite.Play(AnimatorNames.Run); - Master.BasisVelocity = (nextPos - pos - Master.NavigationPoint.Position).Normalized() * - Master.RoleState.MoveSpeed; + Master.DoMove(); } if (_prevPos.DistanceSquaredTo(pos) <= 0.01f) diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiSurroundState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiSurroundState.cs index b66e1fb..f2705bd 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiSurroundState.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiSurroundState.cs @@ -54,11 +54,8 @@ Master.TargetInView = false; } - //在视野中, 或者锁敌状态下, 或者攻击状态下, 继续保持原本逻辑 - if (Master.TargetInView || - (Master.FiringStand && - (Master.AttackState == AiAttackState.LockingTime || Master.AttackState == AiAttackState.Attack) - )) + //在视野中 + if (Master.TargetInView) { if (_pauseTimer >= 0) { @@ -72,7 +69,7 @@ } else { - var masterPosition = Master.GlobalPosition; + var masterPosition = Master.Position; if (_lockTimer >= 1) //卡在一个点超过一秒 { RunOver(playerPos); @@ -84,55 +81,38 @@ _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.5f); _isMoveOver = true; _moveFlag = false; - Master.BasisVelocity = Vector2.Zero; + Master.DoIdle(); } else if (!_moveFlag) { _moveFlag = true; //计算移动 - var nextPos = Master.NavigationAgent2D.GetNextPathPosition(); - Master.AnimatedSprite.Play(AnimatorNames.Run); - Master.BasisVelocity = - (nextPos - masterPosition - Master.NavigationPoint.Position).Normalized() * - Master.RoleState.MoveSpeed; + Master.DoMove(); } else { - var pos = masterPosition; var lastSlideCollision = Master.GetLastSlideCollision(); if (lastSlideCollision != null && lastSlideCollision.GetCollider() is AdvancedRole) //碰到其他角色 { _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.3f); _isMoveOver = true; _moveFlag = false; - Master.BasisVelocity = Vector2.Zero; + Master.DoIdle(); } else { - //判断开火状态, 进行移动 - if (!Master.FiringStand || - (Master.AttackState != AiAttackState.LockingTime && Master.AttackState != AiAttackState.Attack)) - { //正常移动 - //计算移动 - var nextPos = Master.NavigationAgent2D.GetNextPathPosition(); - Master.AnimatedSprite.Play(AnimatorNames.Run); - Master.BasisVelocity = (nextPos - pos - Master.NavigationPoint.Position).Normalized() * - Master.RoleState.MoveSpeed; - } - else //站立不动 - { - Master.AnimatedSprite.Play(AnimatorNames.Idle); - Master.BasisVelocity = Vector2.Zero; - } + //计算移动 + Master.DoMove(); } - - if (_prevPos.DistanceSquaredTo(pos) <= 1 * delta) + + if (_prevPos.DistanceSquaredTo(masterPosition) <= 1 * delta) { _lockTimer += delta; } else { - _prevPos = pos; + _lockTimer = 0; + _prevPos = masterPosition; } } @@ -140,10 +120,9 @@ { ChangeState(AINormalStateEnum.AiFollowUp); } - else + else if (Master.GetAttackTimer() <= 0) //发起攻击 { - //发起攻击 - Master.Attack(); + ChangeState(AINormalStateEnum.AiAttack); } } } diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiTailAfterState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiTailAfterState.cs index fe894e2..f1a2646 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiTailAfterState.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiTailAfterState.cs @@ -54,23 +54,12 @@ if (!Master.NavigationAgent2D.IsNavigationFinished()) { - if (Master.AttackState != AiAttackState.LockingTime && Master.AttackState != AiAttackState.Attack) - { - //计算移动 - var nextPos = Master.NavigationAgent2D.GetNextPathPosition(); - Master.AnimatedSprite.Play(AnimatorNames.Run); - Master.BasisVelocity = (nextPos - Master.GlobalPosition - Master.NavigationPoint.Position).Normalized() * - Master.RoleState.MoveSpeed; - } - else - { - Master.AnimatedSprite.Play(AnimatorNames.Idle); - Master.BasisVelocity = Vector2.Zero; - } + //移动 + Master.DoMove(); } else { - Master.BasisVelocity = Vector2.Zero; + Master.DoIdle(); } //检测玩家是否在视野内, 如果在, 则切换到 AiTargetInView 状态 if (Master.IsInTailAfterViewRange(playerPos)) diff --git a/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs b/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs index b3ff8a1..69fc6e7 100644 --- a/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs +++ b/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs @@ -894,7 +894,7 @@ } /// - /// 获取攻击冷却计时时间, 等于 0 表示冷却完成 + /// 获取攻击冷却计时时间, 小于等于 0 表示冷却完成 /// public float GetAttackTimer() { @@ -1906,45 +1906,45 @@ /// /// Ai 调用, 刷新 Ai 攻击状态并返回, 并不会调用相应的函数 /// - public AiAttackState AiRefreshAttackState() + public AiAttackEnum AiRefreshAttackState() { - AiAttackState flag; + AiAttackEnum flag; if (IsTotalAmmoEmpty()) //当前武器弹药打空 { //切换到有子弹的武器 var index = Master.WeaponPack.FindIndex((we, i) => !we.IsTotalAmmoEmpty()); if (index != -1) { - flag = AiAttackState.ExchangeWeapon; + flag = AiAttackEnum.ExchangeWeapon; } else //所有子弹打光 { - flag = AiAttackState.NoAmmo; + flag = AiAttackEnum.NoAmmo; } } else if (Reloading) //换弹中 { - flag = AiAttackState.TriggerReload; + flag = AiAttackEnum.TriggerReload; } else if (IsAmmoEmpty()) //弹夹已经打空 { - flag = AiAttackState.Reloading; + flag = AiAttackEnum.Reloading; } else if (_beLoadedState == 0 || _beLoadedState == -1) //需要上膛 { - flag = AiAttackState.AttackInterval; + flag = AiAttackEnum.AttackInterval; } else if (_beLoadedState == 1) //上膛中 { - flag = AiAttackState.AttackInterval; + flag = AiAttackEnum.AttackInterval; } else if (_continuousCount >= 1) //连发中 { - flag = AiAttackState.Attack; + flag = AiAttackEnum.Attack; } else if (IsAttackIntervalTime()) //开火间隙 { - flag = AiAttackState.AttackInterval; + flag = AiAttackEnum.AttackInterval; } else { @@ -1953,23 +1953,23 @@ { if (GetDelayedAttackTime() > 0) { - flag = AiAttackState.Attack; + flag = AiAttackEnum.Attack; } else { if (Attribute.ContinuousShoot) //连发 { - flag = AiAttackState.Attack; + flag = AiAttackEnum.Attack; } else //单发 { - flag = AiAttackState.Attack; + flag = AiAttackEnum.Attack; } } } else //锁定时间没到 { - flag = AiAttackState.LockingTime; + flag = AiAttackEnum.LockingTime; } } @@ -1979,35 +1979,35 @@ /// /// Ai调用, 触发扣动扳机, 并返回攻击状态 /// - public AiAttackState AiTriggerAttackState() + public AiAttackEnum AiTriggerAttackState() { - AiAttackState flag; + AiAttackEnum flag; if (IsTotalAmmoEmpty()) //当前武器弹药打空 { //切换到有子弹的武器 var index = Master.WeaponPack.FindIndex((we, i) => !we.IsTotalAmmoEmpty()); if (index != -1) { - flag = AiAttackState.ExchangeWeapon; + flag = AiAttackEnum.ExchangeWeapon; Master.WeaponPack.ExchangeByIndex(index); } else //所有子弹打光 { - flag = AiAttackState.NoAmmo; + flag = AiAttackEnum.NoAmmo; } } else if (Reloading) //换弹中 { - flag = AiAttackState.TriggerReload; + flag = AiAttackEnum.TriggerReload; } else if (IsAmmoEmpty()) //弹夹已经打空 { - flag = AiAttackState.Reloading; + flag = AiAttackEnum.Reloading; Reload(); } else if (_beLoadedState == 0 || _beLoadedState == -1) //需要上膛 { - flag = AiAttackState.AttackInterval; + flag = AiAttackEnum.AttackInterval; if (_attackTimer <= 0) { Master.Attack(); @@ -2015,15 +2015,15 @@ } else if (_beLoadedState == 1) //上膛中 { - flag = AiAttackState.AttackInterval; + flag = AiAttackEnum.AttackInterval; } else if (_continuousCount >= 1) //连发中 { - flag = AiAttackState.Attack; + flag = AiAttackEnum.Attack; } else if (IsAttackIntervalTime()) //开火间隙 { - flag = AiAttackState.AttackInterval; + flag = AiAttackEnum.AttackInterval; } else { @@ -2032,7 +2032,7 @@ { if (GetDelayedAttackTime() > 0) { - flag = AiAttackState.Attack; + flag = AiAttackEnum.Attack; enemy.Attack(); if (_attackFlag) { @@ -2043,7 +2043,7 @@ { if (Attribute.ContinuousShoot) //连发 { - flag = AiAttackState.Attack; + flag = AiAttackEnum.Attack; enemy.Attack(); if (_attackFlag) { @@ -2052,7 +2052,7 @@ } else //单发 { - flag = AiAttackState.Attack; + flag = AiAttackEnum.Attack; enemy.Attack(); if (_attackFlag) { @@ -2063,7 +2063,7 @@ } else //锁定时间没到 { - flag = AiAttackState.LockingTime; + flag = AiAttackEnum.LockingTime; } }