diff --git a/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs b/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs index eef5518..b4bfe60 100644 --- a/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs +++ b/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs @@ -1735,6 +1735,6 @@ /// public Vector2 GetCenterPosition() { - return AnimatedSprite.GlobalPosition + AnimatedSprite.Offset; + return AnimatedSprite.Position + Position; } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/role/AdvancedRole.cs b/DungeonShooting_Godot/src/game/activity/role/AdvancedRole.cs index ceaad7e..c1350c1 100644 --- a/DungeonShooting_Godot/src/game/activity/role/AdvancedRole.cs +++ b/DungeonShooting_Godot/src/game/activity/role/AdvancedRole.cs @@ -326,7 +326,7 @@ //WeaponPack.ActiveItem.TriggerMeleeAttack(this); //播放近战动画 - this.PlayAnimation_MeleeAttack(() => + PlayAnimation_MeleeAttack(() => { MountLookTarget = true; IsMeleeAttack = false; @@ -399,21 +399,6 @@ return -MountPoint.Position.Y; } - public override float GetAttackRotation() - { - return MountPoint.RealRotation; - } - - public override Vector2 GetMountPosition() - { - return MountPoint.GlobalPosition; - } - - public override Node2D GetMountNode() - { - return MountPoint; - } - protected override void OnDestroy() { base.OnDestroy(); diff --git a/DungeonShooting_Godot/src/game/activity/role/AdvancedRole_Animation.cs b/DungeonShooting_Godot/src/game/activity/role/AdvancedRole_Animation.cs new file mode 100644 index 0000000..e829a1f --- /dev/null +++ b/DungeonShooting_Godot/src/game/activity/role/AdvancedRole_Animation.cs @@ -0,0 +1,78 @@ + +using System; +using Godot; +using Vector2 = Godot.Vector2; + +public partial class AdvancedRole +{ + /// + /// 播放近战攻击动画 + /// + public virtual void PlayAnimation_MeleeAttack(Action finish) + { + var r = MountPoint.RotationDegrees; + //var gp = MountPoint.GlobalPosition; + var p1 = MountPoint.Position; + var p2 = p1 + new Vector2(6, 0).Rotated(Mathf.DegToRad(r - MeleeAttackAngle / 2f)); + var p3 = p1 + new Vector2(6, 0).Rotated(Mathf.DegToRad(r + MeleeAttackAngle / 2f)); + + var tween = CreateTween(); + tween.SetParallel(); + + tween.TweenProperty(MountPoint, "rotation_degrees", r - MeleeAttackAngle / 2f, 0.1); + tween.TweenProperty(MountPoint, "position", p2, 0.1); + tween.TweenProperty(MountPoint, "position", p2, 0.1); + tween.Chain(); + + tween.TweenCallback(Callable.From(() => + { + MountPoint.RotationDegrees = r + MeleeAttackAngle / 2f; + MountPoint.Position = p3; + //重新计算武器阴影位置 + var activeItem = WeaponPack.ActiveItem; + activeItem.CalcShadowTransform(); + //创建屏幕抖动 + if (Face == FaceDirection.Right) + { + //GameCamera.Main.DirectionalShake(Vector2.FromAngle(Mathf.DegToRad(r - 90)) * 5); + GameCamera.Main.DirectionalShake(Vector2.FromAngle(Mathf.DegToRad(r - 180)) * 6); + } + else + { + //GameCamera.Main.DirectionalShake(Vector2.FromAngle(Mathf.DegToRad(270 - r)) * 5); + GameCamera.Main.DirectionalShake(Vector2.FromAngle(Mathf.DegToRad(-r)) * 6); + } + //播放特效 + var effect = ObjectManager.GetPoolItem(ResourcePath.prefab_effect_weapon_MeleeAttack1_tscn); + var sprite = (Node2D)effect; + var localFirePosition = activeItem.GetLocalFirePosition() - activeItem.GripPoint.Position; + localFirePosition *= 0.9f; + sprite.Position = p1 + localFirePosition.Rotated(Mathf.DegToRad(r)); + sprite.RotationDegrees = r; + AddChild(sprite); + effect.PlayEffect(); + + //启用近战碰撞区域 + MeleeAttackCollision.Disabled = false; + })); + tween.Chain(); + + tween.TweenInterval(0.1f); + tween.Chain(); + + tween.TweenCallback(Callable.From(() => + { + //关闭近战碰撞区域 + MeleeAttackCollision.Disabled = true; + })); + tween.TweenProperty(MountPoint, "rotation_degrees", r, 0.2); + tween.TweenProperty(MountPoint, "position", p1, 0.2); + tween.Chain(); + + tween.TweenCallback(Callable.From(() => + { + finish(); + })); + tween.Play(); + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/role/Role.cs b/DungeonShooting_Godot/src/game/activity/role/Role.cs index a63cc35..fcea8b0 100644 --- a/DungeonShooting_Godot/src/game/activity/role/Role.cs +++ b/DungeonShooting_Godot/src/game/activity/role/Role.cs @@ -737,15 +737,7 @@ // blood.Rotation = angle; // GameApplication.Instance.Node3D.GetRoot().AddChild(blood); } - - if (target == null || target.IsDestroyed) - { - OnHit(null, damage, angle, !flag); - } - else - { - OnHit(target, damage, angle, !flag); - } + OnHit(target, damage, angle, !flag); //受伤特效 PlayHitAnimation(); @@ -894,30 +886,6 @@ { return -AnimatedSprite.Position.Y; } - - /// - /// 获取攻击标角度, 弧度制 - /// - public virtual float GetAttackRotation() - { - return GetCenterPosition().AngleTo(LookPosition); - } - - /// - /// 获取物品挂载点 - /// - public virtual Vector2 GetMountPosition() - { - return AnimatedSprite.Position; - } - - /// - /// 获取物品挂载节点对象 - /// - public virtual Node2D GetMountNode() - { - return AnimatedSprite; - } protected override void OnDestroy() { diff --git a/DungeonShooting_Godot/src/game/activity/role/RoleAnimation.cs b/DungeonShooting_Godot/src/game/activity/role/RoleAnimation.cs deleted file mode 100644 index 227fb3f..0000000 --- a/DungeonShooting_Godot/src/game/activity/role/RoleAnimation.cs +++ /dev/null @@ -1,149 +0,0 @@ - -using System; -using Godot; -using Vector2 = Godot.Vector2; - -public static class RoleAnimation -{ - /// - /// 播放近战攻击动画 - /// - public static void PlayAnimation_MeleeAttack(this AdvancedRole role, Action finish) - { - var r = role.MountPoint.RotationDegrees; - //var gp = MountPoint.GlobalPosition; - var p1 = role.MountPoint.Position; - var p2 = p1 + new Vector2(6, 0).Rotated(Mathf.DegToRad(r - role.MeleeAttackAngle / 2f)); - var p3 = p1 + new Vector2(6, 0).Rotated(Mathf.DegToRad(r + role.MeleeAttackAngle / 2f)); - - var tween = role.CreateTween(); - tween.SetParallel(); - - tween.TweenProperty(role.MountPoint, "rotation_degrees", r - role.MeleeAttackAngle / 2f, 0.1); - tween.TweenProperty(role.MountPoint, "position", p2, 0.1); - tween.TweenProperty(role.MountPoint, "position", p2, 0.1); - tween.Chain(); - - tween.TweenCallback(Callable.From(() => - { - role.MountPoint.RotationDegrees = r + role.MeleeAttackAngle / 2f; - role.MountPoint.Position = p3; - //重新计算武器阴影位置 - var activeItem = role.WeaponPack.ActiveItem; - activeItem.CalcShadowTransform(); - //创建屏幕抖动 - if (role.Face == FaceDirection.Right) - { - //GameCamera.Main.DirectionalShake(Vector2.FromAngle(Mathf.DegToRad(r - 90)) * 5); - GameCamera.Main.DirectionalShake(Vector2.FromAngle(Mathf.DegToRad(r - 180)) * 6); - } - else - { - //GameCamera.Main.DirectionalShake(Vector2.FromAngle(Mathf.DegToRad(270 - r)) * 5); - GameCamera.Main.DirectionalShake(Vector2.FromAngle(Mathf.DegToRad(-r)) * 6); - } - //播放特效 - var effect = ObjectManager.GetPoolItem(ResourcePath.prefab_effect_weapon_MeleeAttack1_tscn); - var sprite = (Node2D)effect; - var localFirePosition = activeItem.GetLocalFirePosition() - activeItem.GripPoint.Position; - localFirePosition *= 0.9f; - sprite.Position = p1 + localFirePosition.Rotated(Mathf.DegToRad(r)); - sprite.RotationDegrees = r; - role.AddChild(sprite); - effect.PlayEffect(); - - //启用近战碰撞区域 - role.MeleeAttackCollision.Disabled = false; - })); - tween.Chain(); - - tween.TweenInterval(0.1f); - tween.Chain(); - - tween.TweenCallback(Callable.From(() => - { - //关闭近战碰撞区域 - role.MeleeAttackCollision.Disabled = true; - })); - tween.TweenProperty(role.MountPoint, "rotation_degrees", r, 0.2); - tween.TweenProperty(role.MountPoint, "position", p1, 0.2); - tween.Chain(); - - tween.TweenCallback(Callable.From(() => - { - finish(); - })); - tween.Play(); - } - - /// - /// 播放近战攻击动画 - /// - public static void PlayAnimation_MeleeAttack(this AdvancedEnemy role, Action finish) - { - var r = role.MountPoint.RotationDegrees; - //var gp = MountPoint.GlobalPosition; - var p1 = role.MountPoint.Position; - var p2 = p1 + new Vector2(6, 0).Rotated(Mathf.DegToRad(r - role.MeleeAttackAngle / 2f)); - var p3 = p1 + new Vector2(6, 0).Rotated(Mathf.DegToRad(r + role.MeleeAttackAngle / 2f)); - - var tween = role.CreateTween(); - tween.SetParallel(); - - tween.TweenProperty(role.MountPoint, "rotation_degrees", r - role.MeleeAttackAngle / 2f, 0.1); - tween.TweenProperty(role.MountPoint, "position", p2, 0.1); - tween.TweenProperty(role.MountPoint, "position", p2, 0.1); - tween.Chain(); - - tween.TweenCallback(Callable.From(() => - { - role.MountPoint.RotationDegrees = r + role.MeleeAttackAngle / 2f; - role.MountPoint.Position = p3; - //重新计算武器阴影位置 - var activeItem = role.WeaponPack.ActiveItem; - activeItem.CalcShadowTransform(); - //创建屏幕抖动 - if (role.Face == FaceDirection.Right) - { - //GameCamera.Main.DirectionalShake(Vector2.FromAngle(Mathf.DegToRad(r - 90)) * 5); - GameCamera.Main.DirectionalShake(Vector2.FromAngle(Mathf.DegToRad(r - 180)) * 6); - } - else - { - //GameCamera.Main.DirectionalShake(Vector2.FromAngle(Mathf.DegToRad(270 - r)) * 5); - GameCamera.Main.DirectionalShake(Vector2.FromAngle(Mathf.DegToRad(-r)) * 6); - } - //播放特效 - var effect = ObjectManager.GetPoolItem(ResourcePath.prefab_effect_weapon_MeleeAttack1_tscn); - var sprite = (Node2D)effect; - var localFirePosition = activeItem.GetLocalFirePosition() - activeItem.GripPoint.Position; - localFirePosition *= 0.9f; - sprite.Position = p1 + localFirePosition.Rotated(Mathf.DegToRad(r)); - sprite.RotationDegrees = r; - role.AddChild(sprite); - effect.PlayEffect(); - - //启用近战碰撞区域 - role.MeleeAttackCollision.Disabled = false; - })); - tween.Chain(); - - tween.TweenInterval(0.1f); - tween.Chain(); - - tween.TweenCallback(Callable.From(() => - { - //关闭近战碰撞区域 - role.MeleeAttackCollision.Disabled = true; - })); - tween.TweenProperty(role.MountPoint, "rotation_degrees", r, 0.2); - tween.TweenProperty(role.MountPoint, "position", p1, 0.2); - tween.Chain(); - - tween.TweenCallback(Callable.From(() => - { - finish(); - })); - tween.Play(); - } -} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs index 75f7900..b2d184d 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs @@ -14,93 +14,66 @@ using System; using AdvancedState; using Godot; -using NnormalState; -using AiAstonishedState = AdvancedState.AiAstonishedState; -using AiAttackState = AdvancedState.AiAttackState; -using AiFollowUpState = AdvancedState.AiFollowUpState; -using AiLeaveForState = AdvancedState.AiLeaveForState; -using AiNormalState = AdvancedState.AiNormalState; -using AiNotifyState = AdvancedState.AiNotifyState; -using AiSurroundState = AdvancedState.AiSurroundState; -using AiTailAfterState = AdvancedState.AiTailAfterState; /// /// 高级敌人,可以携带武器 /// [Tool] -public partial class AdvancedEnemy : Enemy +public partial class AdvancedEnemy : AdvancedRole { /// - /// 角色携带的武器背包 + /// 目标是否在视野内 /// - public Package WeaponPack { get; private set; } + public bool TargetInView { get; set; } = true; /// - /// 武器挂载点 + /// 敌人身上的状态机控制器 /// - [Export, ExportFillNode] - public MountRotation MountPoint { get; set; } - - /// - /// 近战碰撞检测区域 - /// - [Export, ExportFillNode] - public Area2D MeleeAttackArea { get; set; } - - /// - /// 近战碰撞检测区域的碰撞器 - /// - [Export, ExportFillNode] - public CollisionPolygon2D MeleeAttackCollision { get; set; } + public StateController StateController { get; private set; } /// - /// 近战攻击时挥动武器的角度 + /// 视野半径, 单位像素, 发现玩家后改视野范围可以穿墙 /// - [Export] - public float MeleeAttackAngle { get; set; } = 120; + public float ViewRange { get; set; } = 250; /// - /// 武器挂载点是否始终指向目标 + /// 发现玩家后的视野半径 /// - public bool MountLookTarget { get; set; } = true; - + public float TailAfterViewRange { get; set; } = 400; + /// - /// 背后武器的挂载点 + /// 背后的视野半径, 单位像素 + /// + public float BackViewRange { get; set; } = 50; + + /// + /// 视野检测射线, 朝玩家打射线, 检测是否碰到墙 /// [Export, ExportFillNode] - public Marker2D BackMountPoint { get; set; } - - /// - /// 是否处于近战攻击中 - /// - public bool IsMeleeAttack { get; private set; } - - //近战计时器 - private float _meleeAttackTimer = 0; - - - /// - /// 当拾起某个武器时调用 - /// - protected virtual void OnPickUpWeapon(Weapon weapon) - { - } - - /// - /// 当扔掉某个武器时调用 - /// - protected virtual void OnThrowWeapon(Weapon weapon) - { - } + public RayCast2D ViewRay { get; private set; } /// - /// 当切换到某个武器时调用 + /// 导航代理 /// - protected virtual void OnExchangeWeapon(Weapon weapon) - { - } + [Export, ExportFillNode] + public NavigationAgent2D NavigationAgent2D { get; private set; } + /// + /// 导航代理中点 + /// + [Export, ExportFillNode] + public Marker2D NavigationPoint { get; private set; } + /// + /// 当前敌人所看向的对象, 也就是枪口指向的对象 + /// + public ActivityObject LookTarget { get; set; } + + /// + /// 锁定目标已经走过的时间 + /// + public float LockTargetTime { get; set; } = 0; + public override void OnInit() { base.OnInit(); @@ -207,32 +180,15 @@ //拾起武器操作 EnemyPickUpWeapon(); } - - /// - /// 当武器放到后背时调用, 用于设置武器位置和角度 - /// - /// 武器实例 - /// 放入武器背包的位置 - public virtual void OnPutBackMount(Weapon weapon, int index) + + protected override void OnHit(ActivityObject target, int damage, float angle, bool realHarm) { - if (index < 8) + //受到伤害 + var state = StateController.CurrState; + if (state == AIAdvancedStateEnum.AiNormal || state == AIAdvancedStateEnum.AiLeaveFor) //|| state == AiStateEnum.AiProbe { - if (index % 2 == 0) - { - weapon.Position = new Vector2(-4, 3); - weapon.RotationDegrees = 90 - (index / 2f) * 20; - weapon.Scale = new Vector2(-1, 1); - } - else - { - weapon.Position = new Vector2(4, 3); - weapon.RotationDegrees = 270 + (index - 1) / 2f * 20; - weapon.Scale = new Vector2(1, 1); - } - } - else - { - weapon.Visible = false; + LookTarget = target; + StateController.ChangeState(AIAdvancedStateEnum.AiTailAfter); } } @@ -341,7 +297,60 @@ return 0; } - + + /// + /// 返回目标点是否在视野范围内 + /// + public bool IsInViewRange(Vector2 target) + { + var isForward = IsPositionInForward(target); + if (isForward) + { + if (GlobalPosition.DistanceSquaredTo(target) <= ViewRange * ViewRange) //没有超出视野半径 + { + return true; + } + } + + return false; + } + + /// + /// 返回目标点是否在跟随状态下的视野半径内 + /// + public bool IsInTailAfterViewRange(Vector2 target) + { + var isForward = IsPositionInForward(target); + if (isForward) + { + if (GlobalPosition.DistanceSquaredTo(target) <= TailAfterViewRange * TailAfterViewRange) //没有超出视野半径 + { + return true; + } + } + + return false; + } + + /// + /// 调用视野检测, 如果被墙壁和其它物体遮挡, 则返回true + /// + public bool TestViewRayCast(Vector2 target) + { + ViewRay.Enabled = true; + ViewRay.TargetPosition = ViewRay.ToLocal(target); + ViewRay.ForceRaycastUpdate(); + return ViewRay.IsColliding(); + } + + /// + /// 调用视野检测完毕后, 需要调用 TestViewRayCastOver() 来关闭视野检测射线 + /// + public void TestViewRayCastOver() + { + ViewRay.Enabled = false; + } + /// /// AI 拾起武器操作 /// @@ -349,7 +358,7 @@ { //这几个状态不需要主动拾起武器操作 var state = StateController.CurrState; - if (state == AINormalStateEnum.AiNormal) + if (state == AIAdvancedStateEnum.AiNormal) { return; } @@ -401,7 +410,7 @@ /// /// 获取锁定目标的剩余时间 /// - public override float GetLockRemainderTime() + public float GetLockRemainderTime() { var weapon = WeaponPack.ActiveItem; if (weapon == null) @@ -411,263 +420,48 @@ return weapon.Attribute.AiAttackAttr.LockingTime - LockTargetTime; } + /// + /// 强制设置锁定目标时间 + /// + public void SetLockTargetTime(float time) + { + LockTargetTime = time; + } + public override void LookTargetPosition(Vector2 pos) { LookTarget = null; - LookPosition = pos; - if (MountLookTarget) - { - //脸的朝向 - var gPos = Position; - 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); - } + base.LookTargetPosition(pos); } /// - /// 返回所有武器是否弹药都打光了 + /// 执行移动操作 /// - public bool IsAllWeaponTotalAmmoEmpty() + public void DoMove() { - foreach (var weapon in WeaponPack.ItemSlot) - { - if (weapon != null && !weapon.IsTotalAmmoEmpty()) - { - return false; - } - } - - return true; - } - - public override float GetAttackRotation() - { - return MountPoint.RealRotation; - } - - public override Vector2 GetMountPosition() - { - return MountPoint.GlobalPosition; - } - - public override Node2D GetMountNode() - { - return MountPoint; + AnimatedSprite.Play(AnimatorNames.Run); + //计算移动 + var nextPos = NavigationAgent2D.GetNextPathPosition(); + BasisVelocity = (nextPos - Position - NavigationPoint.Position).Normalized() * RoleState.MoveSpeed; } /// - /// 拾起一个武器, 返回是否成功拾起, 如果不想立刻切换到该武器, exchange 请传 false + /// 执行站立操作 /// - /// 武器对象 - /// 是否立即切换到该武器, 默认 true - public bool PickUpWeapon(Weapon weapon, bool exchange = true) + public void DoIdle() { - if (WeaponPack.PickupItem(weapon, exchange) != -1) - { - //从可互动队列中移除 - InteractiveItemList.Remove(weapon); - OnPickUpWeapon(weapon); - return true; - } - - return false; - } - - /// - /// 切换到下一个武器 - /// - public void ExchangeNextWeapon() - { - var weapon = WeaponPack.ActiveItem; - WeaponPack.ExchangeNext(); - if (WeaponPack.ActiveItem != weapon) - { - OnExchangeWeapon(WeaponPack.ActiveItem); - } - } - - /// - /// 切换到上一个武器 - /// - public void ExchangePrevWeapon() - { - var weapon = WeaponPack.ActiveItem; - WeaponPack.ExchangePrev(); - if (WeaponPack.ActiveItem != weapon) - { - OnExchangeWeapon(WeaponPack.ActiveItem); - } - } - - /// - /// 扔掉当前使用的武器, 切换到上一个武器 - /// - public void ThrowWeapon() - { - ThrowWeapon(WeaponPack.ActiveIndex); - } - - /// - /// 扔掉指定位置的武器 - /// - /// 武器在武器背包中的位置 - public void ThrowWeapon(int index) - { - var weapon = WeaponPack.GetItem(index); - if (weapon == null) - { - return; - } - - var temp = weapon.AnimatedSprite.Position; - if (Face == FaceDirection.Left) - { - temp.Y = -temp.Y; - } - //var pos = GlobalPosition + temp.Rotated(weapon.GlobalRotation); - WeaponPack.RemoveItem(index); - //播放抛出效果 - weapon.ThrowWeapon(this, GlobalPosition); + AnimatedSprite.Play(AnimatorNames.Idle); + BasisVelocity = Vector2.Zero; } /// - /// 切换到下一个武器 + /// 更新房间中标记的目标位置 /// - public void ExchangeNextActiveProp() + public void UpdateMarkTargetPosition() { - var prop = ActivePropsPack.ActiveItem; - ActivePropsPack.ExchangeNext(); - if (prop != ActivePropsPack.ActiveItem) + if (LookTarget != null) { - OnExchangeActiveProp(ActivePropsPack.ActiveItem); - } - } - - /// - /// 切换到上一个武器 - /// - public void ExchangePrevActiveProp() - { - var prop = ActivePropsPack.ActiveItem; - ActivePropsPack.ExchangePrev(); - if (prop != ActivePropsPack.ActiveItem) - { - OnExchangeActiveProp(ActivePropsPack.ActiveItem); - } - } - - //------------------------------------------------------------------------------------- - - /// - /// 触发换弹 - /// - public virtual void Reload() - { - if (WeaponPack.ActiveItem != null) - { - WeaponPack.ActiveItem.Reload(); - } - } - - public override void Attack() - { - if (!IsMeleeAttack && WeaponPack.ActiveItem != null) - { - WeaponPack.ActiveItem.Trigger(this); - } - } - - /// - /// 触发近战攻击 - /// - public virtual void MeleeAttack() - { - if (IsMeleeAttack || _meleeAttackTimer > 0) - { - return; - } - - if (WeaponPack.ActiveItem != null && WeaponPack.ActiveItem.Attribute.CanMeleeAttack) - { - IsMeleeAttack = true; - _meleeAttackTimer = RoleState.MeleeAttackTime; - MountLookTarget = false; - - //WeaponPack.ActiveItem.TriggerMeleeAttack(this); - //播放近战动画 - this.PlayAnimation_MeleeAttack(() => - { - MountLookTarget = true; - IsMeleeAttack = false; - }); - } - } - - /// - /// 切换当前使用的武器的回调 - /// - private void OnChangeActiveItem(Weapon weapon) - { - //这里处理近战区域 - if (weapon != null) - { - MeleeAttackCollision.Polygon = Utils.CreateSectorPolygon( - Utils.ConvertAngle(-MeleeAttackAngle / 2f), - (weapon.GetLocalFirePosition() - weapon.GripPoint.Position).Length() * 1.2f, - MeleeAttackAngle, - 6 - ); - MeleeAttackArea.CollisionMask = AttackLayer | PhysicsLayer.Bullet; - } - } - - /// - /// 近战区域碰到敌人 - /// - private void OnMeleeAttackBodyEntered(Node2D body) - { - var activeWeapon = WeaponPack.ActiveItem; - if (activeWeapon == null) - { - return; - } - var activityObject = body.AsActivityObject(); - if (activityObject != null) - { - if (activityObject is AdvancedRole role) //攻击角色 - { - var damage = Utils.Random.RandomConfigRange(activeWeapon.Attribute.MeleeAttackHarmRange); - damage = RoleState.CalcDamage(damage); - - //击退 - if (role is not Player) //目标不是玩家才会触发击退 - { - var attr = IsAi ? activeWeapon.AiUseAttribute : activeWeapon.PlayerUseAttribute; - var repel = Utils.Random.RandomConfigRange(attr.MeleeAttackRepelRange); - var position = role.GlobalPosition - MountPoint.GlobalPosition; - var v2 = position.Normalized() * repel; - role.MoveController.AddForce(v2); - } - - role.CallDeferred(nameof(Hurt), this, damage, (role.GetCenterPosition() - GlobalPosition).Angle()); - } - else if (activityObject is Bullet bullet) //攻击子弹 - { - var attackLayer = bullet.AttackLayer; - if (CollisionWithMask(attackLayer)) //是攻击玩家的子弹 - { - bullet.PlayDisappearEffect(); - bullet.Destroy(); - } - } + AffiliationArea.RoomInfo.MarkTargetPosition[LookTarget.Id] = LookTarget.Position; } } } diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs index e711869..1513d7c 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs @@ -75,15 +75,12 @@ public ActivityObject LookTarget { get; set; } /// - /// 锁定目标已经走过的时间 - /// - public float LockTargetTime { get; set; } = 0; - - /// /// Ai 攻击属性 /// public ExcelConfig.AiAttackAttr AttackAttribute { get; private set; } + //锁定目标时间 + private float _lockTargetTime = 0; //攻击冷却计时器 private float _attackTimer = 0; @@ -174,11 +171,11 @@ var currState = StateController.CurrState; if (currState == AINormalStateEnum.AiAttack && _attackTimer <= 0) //必须在可以开火时记录时间 { - LockTargetTime += delta; + _lockTargetTime += delta; } else { - LockTargetTime = 0; + _lockTargetTime = 0; } } @@ -186,11 +183,14 @@ { //受到伤害 var state = StateController.CurrState; - if (target != null && state == AINormalStateEnum.AiNormal || state == AINormalStateEnum.AiLeaveFor) //|| state == AiStateEnum.AiProbe - { - LookTarget = target; - StateController.ChangeState(AINormalStateEnum.AiTailAfter); - } + // if (state == AINormalStateEnum.AiNormal) + // { + // StateController.ChangeState(AINormalStateEnum.AiLeaveFor, target); + // } + // else if (state == AINormalStateEnum.AiLeaveFor) + // { + // + // } } protected override void OnDie() @@ -268,13 +268,29 @@ { ViewRay.Enabled = false; } + + /// + /// 获取锁定目标的时间 + /// + public float GetLockTime() + { + return _lockTargetTime; + } /// /// 获取锁定目标的剩余时间 /// - public virtual float GetLockRemainderTime() + public float GetLockRemainderTime() { - return AttackAttribute.LockingTime - LockTargetTime; + return AttackAttribute.LockingTime - _lockTargetTime; + } + + /// + /// 强制设置锁定目标时间 + /// + public void SetLockTargetTime(float time) + { + _lockTargetTime = time; } /// @@ -305,17 +321,6 @@ } /// - /// 更新房间中标记的目标位置 - /// - public void UpdateMarkTargetPosition() - { - if (LookTarget != null) - { - AffiliationArea.RoomInfo.MarkTargetPosition[LookTarget.Id] = LookTarget.Position; - } - } - - /// /// 执行移动操作 /// public void DoMove() 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 f731d72..35e56dd 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AINormalStateEnum.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AINormalStateEnum.cs @@ -11,7 +11,7 @@ /// AiNotify, /// - /// 惊讶状态 + /// 发现目标, 惊讶状态 /// AiAstonished, /// @@ -31,11 +31,7 @@ /// AiSurround, /// - /// Ai 寻找弹药 - /// - AiFindAmmo, - /// - /// Ai攻击 + /// 攻击状态 /// AiAttack, } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs b/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs index e39f771..9a2fd78 100644 --- a/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs +++ b/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs @@ -6,7 +6,7 @@ /// /// 武器的基类 /// -public abstract partial class Weapon : ActivityObject, IPackageItem +public abstract partial class Weapon : ActivityObject, IPackageItem { /// /// 武器使用的属性数据, 该属性会根据是否是玩家使用武器, 如果是Ai使用武器, 则会返回 AiUseAttribute 的属性对象 @@ -32,7 +32,7 @@ /// public CampEnum TargetCamp { get; set; } - public Role Master { get; set; } + public AdvancedRole Master { get; set; } public int PackageIndex { get; set; } = -1; @@ -127,19 +127,7 @@ /// /// 返回是否真正使用该武器 /// - public bool IsActive - { - get - { - if (Master == null) - return false; - else if (Master is AdvancedRole advancedRole) - return advancedRole.WeaponPack.ActiveItem == this; - else if (Master is AdvancedEnemy advancedEnemy) - return advancedEnemy.WeaponPack.ActiveItem == this; - return false; - } - } + public bool IsActive => Master != null && Master.WeaponPack.ActiveItem == this; /// /// 动画播放器 @@ -160,7 +148,7 @@ /// /// 上一次触发改武器开火的角色, 可能为 null /// - public Role TriggerRole { get; private set; } + public AdvancedRole TriggerRole { get; private set; } /// /// 上一次触发改武器开火的触发开火攻击的层级, 数据源自于: @@ -409,7 +397,7 @@ /// 当武器被拾起时调用 /// /// 拾起该武器的角色 - protected virtual void OnPickUp(Role master) + protected virtual void OnPickUp(AdvancedRole master) { } @@ -417,7 +405,7 @@ /// 当武器从武器背包中移除时调用 /// /// 移除该武器的角色 - protected virtual void OnRemove(Role master) + protected virtual void OnRemove(AdvancedRole master) { } @@ -464,7 +452,7 @@ //这把武器被扔在地上, 或者当前武器没有被使用 //if (Master == null || Master.WeaponPack.ActiveItem != this) - if (!IsActive || !_triggerRoleFlag) //在背上, 或者被扔出去了 + if ((Master != null && Master.WeaponPack.ActiveItem != this) || !_triggerRoleFlag) //在背上, 或者被扔出去了 { //_triggerTimer _triggerTimer = _triggerTimer > 0 ? _triggerTimer - delta : 0; @@ -707,7 +695,7 @@ /// 扳机函数, 调用即视为按下扳机 /// /// 按下扳机的角色, 如果传 null, 则视为走火 - public void Trigger(Role triggerRole) + public void Trigger(AdvancedRole triggerRole) { //不能触发扳机 if (!NoMasterCanTrigger && Master == null) return; @@ -1053,7 +1041,7 @@ if (Master != null) { bulletCount = Master.RoleState.CalcBulletCount(bulletCount); - fireRotation += Master.GetAttackRotation(); + fireRotation += Master.MountPoint.RealRotation; } else { @@ -1117,7 +1105,7 @@ /// /// 根据触扳机的角色对象判断该角色使用的武器数据 /// - public ExcelConfig.WeaponBase GetUseAttribute(Role triggerRole) + public ExcelConfig.WeaponBase GetUseAttribute(AdvancedRole triggerRole) { if (triggerRole == null || !triggerRole.IsAi) { @@ -1746,14 +1734,14 @@ /// public float GetRealGlobalRotation() { - return Master.GetAttackRotation() + Rotation; + return Mathf.DegToRad(Master.MountPoint.RealRotationDegrees) + Rotation; } /// /// 触发扔掉武器时抛出的效果, 并不会管武器是否在武器背包中 /// /// 触发扔掉该武器的的角色 - public void ThrowWeapon(Role master) + public void ThrowWeapon(AdvancedRole master) { ThrowWeapon(master, master.GlobalPosition); } @@ -1763,7 +1751,7 @@ /// /// 触发扔掉该武器的的角色 /// 投抛起始位置 - public void ThrowWeapon(Role master, Vector2 startPosition) + public void ThrowWeapon(AdvancedRole master, Vector2 startPosition) { //阴影偏移 ShadowOffset = new Vector2(0, 2); @@ -1773,29 +1761,11 @@ Scale *= new Vector2(1, -1); } - float rotation; - float startHeight; - if (master is AdvancedRole advancedRole) - { - var mountPoint = advancedRole.MountPoint; - rotation = mountPoint.GlobalRotation; - startHeight = -mountPoint.Position.Y; - } - else if (master is AdvancedEnemy advancedEnemy) - { - var mountPoint = advancedEnemy.MountPoint; - rotation = mountPoint.GlobalRotation; - startHeight = -mountPoint.Position.Y; - } - else - { - rotation = master.AnimatedSprite.GlobalRotation; - startHeight = -GetCenterPosition().Y; - } - + var rotation = master.MountPoint.GlobalRotation; GlobalRotation = rotation; startPosition -= GripPoint.Position.Rotated(rotation); + var startHeight = -master.MountPoint.Position.Y; var velocity = new Vector2(20, 0).Rotated(rotation); var yf = Utils.Random.RandomRangeInt(50, 70); Throw(startPosition, startHeight, yf, velocity, 0); @@ -1829,19 +1799,7 @@ { //调整阴影 //ShadowOffset = new Vector2(0, Master.GlobalPosition.Y - GlobalPosition.Y); - if (Master is AdvancedRole advancedRole) - { - ShadowOffset = new Vector2(0, -advancedRole.MountPoint.Position.Y); - } - else if (Master is AdvancedEnemy advancedEnemy) - { - ShadowOffset = new Vector2(0, -advancedEnemy.MountPoint.Position.Y); - } - else - { - ShadowOffset = new Vector2(0, -Master.GetCenterPosition().Y); - } - + ShadowOffset = new Vector2(0, -Master.MountPoint.Position.Y); //枪口默认抬起角度 RotationDegrees = -Attribute.DefaultAngle; ShowShadowSprite(); @@ -1905,33 +1863,16 @@ public void OnActiveItem() { - if (Master is AdvancedRole advancedRole) + //更改父节点 + var parent = GetParentOrNull(); + if (parent == null) { - //更改父节点 - var parent = GetParentOrNull(); - if (parent == null) - { - advancedRole.MountPoint.AddChild(this); - } - else if (parent != advancedRole.MountPoint) - { - parent.RemoveChild(this); - advancedRole.MountPoint.AddChild(this); - } + Master.MountPoint.AddChild(this); } - else if (Master is AdvancedEnemy advancedEnemy) + else if (parent != Master.MountPoint) { - //更改父节点 - var parent = GetParentOrNull(); - if (parent == null) - { - advancedEnemy.MountPoint.AddChild(this); - } - else if (parent != advancedEnemy.MountPoint) - { - parent.RemoveChild(this); - advancedEnemy.MountPoint.AddChild(this); - } + parent.RemoveChild(this); + Master.MountPoint.AddChild(this); } Position = Vector2.Zero; @@ -1943,41 +1884,19 @@ public void OnConcealItem() { - if (Master is AdvancedRole advancedRole) + var tempParent = GetParentOrNull(); + if (tempParent != null) { - var tempParent = GetParentOrNull(); - if (tempParent != null) - { - tempParent.RemoveChild(this); - advancedRole.BackMountPoint.AddChild(this); - advancedRole.OnPutBackMount(this, PackageIndex); - Conceal(); - } + tempParent.RemoveChild(this); + Master.BackMountPoint.AddChild(this); + Master.OnPutBackMount(this, PackageIndex); + Conceal(); } - else if (Master is AdvancedEnemy advancedEnemy) - { - var tempParent = GetParentOrNull(); - if (tempParent != null) - { - tempParent.RemoveChild(this); - advancedEnemy.BackMountPoint.AddChild(this); - advancedEnemy.OnPutBackMount(this, PackageIndex); - Conceal(); - } - } - } public void OnOverflowItem() { - if (Master is AdvancedRole advancedRole) - { - advancedRole.ThrowWeapon(PackageIndex); - } - else if (Master is AdvancedEnemy advancedEnemy) - { - advancedEnemy.ThrowWeapon(PackageIndex); - } + Master.ThrowWeapon(PackageIndex); } /// @@ -2006,13 +1925,12 @@ AiAttackEnum flag; if (IsTotalAmmoEmpty()) //当前武器弹药打空 { - var enemy = (AdvancedEnemy)Master; //切换到有子弹的武器 - var index = enemy.WeaponPack.FindIndex((we, i) => !we.IsTotalAmmoEmpty()); + var index = Master.WeaponPack.FindIndex((we, i) => !we.IsTotalAmmoEmpty()); if (index != -1) { flag = AiAttackEnum.ExchangeWeapon; - enemy.WeaponPack.ExchangeByIndex(index); + Master.WeaponPack.ExchangeByIndex(index); } else //所有子弹打光 { @@ -2059,7 +1977,7 @@ enemy.Attack(); if (_attackFlag) { - enemy.LockTargetTime = 0; + enemy.SetLockTargetTime(0); } } else @@ -2070,7 +1988,7 @@ enemy.Attack(); if (_attackFlag) { - enemy.LockTargetTime = 0; + enemy.SetLockTargetTime(0); } } else //单发 @@ -2079,7 +1997,7 @@ enemy.Attack(); if (_attackFlag) { - enemy.LockTargetTime = 0; + enemy.SetLockTargetTime(0); } } } diff --git a/DungeonShooting_Godot/src/game/activity/weapon/knife/Knife.cs b/DungeonShooting_Godot/src/game/activity/weapon/knife/Knife.cs index d32b28d..b5db0d6 100644 --- a/DungeonShooting_Godot/src/game/activity/weapon/knife/Knife.cs +++ b/DungeonShooting_Godot/src/game/activity/weapon/knife/Knife.cs @@ -50,7 +50,7 @@ if (IsActive) { //让碰撞节点与武器挂载节点位置保持一致, 而不跟着武器走 - _hitArea.GlobalPosition = Master.GetMountPosition(); + _hitArea.GlobalPosition = Master.MountPoint.GlobalPosition; } } @@ -85,8 +85,8 @@ SpecialEffectManager.Play( Master, ResourcePath.resource_spriteFrames_effect_KnifeHit1_tres, "default", - Master.GetMountPosition(), - Master.GetAttackRotation() + Mathf.DegToRad(Attribute.UpliftAngle + 60), + Master.MountPoint.Position, + Master.MountPoint.Rotation + Mathf.DegToRad(Attribute.UpliftAngle + 60), AnimatedSprite.Scale, new Vector2(17, 4), 1 ); @@ -95,7 +95,7 @@ if (Master == Player.Current) { - var r = Mathf.RadToDeg(Master.GetAttackRotation()); + var r = Master.MountPoint.RotationDegrees; //创建屏幕抖动 if (Master.Face == FaceDirection.Right) { @@ -148,7 +148,7 @@ Vector2 position; if (TriggerRole != null) { - position = role.GlobalPosition - TriggerRole.GetMountPosition(); + position = role.GlobalPosition - TriggerRole.MountPoint.GlobalPosition; } else { diff --git a/DungeonShooting_Godot/src/game/room/DungeonManager.cs b/DungeonShooting_Godot/src/game/room/DungeonManager.cs index ab4560a..3cf058f 100644 --- a/DungeonShooting_Godot/src/game/room/DungeonManager.cs +++ b/DungeonShooting_Godot/src/game/room/DungeonManager.cs @@ -566,9 +566,23 @@ //不与玩家处于同一个房间 if (!enemy.IsDestroyed && enemy.AffiliationArea != playerAffiliationArea) { - if (enemy.StateController.CurrState != AINormalStateEnum.AiNormal) + if (enemy is Enemy e) { - enemy.StateController.ChangeState(AINormalStateEnum.AiNormal); + if (e.StateController.CurrState != AINormalStateEnum.AiNormal) + { + e.StateController.ChangeState(AINormalStateEnum.AiNormal); + } + } + else if (enemy is AdvancedEnemy ae) + { + if (ae.StateController.CurrState != AIAdvancedStateEnum.AiNormal) + { + ae.StateController.ChangeState(AIAdvancedStateEnum.AiNormal); + } + } + else + { + throw new Exception("World.Enemy_InstanceList 混入了非 Enemy 和 AdvancedEnemy 类型的对象!"); } } } diff --git a/DungeonShooting_Godot/src/game/room/World.cs b/DungeonShooting_Godot/src/game/room/World.cs index 1285582..1ed2eab 100644 --- a/DungeonShooting_Godot/src/game/room/World.cs +++ b/DungeonShooting_Godot/src/game/room/World.cs @@ -63,7 +63,7 @@ /// /// 记录所有存活的敌人 /// - public List Enemy_InstanceList { get; } = new List(); + public List Enemy_InstanceList { get; } = new List(); private bool _pause = false; private List _coroutineList;