diff --git a/DungeonShooting_Godot/prefab/role/Enemy0002.tscn b/DungeonShooting_Godot/prefab/role/Enemy0002.tscn
index 8cce0b7..fd86415 100644
--- a/DungeonShooting_Godot/prefab/role/Enemy0002.tscn
+++ b/DungeonShooting_Godot/prefab/role/Enemy0002.tscn
@@ -27,18 +27,18 @@
shader_parameter/outline_rainbow = false
shader_parameter/outline_use_blend = true
-[node name="Enemy0001" node_paths=PackedStringArray("HurtArea", "HurtCollision", "MountPoint", "BackMountPoint", "InteractiveArea", "InteractiveCollision", "MeleeAttackArea", "MeleeAttackCollision", "ShadowSprite", "AnimatedSprite", "Collision") instance=ExtResource("1_rncjb")]
+[node name="Enemy0001" node_paths=PackedStringArray("MountPoint", "BackMountPoint", "MeleeAttackArea", "MeleeAttackCollision", "HurtArea", "HurtCollision", "InteractiveArea", "InteractiveCollision", "ShadowSprite", "AnimatedSprite", "Collision") instance=ExtResource("1_rncjb")]
collision_layer = 16
collision_mask = 25
script = ExtResource("2_wjtfl")
-HurtArea = NodePath("HurtArea")
-HurtCollision = NodePath("HurtArea/HurtCollision")
MountPoint = NodePath("MountPoint")
BackMountPoint = NodePath("BackMountPoint")
-InteractiveArea = NodePath("InteractiveArea")
-InteractiveCollision = NodePath("InteractiveArea/InteractiveCollision")
MeleeAttackArea = NodePath("MountPoint/MeleeAttackArea")
MeleeAttackCollision = NodePath("MountPoint/MeleeAttackArea/MeleeAttackCollision")
+HurtArea = NodePath("HurtArea")
+HurtCollision = NodePath("HurtArea/HurtCollision")
+InteractiveArea = NodePath("InteractiveArea")
+InteractiveCollision = NodePath("InteractiveArea/InteractiveCollision")
ShadowSprite = NodePath("ShadowSprite")
AnimatedSprite = NodePath("AnimatedSprite")
Collision = NodePath("Collision")
diff --git a/DungeonShooting_Godot/src/game/Cursor.cs b/DungeonShooting_Godot/src/game/Cursor.cs
index aca4d11..7f8e528 100644
--- a/DungeonShooting_Godot/src/game/Cursor.cs
+++ b/DungeonShooting_Godot/src/game/Cursor.cs
@@ -13,7 +13,7 @@
///
/// 非GUI模式下鼠标指针所挂载的角色
///
- private Role _mountRole;
+ private AdvancedRole _mountRole;
private Sprite2D center;
private Sprite2D lt;
@@ -88,7 +88,7 @@
///
/// 设置非GUI模式下鼠标指针所挂载的角色
///
- public void SetMountRole(Role role)
+ public void SetMountRole(AdvancedRole role)
{
_mountRole = role;
}
@@ -96,7 +96,7 @@
///
/// 获取非GUI模式下鼠标指针所挂载的角色
///
- public Role GetMountRole()
+ public AdvancedRole GetMountRole()
{
return _mountRole;
}
diff --git a/DungeonShooting_Godot/src/game/activity/bullet/explode/Explode.cs b/DungeonShooting_Godot/src/game/activity/bullet/explode/Explode.cs
index d21bca8..5dc5429 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(Role triggerRole = null)
+ public void RunPlay(AdvancedRole triggerRole = null)
{
GameCamera.Main.CreateShake(new Vector2(6, 6), 0.7f, true);
AnimationPlayer.Play(AnimatorNames.Play);
@@ -136,7 +136,7 @@
if (len <= _hitRadius) //在伤害半径内
{
- if (o is Role role) //是角色
+ if (o is AdvancedRole role) //是角色
{
role.CallDeferred(nameof(role.Hurt), _harm, angle);
}
diff --git a/DungeonShooting_Godot/src/game/activity/bullet/laser/Laser.cs b/DungeonShooting_Godot/src/game/activity/bullet/laser/Laser.cs
index 5a62788..d3216f9 100644
--- a/DungeonShooting_Godot/src/game/activity/bullet/laser/Laser.cs
+++ b/DungeonShooting_Godot/src/game/activity/bullet/laser/Laser.cs
@@ -136,7 +136,7 @@
private void OnArea2dEntered(Area2D other)
{
- var role = other.AsActivityObject();
+ var role = other.AsActivityObject();
if (role != null)
{
//击退
@@ -145,7 +145,7 @@
role.MoveController.AddForce(Vector2.FromAngle(Rotation) * BulletData.Repel);
}
//造成伤害
- role.CallDeferred(nameof(Role.Hurt), BulletData.Harm, Rotation);
+ role.CallDeferred(nameof(AdvancedRole.Hurt), BulletData.Harm, Rotation);
}
}
diff --git a/DungeonShooting_Godot/src/game/activity/bullet/normal/Bullet.cs b/DungeonShooting_Godot/src/game/activity/bullet/normal/Bullet.cs
index 7745881..40642b3 100644
--- a/DungeonShooting_Godot/src/game/activity/bullet/normal/Bullet.cs
+++ b/DungeonShooting_Godot/src/game/activity/bullet/normal/Bullet.cs
@@ -131,7 +131,7 @@
///
public virtual void OnCollisionTarget(ActivityObject o)
{
- if (o is Role role)
+ if (o is AdvancedRole role)
{
PlayDisappearEffect();
@@ -145,7 +145,7 @@
}
//造成伤害
- role.CallDeferred(nameof(Role.Hurt), BulletData.Harm, Rotation);
+ role.CallDeferred(nameof(AdvancedRole.Hurt), BulletData.Harm, Rotation);
//穿透次数
CurrentPenetration++;
diff --git a/DungeonShooting_Godot/src/game/activity/package/IPackageItem.cs b/DungeonShooting_Godot/src/game/activity/package/IPackageItem.cs
index aca7c9d..93a5774 100644
--- a/DungeonShooting_Godot/src/game/activity/package/IPackageItem.cs
+++ b/DungeonShooting_Godot/src/game/activity/package/IPackageItem.cs
@@ -1,13 +1,13 @@
///
-/// 可放入背包中的物体接口
+/// 可放入背包中的物体接口,泛型T表示所属角色对象类型
///
-public interface IPackageItem
+public interface IPackageItem where T : Role
{
///
/// 物体所属角色
///
- Role Master { get; set; }
+ T Master { get; set; }
///
/// 物体在背包中的索引, 如果不在背包中则为 -1
diff --git a/DungeonShooting_Godot/src/game/activity/package/Package.cs b/DungeonShooting_Godot/src/game/activity/package/Package.cs
index 378f7ef..4dd43dd 100644
--- a/DungeonShooting_Godot/src/game/activity/package/Package.cs
+++ b/DungeonShooting_Godot/src/game/activity/package/Package.cs
@@ -4,7 +4,7 @@
///
/// 物体背包类
///
-public class Package : Component where T : ActivityObject, IPackageItem
+public class Package : Component where T : ActivityObject, IPackageItem where S : Role
{
///
/// 当前使用对象改变时回调
diff --git a/DungeonShooting_Godot/src/game/activity/prop/Prop.cs b/DungeonShooting_Godot/src/game/activity/prop/Prop.cs
index 1e937e9..beb1751 100644
--- a/DungeonShooting_Godot/src/game/activity/prop/Prop.cs
+++ b/DungeonShooting_Godot/src/game/activity/prop/Prop.cs
@@ -32,7 +32,7 @@
/// 触发扔掉道具效果, 并不会管道具是否在道具背包中
///
/// 触发扔掉该道具的的角色
- public void ThrowProp(Role master)
+ public void ThrowProp(AdvancedRole master)
{
ThrowProp(master, master.GlobalPosition);
}
@@ -47,7 +47,7 @@
//阴影偏移
ShadowOffset = new Vector2(0, 2);
GlobalRotation = 0;
- var startHeight = -master.MountPoint.Position.Y;
+ var startHeight = -master.GetCenterPosition().Y;
Throw(startPosition, startHeight, 0, Vector2.Zero, 0);
//继承role的移动速度
diff --git a/DungeonShooting_Godot/src/game/activity/prop/active/ActiveProp.cs b/DungeonShooting_Godot/src/game/activity/prop/active/ActiveProp.cs
index 7a4b86b..aaa78c3 100644
--- a/DungeonShooting_Godot/src/game/activity/prop/active/ActiveProp.cs
+++ b/DungeonShooting_Godot/src/game/activity/prop/active/ActiveProp.cs
@@ -4,7 +4,7 @@
///
/// 主动使用道具
///
-public abstract partial class ActiveProp : Prop, IPackageItem
+public abstract partial class ActiveProp : Prop, IPackageItem
{
public int PackageIndex { get; set; }
diff --git a/DungeonShooting_Godot/src/game/activity/prop/active/ActiveProp5001.cs b/DungeonShooting_Godot/src/game/activity/prop/active/ActiveProp5001.cs
index e9f0852..eb4662c 100644
--- a/DungeonShooting_Godot/src/game/activity/prop/active/ActiveProp5001.cs
+++ b/DungeonShooting_Godot/src/game/activity/prop/active/ActiveProp5001.cs
@@ -16,17 +16,26 @@
public override bool OnCheckUse()
{
- return Master.WeaponPack.ActiveItem != null && !Master.WeaponPack.ActiveItem.IsAmmoFull();
+ if (Master is AdvancedRole advancedRole)
+ {
+ return advancedRole.WeaponPack.ActiveItem != null && !advancedRole.WeaponPack.ActiveItem.IsAmmoFull();
+ }
+
+ return false;
}
protected override int OnUse()
{
- var weapon = Master.WeaponPack.ActiveItem;
- if (weapon != null)
+ if (Master is AdvancedRole advancedRole)
{
- weapon.SetTotalAmmo(weapon.Attribute.MaxAmmoCapacity);
- return 1;
+ var weapon = advancedRole.WeaponPack.ActiveItem;
+ if (weapon != null)
+ {
+ weapon.SetTotalAmmo(weapon.Attribute.MaxAmmoCapacity);
+ return 1;
+ }
}
+
return 0;
}
}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/activity/prop/buff/BuffProp0013.cs b/DungeonShooting_Godot/src/game/activity/prop/buff/BuffProp0013.cs
index e43270a..05e0202 100644
--- a/DungeonShooting_Godot/src/game/activity/prop/buff/BuffProp0013.cs
+++ b/DungeonShooting_Godot/src/game/activity/prop/buff/BuffProp0013.cs
@@ -8,11 +8,17 @@
{
public override void OnPickUpItem()
{
- Master.WeaponPack.SetCapacity(Master.WeaponPack.Capacity + 1);
+ if (Master is AdvancedRole advancedRole)
+ {
+ advancedRole.WeaponPack.SetCapacity(advancedRole.WeaponPack.Capacity + 1);
+ }
}
public override void OnRemoveItem()
{
- Master.WeaponPack.SetCapacity(Master.WeaponPack.Capacity - 1);
+ if (Master is AdvancedRole advancedRole)
+ {
+ advancedRole.WeaponPack.SetCapacity(advancedRole.WeaponPack.Capacity - 1);
+ }
}
}
\ 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
new file mode 100644
index 0000000..01d64b3
--- /dev/null
+++ b/DungeonShooting_Godot/src/game/activity/role/AdvancedRole.cs
@@ -0,0 +1,430 @@
+using Godot;
+
+///
+/// 高级角色,可以拾起和使用武器
+///
+public abstract partial class AdvancedRole : Role
+{
+ ///
+ /// 角色携带的武器背包
+ ///
+ public Package WeaponPack { get; private set; }
+
+ ///
+ /// 武器挂载点
+ ///
+ [Export, ExportFillNode]
+ public MountRotation MountPoint { get; set; }
+ ///
+ /// 背后武器的挂载点
+ ///
+ [Export, ExportFillNode]
+ public Marker2D BackMountPoint { get; set; }
+
+ ///
+ /// 近战碰撞检测区域
+ ///
+ [Export, ExportFillNode]
+ public Area2D MeleeAttackArea { get; set; }
+
+ ///
+ /// 近战碰撞检测区域的碰撞器
+ ///
+ [Export, ExportFillNode]
+ public CollisionPolygon2D MeleeAttackCollision { get; set; }
+
+ ///
+ /// 近战攻击时挥动武器的角度
+ ///
+ [Export]
+ public float MeleeAttackAngle { get; set; } = 120;
+
+ ///
+ /// 武器挂载点是否始终指向目标
+ ///
+ public bool MountLookTarget { get; set; } = true;
+
+ ///
+ /// 是否处于近战攻击中
+ ///
+ public bool IsMeleeAttack { get; private set; }
+
+ ///
+ /// 当前角色所看向的对象, 也就是枪口指向的对象
+ ///
+ public ActivityObject LookTarget { get; set; }
+
+ //近战计时器
+ private float _meleeAttackTimer = 0;
+
+ ///
+ /// 当拾起某个武器时调用
+ ///
+ protected virtual void OnPickUpWeapon(Weapon weapon)
+ {
+ }
+
+ ///
+ /// 当扔掉某个武器时调用
+ ///
+ protected virtual void OnThrowWeapon(Weapon weapon)
+ {
+ }
+
+ ///
+ /// 当切换到某个武器时调用
+ ///
+ protected virtual void OnExchangeWeapon(Weapon weapon)
+ {
+ }
+
+ public override void OnInit()
+ {
+ base.OnInit();
+ WeaponPack = AddComponent>();
+ WeaponPack.SetCapacity(4);
+
+ MountPoint.Master = this;
+
+ MeleeAttackCollision.Disabled = true;
+ //切换武器回调
+ WeaponPack.ChangeActiveItemEvent += OnChangeActiveItem;
+ //近战区域进入物体
+ MeleeAttackArea.BodyEntered += OnMeleeAttackBodyEntered;
+ }
+
+ protected override void Process(float delta)
+ {
+ if (IsDie)
+ {
+ return;
+ }
+
+ if (_meleeAttackTimer > 0)
+ {
+ _meleeAttackTimer -= delta;
+ }
+
+ //看向目标
+ if (LookTarget != null && MountLookTarget)
+ {
+ var pos = LookTarget.Position;
+ //脸的朝向
+ 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.Process(delta);
+ }
+
+ ///
+ /// 当武器放到后背时调用, 用于设置武器位置和角度
+ ///
+ /// 武器实例
+ /// 放入武器背包的位置
+ public virtual void OnPutBackMount(Weapon weapon, int index)
+ {
+ if (index < 8)
+ {
+ 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;
+ }
+ }
+
+ protected override void OnAffiliationChange(AffiliationArea prevArea)
+ {
+ //身上的武器的所属区域也得跟着变
+ WeaponPack.ForEach((weapon, i) =>
+ {
+ if (AffiliationArea != null)
+ {
+ AffiliationArea.InsertItem(weapon);
+ }
+ else if (weapon.AffiliationArea != null)
+ {
+ weapon.AffiliationArea.RemoveItem(weapon);
+ }
+ });
+ }
+
+ public override Vector2 GetCenterPosition()
+ {
+ return MountPoint.GlobalPosition;
+ }
+
+ public override void LookTargetPosition(Vector2 pos)
+ {
+ LookTarget = null;
+ if (MountLookTarget)
+ {
+ //脸的朝向
+ var gPos = GlobalPosition;
+ 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);
+ }
+ }
+
+ ///
+ /// 返回所有武器是否弹药都打光了
+ ///
+ public bool IsAllWeaponTotalAmmoEmpty()
+ {
+ foreach (var weapon in WeaponPack.ItemSlot)
+ {
+ if (weapon != null && !weapon.IsTotalAmmoEmpty())
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ //-------------------------------------------------------------------------------------
+
+ ///
+ /// 拾起一个武器, 返回是否成功拾起, 如果不想立刻切换到该武器, exchange 请传 false
+ ///
+ /// 武器对象
+ /// 是否立即切换到该武器, 默认 true
+ public bool PickUpWeapon(Weapon weapon, bool exchange = true)
+ {
+ 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);
+ }
+
+ ///
+ /// 切换到下一个武器
+ ///
+ public void ExchangeNextActiveProp()
+ {
+ var prop = ActivePropsPack.ActiveItem;
+ ActivePropsPack.ExchangeNext();
+ if (prop != ActivePropsPack.ActiveItem)
+ {
+ 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);
+ //播放近战动画
+ 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), damage, (role.GetCenterPosition() - GlobalPosition).Angle());
+ }
+ else if (activityObject is Bullet bullet) //攻击子弹
+ {
+ var attackLayer = bullet.AttackLayer;
+ if (CollisionWithMask(attackLayer)) //是攻击玩家的子弹
+ {
+ bullet.PlayDisappearEffect();
+ bullet.Destroy();
+ }
+ }
+ }
+ }
+
+ protected override void OnDestroy()
+ {
+ base.OnDestroy();
+ WeaponPack.Destroy();
+ }
+}
\ No newline at end of file
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/MountRotation.cs b/DungeonShooting_Godot/src/game/activity/role/MountRotation.cs
index e265b10..eca09e9 100644
--- a/DungeonShooting_Godot/src/game/activity/role/MountRotation.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/MountRotation.cs
@@ -15,7 +15,7 @@
///
/// 所在的角色
///
- public Role Master { get; set; }
+ public AdvancedRole Master { get; set; }
///
/// 当前节点真实的旋转角度, 角度制
diff --git a/DungeonShooting_Godot/src/game/activity/role/Role.cs b/DungeonShooting_Godot/src/game/activity/role/Role.cs
index 344294d..2abb192 100644
--- a/DungeonShooting_Godot/src/game/activity/role/Role.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/Role.cs
@@ -1,3 +1,4 @@
+
using System.Collections;
using System.Collections.Generic;
using Godot;
@@ -57,24 +58,8 @@
///
/// 携带的主动道具包裹
///
- public Package ActivePropsPack { get; private set; }
-
- ///
- /// 角色携带的武器背包
- ///
- public Package WeaponPack { get; private set; }
-
- ///
- /// 武器挂载点
- ///
- [Export, ExportFillNode]
- public MountRotation MountPoint { get; set; }
- ///
- /// 背后武器的挂载点
- ///
- [Export, ExportFillNode]
- public Marker2D BackMountPoint { get; set; }
-
+ public Package ActivePropsPack { get; private set; }
+
///
/// 互动碰撞区域
///
@@ -87,30 +72,7 @@
[Export, ExportFillNode]
public CollisionShape2D InteractiveCollision { get; set; }
- ///
- /// 近战碰撞检测区域
- ///
- [Export, ExportFillNode]
- public Area2D MeleeAttackArea { get; set; }
-
- ///
- /// 近战碰撞检测区域的碰撞器
- ///
- [Export, ExportFillNode]
- public CollisionPolygon2D MeleeAttackCollision { get; set; }
-
- ///
- /// 近战攻击时挥动武器的角度
- ///
- [Export]
- public float MeleeAttackAngle { get; set; } = 120;
-
- ///
- /// 武器挂载点是否始终指向目标
- ///
- public bool MountLookTarget { get; set; } = true;
-
- ///
+ ///
/// 脸的朝向
///
public FaceDirection Face { get => _face; set => SetFace(value); }
@@ -241,36 +203,22 @@
private bool _invincible = false;
///
- /// 当前角色所看向的对象, 也就是枪口指向的对象
- ///
- public ActivityObject LookTarget { get; set; }
-
- ///
/// 当前可以互动的物体
///
public ActivityObject InteractiveItem { get; private set; }
-
- ///
- /// 是否可以翻滚
- ///
- public bool CanRoll => _rollCoolingTimer <= 0;
-
- ///
- /// 是否处于近战攻击中
- ///
- public bool IsMeleeAttack { get; private set; }
-
+
///
/// 瞄准辅助线, 需要手动调用 InitSubLine() 初始化
///
public SubLine SubLine { get; private set; }
- //翻滚冷却计时器
- private float _rollCoolingTimer = 0;
+ ///
+ /// 所有角色碰撞的物体
+ ///
+ public List InteractiveItemList { get; } = new List();
+
//初始缩放
private Vector2 _startScale;
- //所有角色碰撞的物体
- private readonly List _interactiveItemList = new List();
//当前可互动的物体
private CheckInteractiveResult _currentResultData;
private uint _currentLayer;
@@ -282,9 +230,8 @@
private long _invincibleFlashingId = -1;
//护盾恢复计时器
private float _shieldRecoveryTimer = 0;
- //近战计时器
- private float _meleeAttackTimer = 0;
+
///
/// 当血量改变时调用
///
@@ -353,28 +300,8 @@
protected virtual void OnDie()
{
}
-
- ///
- /// 当拾起某个武器时调用
- ///
- protected virtual void OnPickUpWeapon(Weapon weapon)
- {
- }
- ///
- /// 当扔掉某个武器时调用
- ///
- protected virtual void OnThrowWeapon(Weapon weapon)
- {
- }
-
- ///
- /// 当切换到某个武器时调用
- ///
- protected virtual void OnExchangeWeapon(Weapon weapon)
- {
- }
-
+
///
/// 当拾起某个主动道具时调用
///
@@ -409,16 +336,21 @@
protected virtual void OnRemoveBuffProp(BuffProp buffProp)
{
}
-
+
+
+ ///
+ /// 触发攻击
+ ///
+ public virtual void Attack()
+ {
+ }
+
public override void OnInit()
{
- ActivePropsPack = AddComponent>();
+ ActivePropsPack = AddComponent>();
ActivePropsPack.SetCapacity(1);
- WeaponPack = AddComponent>();
- WeaponPack.SetCapacity(4);
-
+
_startScale = Scale;
- MountPoint.Master = this;
HurtArea.CollisionLayer = CollisionLayer;
HurtArea.CollisionMask = 0;
@@ -429,56 +361,18 @@
//连接互动物体信号
InteractiveArea.BodyEntered += _OnPropsEnter;
InteractiveArea.BodyExited += _OnPropsExit;
-
- MeleeAttackCollision.Disabled = true;
- //切换武器回调
- WeaponPack.ChangeActiveItemEvent += OnChangeActiveItem;
- //近战区域进入物体
- MeleeAttackArea.BodyEntered += OnMeleeAttackBodyEntered;
}
protected override void Process(float delta)
{
- if (IsDie)
- {
- return;
- }
- if (_rollCoolingTimer > 0)
- {
- _rollCoolingTimer -= delta;
- }
-
- if (_meleeAttackTimer > 0)
- {
- _meleeAttackTimer -= delta;
- }
-
- //看向目标
- if (LookTarget != null && MountLookTarget)
- {
- Vector2 pos = LookTarget.GlobalPosition;
- //脸的朝向
- var gPos = GlobalPosition;
- 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);
- }
-
- //检查可互动的物体
+ //检查可互动的物体
bool findFlag = false;
- for (int i = 0; i < _interactiveItemList.Count; i++)
+ for (int i = 0; i < InteractiveItemList.Count; i++)
{
- var item = _interactiveItemList[i];
+ var item = InteractiveItemList[i];
if (item == null || item.IsDestroyed)
{
- _interactiveItemList.RemoveAt(i--);
+ InteractiveItemList.RemoveAt(i--);
}
else if (!item.IsThrowing)
{
@@ -578,8 +472,9 @@
}
}
}
+
}
-
+
///
/// 初始化瞄准辅助线
///
@@ -593,50 +488,7 @@
SubLine = AddComponent();
}
- ///
- /// 当武器放到后背时调用, 用于设置武器位置和角度
- ///
- /// 武器实例
- /// 放入武器背包的位置
- public virtual void OnPutBackMount(Weapon weapon, int index)
- {
- if (index < 8)
- {
- 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;
- }
- }
- protected override void OnAffiliationChange(AffiliationArea prevArea)
- {
- //身上的武器的所属区域也得跟着变
- WeaponPack.ForEach((weapon, i) =>
- {
- if (AffiliationArea != null)
- {
- AffiliationArea.InsertItem(weapon);
- }
- else if (weapon.AffiliationArea != null)
- {
- weapon.AffiliationArea.RemoveItem(weapon);
- }
- });
- }
-
///
/// 是否是满血
///
@@ -648,32 +500,25 @@
///
/// 获取当前角色的中心点坐标
///
- public Vector2 GetCenterPosition()
+ public virtual Vector2 GetCenterPosition()
{
- return MountPoint.GlobalPosition;
+ return AnimatedSprite.GlobalPosition;
}
-
+
///
- /// 使角色看向指定的坐标,
- /// 注意, 调用该函数会清空 LookTarget, 因为拥有 LookTarget 时也会每帧更新玩家视野位置
+ /// 使角色看向指定的坐标的方向
///
- public void LookTargetPosition(Vector2 pos)
+ public virtual void LookTargetPosition(Vector2 pos)
{
- LookTarget = null;
- if (MountLookTarget)
+ //脸的朝向
+ var gPos = GlobalPosition;
+ if (pos.X > gPos.X && Face == FaceDirection.Left)
{
- //脸的朝向
- var gPos = GlobalPosition;
- 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);
+ Face = FaceDirection.Right;
+ }
+ else if (pos.X < gPos.X && Face == FaceDirection.Right)
+ {
+ Face = FaceDirection.Left;
}
}
@@ -686,101 +531,9 @@
return (Face == FaceDirection.Left && pos.X <= gps.X) ||
(Face == FaceDirection.Right && pos.X >= gps.X);
}
-
- ///
- /// 返回所有武器是否弹药都打光了
- ///
- public bool IsAllWeaponTotalAmmoEmpty()
- {
- foreach (var weapon in WeaponPack.ItemSlot)
- {
- if (weapon != null && !weapon.IsTotalAmmoEmpty())
- {
- return false;
- }
- }
-
- return true;
- }
- //-------------------------------------------------------------------------------------
///
- /// 拾起一个武器, 返回是否成功拾起, 如果不想立刻切换到该武器, exchange 请传 false
- ///
- /// 武器对象
- /// 是否立即切换到该武器, 默认 true
- public bool PickUpWeapon(Weapon weapon, bool exchange = true)
- {
- 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);
- }
-
- ///
/// 拾起主动道具, 返回是否成功拾起, 如果不想立刻切换到该道具, exchange 请传 false
///
/// 主动道具对象
@@ -790,7 +543,7 @@
if (ActivePropsPack.PickupItem(activeProp, exchange) != -1)
{
//从可互动队列中移除
- _interactiveItemList.Remove(activeProp);
+ InteractiveItemList.Remove(activeProp);
OnPickUpActiveProp(activeProp);
return true;
}
@@ -799,32 +552,6 @@
}
///
- /// 切换到下一个武器
- ///
- public void ExchangeNextActiveProp()
- {
- var prop = ActivePropsPack.ActiveItem;
- ActivePropsPack.ExchangeNext();
- if (prop != ActivePropsPack.ActiveItem)
- {
- OnExchangeActiveProp(ActivePropsPack.ActiveItem);
- }
- }
-
- ///
- /// 切换到上一个武器
- ///
- public void ExchangePrevActiveProp()
- {
- var prop = ActivePropsPack.ActiveItem;
- ActivePropsPack.ExchangePrev();
- if (prop != ActivePropsPack.ActiveItem)
- {
- OnExchangeActiveProp(ActivePropsPack.ActiveItem);
- }
- }
-
- ///
/// 扔掉当前使用的道具
///
public void ThrowActiveProp()
@@ -901,8 +628,7 @@
//播放抛出效果
buffProp.ThrowProp(this, GlobalPosition);
}
-
- //-------------------------------------------------------------------------------------
+
///
/// 返回是否存在可互动的物体
@@ -926,55 +652,8 @@
return null;
}
-
- ///
- /// 触发换弹
- ///
- public virtual void Reload()
- {
- if (WeaponPack.ActiveItem != null)
- {
- WeaponPack.ActiveItem.Reload();
- }
- }
-
- ///
- /// 触发攻击
- ///
- public virtual 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);
- //播放近战动画
- PlayAnimation_MeleeAttack(() =>
- {
- MountLookTarget = true;
- IsMeleeAttack = false;
- });
- }
- }
-
+
+
///
/// 触发使用道具
///
@@ -1102,9 +781,9 @@
{
if (other is ActivityObject propObject && !propObject.CollisionWithMask(PhysicsLayer.OnHand))
{
- if (!_interactiveItemList.Contains(propObject))
+ if (!InteractiveItemList.Contains(propObject))
{
- _interactiveItemList.Add(propObject);
+ InteractiveItemList.Add(propObject);
}
}
}
@@ -1117,9 +796,9 @@
{
if (other is ActivityObject propObject)
{
- if (_interactiveItemList.Contains(propObject))
+ if (InteractiveItemList.Contains(propObject))
{
- _interactiveItemList.Remove(propObject);
+ InteractiveItemList.Remove(propObject);
}
if (InteractiveItem == propObject)
{
@@ -1130,87 +809,8 @@
}
}
}
-
- ///
- /// 切换当前使用的武器的回调
- ///
- 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 Role 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), damage, (role.GetCenterPosition() - GlobalPosition).Angle());
- }
- else if (activityObject is Bullet bullet) //攻击子弹
- {
- var attackLayer = bullet.AttackLayer;
- if (CollisionWithMask(attackLayer)) //是攻击玩家的子弹
- {
- bullet.PlayDisappearEffect();
- bullet.Destroy();
- }
- }
- }
- }
-
- protected override void OnDestroy()
- {
- //销毁道具
- foreach (var buffProp in BuffPropPack)
- {
- buffProp.Destroy();
- }
- BuffPropPack.Clear();
- ActivePropsPack.Destroy();
- WeaponPack.Destroy();
- }
-
- ///
- /// 翻滚结束
- ///
- public void OverRoll()
- {
- _rollCoolingTimer = RoleState.RollTime;
- }
-
+
+
///
/// 返回当前角色是否是玩家
///
@@ -1241,4 +841,15 @@
return Mathf.Pi - rotation;
}
+
+ protected override void OnDestroy()
+ {
+ //销毁道具
+ foreach (var buffProp in BuffPropPack)
+ {
+ buffProp.Destroy();
+ }
+ BuffPropPack.Clear();
+ ActivePropsPack.Destroy();
+ }
}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/activity/role/Role_Animation.cs b/DungeonShooting_Godot/src/game/activity/role/Role_Animation.cs
deleted file mode 100644
index 1dfcc68..0000000
--- a/DungeonShooting_Godot/src/game/activity/role/Role_Animation.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-
-using System;
-using Godot;
-using Vector2 = Godot.Vector2;
-
-public partial class Role
-{
- ///
- /// 播放近战攻击动画
- ///
- 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/SubLine.cs b/DungeonShooting_Godot/src/game/activity/role/SubLine.cs
index 5f9dd84..03039ac 100644
--- a/DungeonShooting_Godot/src/game/activity/role/SubLine.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/SubLine.cs
@@ -5,7 +5,7 @@
///
/// 瞄准辅助线
///
-public class SubLine : Component
+public class SubLine : Component
{
///
/// 是否正在播放警告闪烁动画
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs
index c9f9a7f..6fecea5 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs
@@ -18,7 +18,7 @@
/// 基础敌人
///
[Tool]
-public partial class Enemy : Role
+public partial class Enemy : AdvancedRole
{
///
/// 目标是否在视野内
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiNormalState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiNormalState.cs
index b0a208c..a18851f 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiNormalState.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiNormalState.cs
@@ -110,7 +110,7 @@
{
var pos = Master.GlobalPosition;
var lastSlideCollision = Master.GetLastSlideCollision();
- if (lastSlideCollision != null && lastSlideCollision.GetCollider() is Role) //碰到其他角色
+ if (lastSlideCollision != null && lastSlideCollision.GetCollider() is AdvancedRole) //碰到其他角色
{
_pauseTimer = Utils.Random.RandomRangeFloat(0.1f, 0.5f);
_isMoveOver = true;
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiSurroundState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiSurroundState.cs
index 967cc65..38a6284 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiSurroundState.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiSurroundState.cs
@@ -110,7 +110,7 @@
{
var pos = Master.GlobalPosition;
var lastSlideCollision = Master.GetLastSlideCollision();
- if (lastSlideCollision != null && lastSlideCollision.GetCollider() is Role) //碰到其他角色
+ if (lastSlideCollision != null && lastSlideCollision.GetCollider() is AdvancedRole) //碰到其他角色
{
_pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.3f);
_isMoveOver = true;
diff --git a/DungeonShooting_Godot/src/game/activity/role/player/Player.cs b/DungeonShooting_Godot/src/game/activity/role/player/Player.cs
index 47146fd..3b7fc1d 100644
--- a/DungeonShooting_Godot/src/game/activity/role/player/Player.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/player/Player.cs
@@ -6,7 +6,7 @@
/// 玩家角色基类, 所有角色都必须继承该类
///
[Tool]
-public partial class Player : Role
+public partial class Player : AdvancedRole
{
///
/// 获取当前操作的角色
@@ -19,6 +19,14 @@
public StateController StateController { get; private set; }
///
+ /// 是否可以翻滚
+ ///
+ public bool CanRoll => _rollCoolingTimer <= 0;
+
+ //翻滚冷却计时器
+ private float _rollCoolingTimer = 0;
+
+ ///
/// 设置当前操作的玩家对象
///
public static void SetCurrentPlayer(Player player)
@@ -325,6 +333,14 @@
}
}
+ ///
+ /// 翻滚结束
+ ///
+ public void OverRoll()
+ {
+ _rollCoolingTimer = RoleState.RollTime;
+ }
+
// protected override void DebugDraw()
// {
// base.DebugDraw();
diff --git a/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs b/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs
index e12efa8..2e2400b 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;
@@ -148,7 +148,7 @@
///
/// 上一次触发改武器开火的角色, 可能为 null
///
- public Role TriggerRole { get; private set; }
+ public AdvancedRole TriggerRole { get; private set; }
///
/// 上一次触发改武器开火的触发开火攻击的层级, 数据源自于:
@@ -397,7 +397,7 @@
/// 当武器被拾起时调用
///
/// 拾起该武器的角色
- protected virtual void OnPickUp(Role master)
+ protected virtual void OnPickUp(AdvancedRole master)
{
}
@@ -405,7 +405,7 @@
/// 当武器从武器背包中移除时调用
///
/// 移除该武器的角色
- protected virtual void OnRemove(Role master)
+ protected virtual void OnRemove(AdvancedRole master)
{
}
@@ -695,7 +695,7 @@
/// 扳机函数, 调用即视为按下扳机
///
/// 按下扳机的角色, 如果传 null, 则视为走火
- public void Trigger(Role triggerRole)
+ public void Trigger(AdvancedRole triggerRole)
{
//不能触发扳机
if (!NoMasterCanTrigger && Master == null) return;
@@ -1097,7 +1097,7 @@
///
/// 根据触扳机的角色对象判断该角色使用的武器数据
///
- public ExcelConfig.WeaponBase GetUseAttribute(Role triggerRole)
+ public ExcelConfig.WeaponBase GetUseAttribute(AdvancedRole triggerRole)
{
if (triggerRole == null || !triggerRole.IsAi)
{
@@ -1117,7 +1117,7 @@
{
return (uint)TriggerRoleAttackLayer;
}
- return Master != null ? Master.AttackLayer : Role.DefaultAttackLayer;
+ return Master != null ? Master.AttackLayer : AdvancedRole.DefaultAttackLayer;
}
///
@@ -1606,7 +1606,7 @@
{
var result = new CheckInteractiveResult(this);
- if (master is Role roleMaster) //碰到角色
+ if (master is AdvancedRole roleMaster) //碰到角色
{
if (Master == null)
{
@@ -1652,7 +1652,7 @@
public override void Interactive(ActivityObject master)
{
- if (master is Role roleMaster) //与role互动
+ if (master is AdvancedRole roleMaster) //与role互动
{
var holster = roleMaster.WeaponPack;
//查找是否有同类型武器
@@ -1727,7 +1727,7 @@
/// 触发扔掉武器时抛出的效果, 并不会管武器是否在武器背包中
///
/// 触发扔掉该武器的的角色
- public void ThrowWeapon(Role master)
+ public void ThrowWeapon(AdvancedRole master)
{
ThrowWeapon(master, master.GlobalPosition);
}
@@ -1737,7 +1737,7 @@
///
/// 触发扔掉该武器的的角色
/// 投抛起始位置
- public void ThrowWeapon(Role master, Vector2 startPosition)
+ public void ThrowWeapon(AdvancedRole master, Vector2 startPosition)
{
//阴影偏移
ShadowOffset = new Vector2(0, 2);
diff --git a/DungeonShooting_Godot/src/game/activity/weapon/knife/Knife.cs b/DungeonShooting_Godot/src/game/activity/weapon/knife/Knife.cs
index f54b9d3..1df0f76 100644
--- a/DungeonShooting_Godot/src/game/activity/weapon/knife/Knife.cs
+++ b/DungeonShooting_Godot/src/game/activity/weapon/knife/Knife.cs
@@ -127,7 +127,7 @@
var activityObject = body.AsActivityObject();
if (activityObject != null)
{
- if (activityObject is Role role) //碰到角色
+ if (activityObject is AdvancedRole role) //碰到角色
{
var damage = Utils.Random.RandomConfigRange(Attribute.Bullet.HarmRange);
//计算子弹造成的伤害
@@ -159,7 +159,7 @@
}
//造成伤害
- role.CallDeferred(nameof(Role.Hurt), damage, (role.GetCenterPosition() - GlobalPosition).Angle());
+ role.CallDeferred(nameof(AdvancedRole.Hurt), damage, (role.GetCenterPosition() - GlobalPosition).Angle());
}
else if (activityObject is Bullet bullet) //攻击子弹
{
diff --git a/DungeonShooting_Godot/src/game/camera/GameCamera.cs b/DungeonShooting_Godot/src/game/camera/GameCamera.cs
index 27827a8..74a355b 100644
--- a/DungeonShooting_Godot/src/game/camera/GameCamera.cs
+++ b/DungeonShooting_Godot/src/game/camera/GameCamera.cs
@@ -50,7 +50,7 @@
///
/// 相机跟随目标
///
- private Role _followTarget;
+ private AdvancedRole _followTarget;
// 3.5
//public Vector2 SubPixelPosition { get; private set; }
@@ -122,7 +122,7 @@
///
/// 设置相机跟随目标
///
- public void SetFollowTarget(Role target)
+ public void SetFollowTarget(AdvancedRole target)
{
_followTarget = target;
if (target != null)
@@ -135,7 +135,7 @@
///
/// 获取相机跟随目标
///
- public Role GetFollowTarget()
+ public AdvancedRole GetFollowTarget()
{
return _followTarget;
}
diff --git a/DungeonShooting_Godot/src/game/data/BulletData.cs b/DungeonShooting_Godot/src/game/data/BulletData.cs
index cd57ab2..34547ad 100644
--- a/DungeonShooting_Godot/src/game/data/BulletData.cs
+++ b/DungeonShooting_Godot/src/game/data/BulletData.cs
@@ -20,7 +20,7 @@
///
/// 发射该子弹的角色
///
- public Role TriggerRole;
+ public AdvancedRole TriggerRole;
///
/// 造成的伤害
diff --git a/DungeonShooting_Godot/src/game/manager/SoundManager.cs b/DungeonShooting_Godot/src/game/manager/SoundManager.cs
index 2195543..80790b0 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, Role triggerRole = null)
+ public static GameAudioPlayer2D PlaySoundByConfig(string id, Vector2 viewPosition, AdvancedRole 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, Role triggerRole = null)
+ public static GameAudioPlayer2D PlaySoundByConfig(ExcelConfig.Sound sound, Vector2 viewPosition, AdvancedRole triggerRole = null)
{
return PlaySoundEffectPosition(
sound.Path,
@@ -226,7 +226,7 @@
/// 播放音效的位置, 该位置为 SubViewport 下的坐标, 也就是 使用的坐标
/// 延时时间
/// 触发播放音效的角色, 因为 Npc 产生的音效声音更小, 可以传 null
- public static GameAudioPlayer2D PlaySoundByConfigDelay(string id, Vector2 viewPosition, float delayTime, Role triggerRole = null)
+ public static GameAudioPlayer2D PlaySoundByConfigDelay(string id, Vector2 viewPosition, float delayTime, AdvancedRole 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, Role triggerRole = null)
+ public static GameAudioPlayer2D PlaySoundByConfigDelay(ExcelConfig.Sound sound, Vector2 viewPosition, float delayTime, AdvancedRole triggerRole = null)
{
return PlaySoundEffectPositionDelay(
sound.Path,
@@ -303,7 +303,7 @@
///
/// 计算指定角色播放音效使用的音量
///
- public static float CalcRoleVolume(float volume, Role role)
+ public static float CalcRoleVolume(float volume, AdvancedRole role)
{
if (role is not Player)
{