diff --git a/DungeonShooting_Godot/prefab/role/Enemy0002.tscn b/DungeonShooting_Godot/prefab/role/Enemy0002.tscn index c9fd918..d20ba0e 100644 --- a/DungeonShooting_Godot/prefab/role/Enemy0002.tscn +++ b/DungeonShooting_Godot/prefab/role/Enemy0002.tscn @@ -47,3 +47,6 @@ material = SubResource("ShaderMaterial_ntjmx") position = Vector2(0, -10) sprite_frames = ExtResource("4_ehtyi") + +[node name="FirePoint" type="Marker2D" parent="AnimatedSprite" index="0"] +position = Vector2(9, 4) diff --git a/DungeonShooting_Godot/src/game/activity/bullet/explode/Explode.cs b/DungeonShooting_Godot/src/game/activity/bullet/explode/Explode.cs index 6bbec1c..d21bca8 100644 --- a/DungeonShooting_Godot/src/game/activity/bullet/explode/Explode.cs +++ b/DungeonShooting_Godot/src/game/activity/bullet/explode/Explode.cs @@ -87,7 +87,7 @@ /// /// 播放爆炸, triggerRole 为触发该爆炸的角色 /// - public void RunPlay(AdvancedRole triggerRole = null) + public void RunPlay(Role triggerRole = null) { GameCamera.Main.CreateShake(new Vector2(6, 6), 0.7f, true); AnimationPlayer.Play(AnimatorNames.Play); diff --git a/DungeonShooting_Godot/src/game/activity/bullet/normal/Bullet.cs b/DungeonShooting_Godot/src/game/activity/bullet/normal/Bullet.cs index 2e7af1e..647d9fd 100644 --- a/DungeonShooting_Godot/src/game/activity/bullet/normal/Bullet.cs +++ b/DungeonShooting_Godot/src/game/activity/bullet/normal/Bullet.cs @@ -63,24 +63,18 @@ BulletData = data; AttackLayer = attackLayer; Rotation = data.Rotation; - - float altitude; + var triggerRole = data.TriggerRole; - if (triggerRole != null) + if (data.TriggerRole != null && data.TriggerRole.AffiliationArea != null) //设置所属区域 { - altitude = -triggerRole.MountPoint.Position.Y; - if (triggerRole.AffiliationArea != null) //设置所属区域 + if (triggerRole.AffiliationArea != null) { triggerRole.AffiliationArea.InsertItem(this); } } - else - { - altitude = 8; - } - Position = data.Position + new Vector2(0, altitude); - Altitude = altitude; + Position = data.Position + new Vector2(0, data.Altitude); + Altitude = data.Altitude; if (data.VerticalSpeed != 0) { VerticalSpeed = data.VerticalSpeed; diff --git a/DungeonShooting_Godot/src/game/activity/bullet/normal/IBullet.cs b/DungeonShooting_Godot/src/game/activity/bullet/normal/IBullet.cs index a81f718..9611387 100644 --- a/DungeonShooting_Godot/src/game/activity/bullet/normal/IBullet.cs +++ b/DungeonShooting_Godot/src/game/activity/bullet/normal/IBullet.cs @@ -12,7 +12,7 @@ /// 离开对象池时的事件 /// event Action OnLeavePoolEvent; - + /// /// 攻击的层级 /// diff --git a/DungeonShooting_Godot/src/game/activity/role/AdvancedRole.cs b/DungeonShooting_Godot/src/game/activity/role/AdvancedRole.cs index 01d64b3..7e7bade 100644 --- a/DungeonShooting_Godot/src/game/activity/role/AdvancedRole.cs +++ b/DungeonShooting_Godot/src/game/activity/role/AdvancedRole.cs @@ -422,6 +422,11 @@ } } + public override float GetFirePointAltitude() + { + return -MountPoint.Position.Y; + } + protected override void OnDestroy() { base.OnDestroy(); diff --git a/DungeonShooting_Godot/src/game/activity/role/Role.cs b/DungeonShooting_Godot/src/game/activity/role/Role.cs index 0fda986..fde5416 100644 --- a/DungeonShooting_Godot/src/game/activity/role/Role.cs +++ b/DungeonShooting_Godot/src/game/activity/role/Role.cs @@ -842,6 +842,14 @@ return Mathf.Pi - rotation; } + /// + /// 获取开火点高度 + /// + public virtual float GetFirePointAltitude() + { + return -AnimatedSprite.Position.Y; + } + protected override void OnDestroy() { //销毁道具 diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs index 70780b3..4b6e5f3 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs @@ -50,6 +50,12 @@ /// [Export, ExportFillNode] public Marker2D NavigationPoint { get; private set; } + + /// + /// 开火位置 + /// + [Export, ExportFillNode] + public Marker2D FirePoint { get; private set; } /// /// Ai攻击状态, 调用 Attack() 函数后会刷新 @@ -301,4 +307,9 @@ { return 200; } + + public override float GetFirePointAltitude() + { + return -AnimatedSprite.Position.Y - FirePoint.Position.Y; + } } \ 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 ae423dc..9541182 100644 --- a/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs +++ b/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs @@ -1473,13 +1473,13 @@ this.CallDelay(Attribute.ThrowShellDelayTime, () => { _reloadShellFlag = true; - ThrowShell(Attribute.Shell, speedScale); + FireManager.ThrowShell(this, Attribute.Shell, speedScale); }); } else if (Attribute.ThrowShellDelayTime == 0) { _reloadShellFlag = true; - ThrowShell(Attribute.Shell, speedScale); + FireManager.ThrowShell(this, Attribute.Shell, speedScale); } } diff --git a/DungeonShooting_Godot/src/game/activity/weapon/Weapon_Bullet.cs b/DungeonShooting_Godot/src/game/activity/weapon/Weapon_Bullet.cs deleted file mode 100644 index 2370533..0000000 --- a/DungeonShooting_Godot/src/game/activity/weapon/Weapon_Bullet.cs +++ /dev/null @@ -1,145 +0,0 @@ - -using System; -using Config; -using Godot; - -public partial class Weapon -{ - //-------------------------------- 子弹相关 ----------------------------- - - /// - /// 投抛弹壳的默认实现方式, shellId为弹壳id - /// - protected ActivityObject ThrowShell(ExcelConfig.ActivityBase shell, float speedScale = 1) - { - var startPos = ShellPoint.GlobalPosition; - float startHeight; - if (Master != null) - { - var shellPosition = (Master != null ? Master.MountPoint.Position : Position) + ShellPoint.Position; - startHeight = -shellPosition.Y; - startPos.Y += startHeight; - } - else - { - startHeight = Altitude; - } - - var direction = GlobalRotationDegrees + Utils.Random.RandomRangeInt(-30, 30) + 180; - var verticalSpeed = Utils.Random.RandomRangeInt((int)(60 * speedScale), (int)(120 * speedScale)); - var velocity = new Vector2(Utils.Random.RandomRangeInt((int)(20 * speedScale), (int)(60 * speedScale)), 0).Rotated(direction * Mathf.Pi / 180); - var rotate = Utils.Random.RandomRangeInt((int)(-720 * speedScale), (int)(720 * speedScale)); - var shellInstance = Create(shell); - shellInstance.Rotation = (Master != null ? Master.MountPoint.RealRotation : Rotation); - shellInstance.Throw(startPos, startHeight, verticalSpeed, velocity, rotate); - shellInstance.InheritVelocity(Master != null ? Master : this); - if (Master == null) - { - AffiliationArea.InsertItem(shellInstance); - } - else - { - Master.AffiliationArea.InsertItem(shellInstance); - } - - return shellInstance; - } - - /// - /// 发射子弹 - /// - protected IBullet ShootBullet(float fireRotation, ExcelConfig.BulletBase bullet) - { - if (bullet.Type == 1) //实体子弹 - { - return ShootSolidBullet(fireRotation, bullet); - } - else if (bullet.Type == 2) //激光子弹 - { - return ShootLaser(fireRotation, bullet); - } - - return null; - } - - /// - /// 发射子弹的默认实现方式 - /// - private Bullet ShootSolidBullet(float fireRotation, ExcelConfig.BulletBase bullet) - { - var data = new BulletData() - { - Weapon = this, - BulletBase = bullet, - TriggerRole = TriggerRole, - Harm = Utils.Random.RandomConfigRange(bullet.HarmRange), - Repel = Utils.Random.RandomConfigRange(bullet.RepelRange), - MaxDistance = Utils.Random.RandomConfigRange(bullet.DistanceRange), - FlySpeed = Utils.Random.RandomConfigRange(bullet.SpeedRange), - VerticalSpeed = Utils.Random.RandomConfigRange(bullet.VerticalSpeed), - BounceCount = Utils.Random.RandomConfigRange(bullet.BounceCount), - Penetration = Utils.Random.RandomConfigRange(bullet.Penetration), - Position = FirePoint.GlobalPosition, - }; - - var deviationAngle = Utils.Random.RandomConfigRange(bullet.DeviationAngleRange); - if (TriggerRole != null) - { - var roleState = TriggerRole.RoleState; - data.Harm = roleState.CalcDamage(data.Harm); - data.Repel = roleState.CalcBulletRepel(this, data.Repel); - data.FlySpeed = roleState.CalcBulletSpeed(this, data.FlySpeed); - data.MaxDistance = roleState.CalcBulletDistance(this, data.MaxDistance); - data.BounceCount = roleState.CalcBulletBounceCount(this, data.BounceCount); - data.Penetration = roleState.CalcBulletPenetration(this, data.Penetration); - deviationAngle = roleState.CalcBulletDeviationAngle(this, deviationAngle); - - if (TriggerRole.IsAi) //只有玩家使用该武器才能获得正常速度的子弹 - { - data.FlySpeed *= AiUseAttribute.AiAttackAttr.BulletSpeedScale; - } - } - - data.Rotation = fireRotation + Mathf.DegToRad(deviationAngle); - //创建子弹 - var bulletInstance = ObjectManager.GetBullet(bullet.Prefab); - bulletInstance.InitData(data, GetAttackLayer()); - return bulletInstance; - } - - /// - /// 发射射线的默认实现方式 - /// - private Laser ShootLaser(float fireRotation, ExcelConfig.BulletBase bullet) - { - var data = new BulletData() - { - Weapon = this, - BulletBase = bullet, - TriggerRole = TriggerRole, - Harm = Utils.Random.RandomConfigRange(bullet.HarmRange), - Repel = Utils.Random.RandomConfigRange(bullet.RepelRange), - MaxDistance = Utils.Random.RandomConfigRange(bullet.DistanceRange), - BounceCount = Utils.Random.RandomConfigRange(bullet.BounceCount), - LifeTime = Utils.Random.RandomConfigRange(bullet.LifeTimeRange), - Position = FirePoint.GlobalPosition, - }; - - var deviationAngle = Utils.Random.RandomConfigRange(bullet.DeviationAngleRange); - if (TriggerRole != null) - { - var roleState = TriggerRole.RoleState; - data.Harm = roleState.CalcDamage(data.Harm); - data.Repel = roleState.CalcBulletRepel(this, data.Repel); - data.BounceCount = roleState.CalcBulletBounceCount(this, data.BounceCount); - deviationAngle = roleState.CalcBulletDeviationAngle(this, deviationAngle); - } - - data.Rotation = fireRotation + Mathf.DegToRad(deviationAngle); - //创建激光 - var laser = ObjectManager.GetLaser(bullet.Prefab); - laser.AddToActivityRoot(RoomLayerEnum.YSortLayer); - laser.InitData(data, GetAttackLayer(), 3); - return laser; - } -} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/weapon/gun/Gun.cs b/DungeonShooting_Godot/src/game/activity/weapon/gun/Gun.cs index 76ed43c..a5fb906 100644 --- a/DungeonShooting_Godot/src/game/activity/weapon/gun/Gun.cs +++ b/DungeonShooting_Godot/src/game/activity/weapon/gun/Gun.cs @@ -30,7 +30,7 @@ protected override void OnShoot(float fireRotation) { - ShootBullet(fireRotation, Attribute.Bullet); + FireManager.ShootBullet(this, fireRotation, Attribute.Bullet); } // //测试用, 敌人被消灭时触发手上武器开火 diff --git a/DungeonShooting_Godot/src/game/data/BulletData.cs b/DungeonShooting_Godot/src/game/data/BulletData.cs index 34547ad..1df47cc 100644 --- a/DungeonShooting_Godot/src/game/data/BulletData.cs +++ b/DungeonShooting_Godot/src/game/data/BulletData.cs @@ -8,7 +8,7 @@ public class BulletData { /// - /// 发射该子弹的武器 + /// 发射该子弹的武器, 可能为null /// public Weapon Weapon; @@ -18,9 +18,9 @@ public ExcelConfig.BulletBase BulletBase; /// - /// 发射该子弹的角色 + /// 发射该子弹的角色, 可能为null /// - public AdvancedRole TriggerRole; + public Role TriggerRole; /// /// 造成的伤害 @@ -43,6 +43,11 @@ public float FlySpeed; /// + /// 初始离地高度 + /// + public float Altitude; + + /// /// 纵轴速度 /// public float VerticalSpeed; diff --git a/DungeonShooting_Godot/src/game/manager/FireManager.cs b/DungeonShooting_Godot/src/game/manager/FireManager.cs new file mode 100644 index 0000000..95c1d88 --- /dev/null +++ b/DungeonShooting_Godot/src/game/manager/FireManager.cs @@ -0,0 +1,178 @@ + +using Config; +using Godot; + +public static class FireManager +{ + + /// + /// 投抛弹壳的默认实现方式, shellId为弹壳id + /// + public static ActivityObject ThrowShell(Weapon weapon, ExcelConfig.ActivityBase shell, float speedScale = 1) + { + var startPos = weapon.ShellPoint.GlobalPosition; + float startHeight; + var master = weapon.Master; + if (master != null) + { + var shellPosition = master.MountPoint.Position + weapon.ShellPoint.Position; + startHeight = -shellPosition.Y; + startPos.Y += startHeight; + } + else + { + startHeight = weapon.Altitude; + } + + var direction = weapon.GlobalRotationDegrees + Utils.Random.RandomRangeInt(-30, 30) + 180; + var verticalSpeed = Utils.Random.RandomRangeInt((int)(60 * speedScale), (int)(120 * speedScale)); + var velocity = new Vector2(Utils.Random.RandomRangeInt((int)(20 * speedScale), (int)(60 * speedScale)), 0).Rotated(direction * Mathf.Pi / 180); + var rotate = Utils.Random.RandomRangeInt((int)(-720 * speedScale), (int)(720 * speedScale)); + var shellInstance = ActivityObject.Create(shell); + shellInstance.Rotation = (master != null ? master.MountPoint.RealRotation : weapon.Rotation); + shellInstance.Throw(startPos, startHeight, verticalSpeed, velocity, rotate); + shellInstance.InheritVelocity(master != null ? master : weapon); + if (master == null) + { + weapon.AffiliationArea.InsertItem(shellInstance); + } + else + { + master.AffiliationArea.InsertItem(shellInstance); + } + + return shellInstance; + } + + /// + /// 通过武器发射子弹 + /// + public static IBullet ShootBullet(Weapon weapon, float fireRotation, ExcelConfig.BulletBase bullet) + { + if (bullet.Type == 1) //实体子弹 + { + return ShootSolidBullet(weapon, fireRotation, bullet); + } + else if (bullet.Type == 2) //激光子弹 + { + return ShootLaser(weapon, fireRotation, bullet); + } + else + { + Debug.LogError("暂未支持的子弹类型: " + bullet.Type); + } + + return null; + } + + /// + /// + /// + /// + /// + /// + /// + public static IBullet ShootBullet(Role trigger, float fireRotation, ExcelConfig.BulletBase bullet) + { + // if (bullet.Type == 1) //实体子弹 + // { + // return ShootSolidBullet(trigger, fireRotation, bullet); + // } + + return null; + } + + /// + /// 发射子弹的默认实现方式 + /// + private static Bullet ShootSolidBullet(Weapon weapon, float fireRotation, ExcelConfig.BulletBase bullet) + { + var data = new BulletData() + { + Weapon = weapon, + BulletBase = bullet, + TriggerRole = weapon.TriggerRole, + Harm = Utils.Random.RandomConfigRange(bullet.HarmRange), + Repel = Utils.Random.RandomConfigRange(bullet.RepelRange), + MaxDistance = Utils.Random.RandomConfigRange(bullet.DistanceRange), + FlySpeed = Utils.Random.RandomConfigRange(bullet.SpeedRange), + VerticalSpeed = Utils.Random.RandomConfigRange(bullet.VerticalSpeed), + BounceCount = Utils.Random.RandomConfigRange(bullet.BounceCount), + Penetration = Utils.Random.RandomConfigRange(bullet.Penetration), + Position = weapon.FirePoint.GlobalPosition, + }; + + var deviationAngle = Utils.Random.RandomConfigRange(bullet.DeviationAngleRange); + if (weapon.TriggerRole != null) + { + data.Altitude = weapon.TriggerRole.GetFirePointAltitude(); + var roleState = weapon.TriggerRole.RoleState; + data.Harm = roleState.CalcDamage(data.Harm); + data.Repel = roleState.CalcBulletRepel(weapon, data.Repel); + data.FlySpeed = roleState.CalcBulletSpeed(weapon, data.FlySpeed); + data.MaxDistance = roleState.CalcBulletDistance(weapon, data.MaxDistance); + data.BounceCount = roleState.CalcBulletBounceCount(weapon, data.BounceCount); + data.Penetration = roleState.CalcBulletPenetration(weapon, data.Penetration); + deviationAngle = roleState.CalcBulletDeviationAngle(weapon, deviationAngle); + + if (weapon.TriggerRole.IsAi) //只有玩家使用该武器才能获得正常速度的子弹 + { + data.FlySpeed *= weapon.AiUseAttribute.AiAttackAttr.BulletSpeedScale; + } + } + else + { + data.Altitude = 1; + } + + data.Rotation = fireRotation + Mathf.DegToRad(deviationAngle); + //创建子弹 + var bulletInstance = ObjectManager.GetBullet(bullet.Prefab); + bulletInstance.InitData(data, weapon.GetAttackLayer()); + return bulletInstance; + } + + /// + /// 发射射线的默认实现方式 + /// + private static Laser ShootLaser(Weapon weapon, float fireRotation, ExcelConfig.BulletBase bullet) + { + var data = new BulletData() + { + Weapon = weapon, + BulletBase = bullet, + TriggerRole = weapon.TriggerRole, + Harm = Utils.Random.RandomConfigRange(bullet.HarmRange), + Repel = Utils.Random.RandomConfigRange(bullet.RepelRange), + MaxDistance = Utils.Random.RandomConfigRange(bullet.DistanceRange), + BounceCount = Utils.Random.RandomConfigRange(bullet.BounceCount), + LifeTime = Utils.Random.RandomConfigRange(bullet.LifeTimeRange), + Position = weapon.FirePoint.GlobalPosition, + }; + + var deviationAngle = Utils.Random.RandomConfigRange(bullet.DeviationAngleRange); + if (weapon.TriggerRole != null) + { + data.Altitude = weapon.TriggerRole.GetFirePointAltitude(); + var roleState = weapon.TriggerRole.RoleState; + data.Harm = roleState.CalcDamage(data.Harm); + data.Repel = roleState.CalcBulletRepel(weapon, data.Repel); + data.BounceCount = roleState.CalcBulletBounceCount(weapon, data.BounceCount); + deviationAngle = roleState.CalcBulletDeviationAngle(weapon, deviationAngle); + } + else + { + data.Altitude = 1; + } + + data.Rotation = fireRotation + Mathf.DegToRad(deviationAngle); + //创建激光 + var laser = ObjectManager.GetLaser(bullet.Prefab); + laser.AddToActivityRoot(RoomLayerEnum.YSortLayer); + laser.InitData(data, weapon.GetAttackLayer(), 3); + return laser; + } + + //----------------------------------------------------------------------------------- + +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/manager/SoundManager.cs b/DungeonShooting_Godot/src/game/manager/SoundManager.cs index 80790b0..2195543 100644 --- a/DungeonShooting_Godot/src/game/manager/SoundManager.cs +++ b/DungeonShooting_Godot/src/game/manager/SoundManager.cs @@ -198,7 +198,7 @@ /// 音效Id /// 播放音效的位置, 该位置为 SubViewport 下的坐标, 也就是 使用的坐标 /// 触发播放音效的角色, 因为 Npc 产生的音效声音更小, 可以传 null - public static GameAudioPlayer2D PlaySoundByConfig(string id, Vector2 viewPosition, AdvancedRole triggerRole = null) + public static GameAudioPlayer2D PlaySoundByConfig(string id, Vector2 viewPosition, Role triggerRole = null) { var sound = ExcelConfig.Sound_Map[id]; return PlaySoundByConfig(sound, viewPosition, triggerRole); @@ -210,7 +210,7 @@ /// 音效数据 /// 播放音效的位置, 该位置为 SubViewport 下的坐标, 也就是 使用的坐标 /// 触发播放音效的角色, 因为 Npc 产生的音效声音更小, 可以传 null - public static GameAudioPlayer2D PlaySoundByConfig(ExcelConfig.Sound sound, Vector2 viewPosition, AdvancedRole triggerRole = null) + public static GameAudioPlayer2D PlaySoundByConfig(ExcelConfig.Sound sound, Vector2 viewPosition, Role triggerRole = null) { return PlaySoundEffectPosition( sound.Path, @@ -226,7 +226,7 @@ /// 播放音效的位置, 该位置为 SubViewport 下的坐标, 也就是 使用的坐标 /// 延时时间 /// 触发播放音效的角色, 因为 Npc 产生的音效声音更小, 可以传 null - public static GameAudioPlayer2D PlaySoundByConfigDelay(string id, Vector2 viewPosition, float delayTime, AdvancedRole triggerRole = null) + public static GameAudioPlayer2D PlaySoundByConfigDelay(string id, Vector2 viewPosition, float delayTime, Role triggerRole = null) { var sound = ExcelConfig.Sound_Map[id]; return PlaySoundByConfigDelay(sound, viewPosition, delayTime, triggerRole); @@ -239,7 +239,7 @@ /// 播放音效的位置, 该位置为 SubViewport 下的坐标, 也就是 使用的坐标 /// 延时时间 /// 触发播放音效的角色, 因为 Npc 产生的音效声音更小, 可以传 null - public static GameAudioPlayer2D PlaySoundByConfigDelay(ExcelConfig.Sound sound, Vector2 viewPosition, float delayTime, AdvancedRole triggerRole = null) + public static GameAudioPlayer2D PlaySoundByConfigDelay(ExcelConfig.Sound sound, Vector2 viewPosition, float delayTime, Role triggerRole = null) { return PlaySoundEffectPositionDelay( sound.Path, @@ -303,7 +303,7 @@ /// /// 计算指定角色播放音效使用的音量 /// - public static float CalcRoleVolume(float volume, AdvancedRole role) + public static float CalcRoleVolume(float volume, Role role) { if (role is not Player) {