diff --git a/DungeonShooting_Godot/src/game/item/package/Holster.cs b/DungeonShooting_Godot/src/game/item/package/Holster.cs
index a737b40..2b281b2 100644
--- a/DungeonShooting_Godot/src/game/item/package/Holster.cs
+++ b/DungeonShooting_Godot/src/game/item/package/Holster.cs
@@ -29,7 +29,9 @@
/// 归属者
///
public Role Master { get; }
-
+
+ //public Weapon HandheldWeapon { get; private set; }
+
///
/// 当前使用的武器对象
///
@@ -68,6 +70,23 @@
}
///
+ /// 返回当前武器袋是否还有空位
+ ///
+ public bool HasVacancy()
+ {
+ for (int i = 0; i < SlotList.Length; i++)
+ {
+ var item = SlotList[i];
+ if (item.Enable && item.Weapon == null)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ ///
/// 根据索引获取武器
///
public Weapon GetWeapon(int index) {
@@ -87,7 +106,7 @@
for (int i = 0; i < SlotList.Length; i++)
{
var item = SlotList[i];
- if (item.Weapon != null && item.Weapon.Id == id)
+ if (item.Weapon != null && item.Weapon.TypeId == id)
{
return i;
}
@@ -134,7 +153,8 @@
/// 拾起武器, 存入武器袋中, 返回存放在武器袋的位置, 如果容不下这把武器, 则会返回 -1
///
/// 武器对象
- public int PickupWeapon(Weapon weapon)
+ /// 是否立即切换到该武器, 默认 true
+ public int PickupWeapon(Weapon weapon, bool exchange = true)
{
//已经被拾起了
if (weapon.Master != null)
@@ -149,7 +169,11 @@
weapon.Pickup();
item.Weapon = weapon;
weapon.PickUpWeapon(Master);
- ExchangeByIndex(i);
+ if (exchange)
+ {
+ ExchangeByIndex(i);
+ }
+
return i;
}
}
diff --git a/DungeonShooting_Godot/src/game/item/weapon/Weapon.cs b/DungeonShooting_Godot/src/game/item/weapon/Weapon.cs
index 4bbf70a..297cfd3 100644
--- a/DungeonShooting_Godot/src/game/item/weapon/Weapon.cs
+++ b/DungeonShooting_Godot/src/game/item/weapon/Weapon.cs
@@ -7,9 +7,9 @@
public abstract class Weapon : ActivityObject
{
///
- /// 武器的唯一id
+ /// 武器的类型 id
///
- public string Id { get; }
+ public string TypeId { get; }
///
/// 开火回调事件
@@ -158,15 +158,15 @@
//当前后坐力导致的偏移长度
private float _currBacklashLength = 0;
-
+
///
/// 根据属性创建一把武器
///
- /// 武器唯一id
+ /// 武器的类型id
/// 属性
- public Weapon(string id, WeaponAttribute attribute) : base(attribute.WeaponPrefab)
+ public Weapon(string typeId, WeaponAttribute attribute) : base(attribute.WeaponPrefab)
{
- Id = id;
+ TypeId = typeId;
Attribute = attribute;
FirePoint = GetNode("WeaponBody/FirePoint");
@@ -186,7 +186,7 @@
if (Attribute.AmmoCapacity > Attribute.MaxAmmoCapacity)
{
Attribute.AmmoCapacity = Attribute.MaxAmmoCapacity;
- GD.PrintErr("弹夹的容量不能超过弹药上限, 武器id: " + id);
+ GD.PrintErr("弹夹的容量不能超过弹药上限, 武器id: " + typeId);
}
//弹药量
CurrAmmo = Attribute.AmmoCapacity;
@@ -763,7 +763,7 @@
{
var masterWeapon = roleMaster.Holster.ActiveWeapon;
//查找是否有同类型武器
- var index = roleMaster.Holster.FindWeapon(Id);
+ var index = roleMaster.Holster.FindWeapon(TypeId);
if (index != -1) //如果有这个武器
{
if (CurrAmmo + ResidueAmmo != 0) //子弹不为空
@@ -774,7 +774,7 @@
//可以互动拾起弹药
result.CanInteractive = true;
result.Message = Attribute.Name;
- result.ShowIcon = "res://resource/sprite/ui/icon/icon_bullet.png";
+ result.ShowIcon = ResourcePath.resource_sprite_ui_icon_icon_bullet_png;
return result;
}
}
@@ -786,7 +786,7 @@
//可以互动, 拾起武器
result.CanInteractive = true;
result.Message = Attribute.Name;
- result.ShowIcon = "res://resource/sprite/ui/icon/icon_pickup.png";
+ result.ShowIcon = ResourcePath.resource_sprite_ui_icon_icon_pickup_png;
return result;
}
else if (masterWeapon != null && masterWeapon.Attribute.WeightType == Attribute.WeightType) //替换武器
@@ -794,7 +794,7 @@
//可以互动, 切换武器
result.CanInteractive = true;
result.Message = Attribute.Name;
- result.ShowIcon = "res://resource/sprite/ui/icon/icon_replace.png";
+ result.ShowIcon = ResourcePath.resource_sprite_ui_icon_icon_replace_png;
return result;
}
}
@@ -810,7 +810,7 @@
{
var holster = roleMaster.Holster;
//查找是否有同类型武器
- var index = holster.FindWeapon(Id);
+ var index = holster.FindWeapon(TypeId);
if (index != -1) //如果有这个武器
{
if (CurrAmmo + ResidueAmmo == 0) //没有子弹了
diff --git a/DungeonShooting_Godot/src/game/item/weapon/gun/Gun.cs b/DungeonShooting_Godot/src/game/item/weapon/gun/Gun.cs
index eddf18b..abee1bf 100644
--- a/DungeonShooting_Godot/src/game/item/weapon/gun/Gun.cs
+++ b/DungeonShooting_Godot/src/game/item/weapon/gun/Gun.cs
@@ -24,8 +24,8 @@
//连发
ContinuousShoot = true;
AmmoCapacity = 30;
- StandbyAmmoCapacity = 30 * 70;
- MaxAmmoCapacity = 30 * 70;
+ StandbyAmmoCapacity = 30 * 3;
+ MaxAmmoCapacity = 30 * 3;
//扳机检测间隔
TriggerInterval = 0f;
//连发数量
@@ -86,7 +86,7 @@
}
}
- public Gun(string id, WeaponAttribute attribute): base(id, attribute)
+ public Gun(string typeId, WeaponAttribute attribute): base(typeId, attribute)
{
}
diff --git a/DungeonShooting_Godot/src/game/item/weapon/gun/Shotgun.cs b/DungeonShooting_Godot/src/game/item/weapon/gun/Shotgun.cs
index 3e9d8e3..46713db 100644
--- a/DungeonShooting_Godot/src/game/item/weapon/gun/Shotgun.cs
+++ b/DungeonShooting_Godot/src/game/item/weapon/gun/Shotgun.cs
@@ -34,8 +34,8 @@
MinDistance = 200;
MaxDistance = 250;
//发射子弹数量
- MinFireBulletCount = 1;
- MaxFireBulletCount = 1;
+ MinFireBulletCount = 5;
+ MaxFireBulletCount = 5;
//抬起角度
UpliftAngle = 15;
MaxBacklash = 6;
@@ -50,7 +50,7 @@
///
public PackedScene ShellPack;
- public Shotgun(string id, WeaponAttribute attribute) : base(id, attribute)
+ public Shotgun(string typeId, WeaponAttribute attribute) : base(typeId, attribute)
{
ShellPack = ResourceManager.Load(ResourcePath.prefab_weapon_shell_ShellCase_tscn);
}
@@ -86,20 +86,15 @@
protected override void OnShoot(float fireRotation)
{
- for (int i = 0; i < 5; i++)
- {
- //创建子弹
- //CreateBullet(BulletPack, FirePoint.GlobalPosition, fireRotation + MathUtils.RandRange(-20 / 180f * Mathf.Pi, 20 / 180f * Mathf.Pi));
-
- var bullet = new Bullet(
- ResourcePath.prefab_weapon_bullet_Bullet_tscn,
- Utils.RandRangeInt(280, 380),
- Utils.RandRange(Attribute.MinDistance, Attribute.MaxDistance),
- FirePoint.GlobalPosition,
- fireRotation + Utils.RandRange(-20 / 180f * Mathf.Pi, 20 / 180f * Mathf.Pi),
- GetAttackLayer()
- );
- bullet.PutDown();
- }
+ //创建子弹
+ var bullet = new Bullet(
+ ResourcePath.prefab_weapon_bullet_Bullet_tscn,
+ Utils.RandRangeInt(280, 380),
+ Utils.RandRange(Attribute.MinDistance, Attribute.MaxDistance),
+ FirePoint.GlobalPosition,
+ fireRotation + Utils.RandRange(-20 / 180f * Mathf.Pi, 20 / 180f * Mathf.Pi),
+ GetAttackLayer()
+ );
+ bullet.PutDown();
}
}
diff --git a/DungeonShooting_Godot/src/game/item/weapon/knife/Knife.cs b/DungeonShooting_Godot/src/game/item/weapon/knife/Knife.cs
index 60a3427..aee151f 100644
--- a/DungeonShooting_Godot/src/game/item/weapon/knife/Knife.cs
+++ b/DungeonShooting_Godot/src/game/item/weapon/knife/Knife.cs
@@ -22,6 +22,7 @@
MaxAmmoCapacity = AmmoCapacity;
//握把位置
HoldPosition = new Vector2(10, 0);
+ MaxDistance = MinDistance = 35;
//后坐力改为向前, 模拟手伸长的效果
MaxBacklash = -8;
MinBacklash = -8;
@@ -34,7 +35,7 @@
private int _attackIndex = 0;
- public Knife(string id, WeaponAttribute attribute) : base(id, attribute)
+ public Knife(string typeId, WeaponAttribute attribute) : base(typeId, attribute)
{
_hitArea = GetNode("HitArea");
_hitArea.Monitoring = false;
diff --git a/DungeonShooting_Godot/src/game/role/Role.cs b/DungeonShooting_Godot/src/game/role/Role.cs
index 80a19ee..a524d9b 100644
--- a/DungeonShooting_Godot/src/game/role/Role.cs
+++ b/DungeonShooting_Godot/src/game/role/Role.cs
@@ -157,7 +157,7 @@
///
/// 可以互动的道具
///
- protected ActivityObject InteractiveItem { get; private set; }
+ public ActivityObject InteractiveItem { get; private set; }
///
/// 当血量改变时调用
@@ -368,12 +368,13 @@
}
///
- /// 拾起一个武器, 并且切换到这个武器, 返回是否成功拾取
+ /// 拾起一个武器, 返回是否成功拾取, 如果不想立刻切换到该武器, exchange 请传 false
///
/// 武器对象
- public virtual bool PickUpWeapon(Weapon weapon)
+ /// 是否立即切换到该武器, 默认 true
+ public virtual bool PickUpWeapon(Weapon weapon, bool exchange = true)
{
- if (Holster.PickupWeapon(weapon) != -1)
+ if (Holster.PickupWeapon(weapon, exchange) != -1)
{
//从可互动队列中移除
_interactiveItemList.Remove(weapon);
@@ -404,7 +405,16 @@
///
public virtual void ThrowWeapon()
{
- var weapon = Holster.RemoveWeapon(Holster.ActiveIndex);
+ ThrowWeapon(Holster.ActiveIndex);
+ }
+
+ ///
+ /// 扔掉指定位置的武器
+ ///
+ /// 武器在武器袋中的位置
+ public virtual void ThrowWeapon(int index)
+ {
+ var weapon = Holster.RemoveWeapon(index);
//播放抛出效果
if (weapon != null)
{
@@ -431,6 +441,7 @@
item.Interactive(this);
return item;
}
+
return null;
}
diff --git a/DungeonShooting_Godot/src/game/role/enemy/Enemy.cs b/DungeonShooting_Godot/src/game/role/enemy/Enemy.cs
index 098fb0e..773a1f9 100644
--- a/DungeonShooting_Godot/src/game/role/enemy/Enemy.cs
+++ b/DungeonShooting_Godot/src/game/role/enemy/Enemy.cs
@@ -19,12 +19,12 @@
///
public class Enemy : Role
{
-
+
///
/// 公共属性, 是否找到目标, 如果找到目标, 则所有敌人都会知道玩家的位置
///
public static bool IsFindTarget { get; private set; }
-
+
///
/// 找到的目标的位置, 如果目标在视野内, 则一直更新
///
@@ -56,7 +56,7 @@
/// 视野检测射线, 朝玩家打射线, 检测是否碰到墙
///
public RayCast2D ViewRay { get; }
-
+
///
/// 导航代理
///
@@ -68,7 +68,7 @@
public Position2D NavigationPoint { get; }
private float _enemyAttackTimer = 0;
-
+
public Enemy() : base(ResourcePath.prefab_role_Enemy_tscn)
{
StateController = new StateController();
@@ -96,14 +96,12 @@
StateController.Register(new AiFollowUpState());
StateController.Register(new AiLeaveForState());
StateController.Register(new AiSurroundState());
+ StateController.Register(new AiFindAmmoState());
}
public override void _Ready()
{
base._Ready();
- //防撞速度计算
- NavigationAgent2D.Connect("velocity_computed", this, nameof(OnVelocityComputed));
-
//默认状态
StateController.ChangeState(AiStateEnum.AiNormal);
@@ -120,6 +118,7 @@
public override void _ExitTree()
{
+ base._ExitTree();
_enemies.Remove(this);
}
@@ -128,6 +127,8 @@
base._PhysicsProcess(delta);
_enemyAttackTimer -= delta;
+
+ EnemyPickUpWeapon();
}
///
@@ -157,17 +158,20 @@
{
if (weapon.IsTotalAmmoEmpty()) //当前武器弹药打空
{
- //扔掉当前武器
- ThrowWeapon();
- // var index = Holster.FindWeapon(we => !we.IsTotalAmmoEmpty());
- // if (index != -1)
- // {
- //
- // }
+ //切换到有子弹的武器
+ var index = Holster.FindWeapon(we => !we.IsTotalAmmoEmpty());
+ if (index != -1)
+ {
+ Holster.ExchangeByIndex(index);
+ }
+ else //所有子弹打光, 去寻找武器
+ {
+ //StateController.ChangeStateLate(AiStateEnum.AiFindAmmo);
+ }
}
else if (weapon.Reloading) //换弹中
{
-
+
}
else if (weapon.IsAmmoEmpty()) //弹夹已经打空
{
@@ -183,7 +187,7 @@
{
if (_enemyAttackTimer <= 0)
{
- _enemyAttackTimer = 60f / weapon.Attribute.StartFiringSpeed;
+ _enemyAttackTimer = 60f / weapon.Attribute.StartFiringSpeed + Utils.RandRange(0, 0.06f);
Attack();
}
}
@@ -259,8 +263,52 @@
ViewRay.Enabled = false;
}
- private void OnVelocityComputed(Vector2 velocity)
+ ///
+ /// AI 拾起武器操作
+ ///
+ private void EnemyPickUpWeapon()
{
- GD.Print("velocity: " + velocity);
+ //拾起地上的武器
+ if (InteractiveItem is Weapon weapon)
+ {
+ if (Holster.ActiveWeapon == null) //手上没有武器, 无论如何也要拾起
+ {
+ TriggerInteractive();
+ return;
+ }
+
+ //没弹药了
+ if (weapon.IsTotalAmmoEmpty())
+ {
+ return;
+ }
+
+ var index = Holster.FindWeapon(we => we.TypeId == weapon.TypeId);
+ if (index != -1) //与武器袋中武器类型相同, 补充子弹
+ {
+ if (!Holster.GetWeapon(index).IsAmmoFull())
+ {
+ TriggerInteractive();
+ }
+
+ return;
+ }
+
+ var index2 = Holster.FindWeapon(we =>
+ we.Attribute.WeightType == weapon.Attribute.WeightType && we.IsTotalAmmoEmpty());
+ if (index2 != -1) //则扔掉没子弹的武器
+ {
+ ThrowWeapon(index2);
+ TriggerInteractive();
+ return;
+ }
+
+ if (Holster.HasVacancy()) //有空位, 拾起武器
+ {
+ TriggerInteractive();
+ return;
+ }
+ }
}
+
}
diff --git a/DungeonShooting_Godot/src/game/role/enemy/state/AIStateEnum.cs b/DungeonShooting_Godot/src/game/role/enemy/state/AIStateEnum.cs
index e94b6fb..816e2c7 100644
--- a/DungeonShooting_Godot/src/game/role/enemy/state/AIStateEnum.cs
+++ b/DungeonShooting_Godot/src/game/role/enemy/state/AIStateEnum.cs
@@ -2,7 +2,7 @@
public enum AiStateEnum
{
///
- /// ai状态, 正常, 未发现目标
+ /// Ai 状态, 正常, 未发现目标
///
AiNormal,
///
@@ -25,4 +25,8 @@
/// 距离足够进, 在目标附近随机移动
///
AiSurround,
+ ///
+ /// Ai 寻找弹药
+ ///
+ AiFindAmmo,
}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/role/enemy/state/AiFindAmmoState.cs b/DungeonShooting_Godot/src/game/role/enemy/state/AiFindAmmoState.cs
new file mode 100644
index 0000000..5ef4304
--- /dev/null
+++ b/DungeonShooting_Godot/src/game/role/enemy/state/AiFindAmmoState.cs
@@ -0,0 +1,27 @@
+
+using Godot;
+
+///
+/// Ai 寻找弹药
+///
+public class AiFindAmmoState : StateBase
+{
+ public AiFindAmmoState() : base(AiStateEnum.AiFindAmmo)
+ {
+ }
+
+ public override void Enter(AiStateEnum prev, params object[] args)
+ {
+ GD.Print("寻找武器");
+ }
+
+ public override void PhysicsProcess(float delta)
+ {
+
+ }
+
+ public override void DebugDraw()
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/room/RoomManager.cs b/DungeonShooting_Godot/src/game/room/RoomManager.cs
index 17d5396..c08cbcd 100644
--- a/DungeonShooting_Godot/src/game/room/RoomManager.cs
+++ b/DungeonShooting_Godot/src/game/room/RoomManager.cs
@@ -95,23 +95,23 @@
// enemyTemp.PickUpWeapon(WeaponManager.GetGun("1001"));
// }
- var enemy2 = new Enemy();
- enemy2.Name = "Enemy2";
- enemy2.PutDown(new Vector2(540, 100));
- enemy2.PickUpWeapon(WeaponManager.GetGun("1002"));
- enemy2.PickUpWeapon(WeaponManager.GetGun("1004"));
- enemy2.PickUpWeapon(WeaponManager.GetGun("1003"));
- //
- var enemy3 = new Enemy();
- enemy3.Name = "Enemy3";
- enemy3.PutDown(new Vector2(540, 300));
- enemy3.PickUpWeapon(WeaponManager.GetGun("1003"));
- enemy3.PickUpWeapon(WeaponManager.GetGun("1002"));
+ // var enemy2 = new Enemy();
+ // enemy2.Name = "Enemy2";
+ // enemy2.PutDown(new Vector2(540, 100));
+ // enemy2.PickUpWeapon(WeaponManager.GetGun("1002"));
+ // enemy2.PickUpWeapon(WeaponManager.GetGun("1004"));
+ // enemy2.PickUpWeapon(WeaponManager.GetGun("1003"));
+ // //
+ // var enemy3 = new Enemy();
+ // enemy3.Name = "Enemy3";
+ // enemy3.PutDown(new Vector2(540, 300));
+ // enemy3.PickUpWeapon(WeaponManager.GetGun("1003"));
+ // enemy3.PickUpWeapon(WeaponManager.GetGun("1002"));
- WeaponManager.GetGun("1001").PutDown(new Vector2(80, 100));
- WeaponManager.GetGun("1001").PutDown(new Vector2(80, 80));
- WeaponManager.GetGun("1002").PutDown(new Vector2(80, 120));
- WeaponManager.GetGun("1003").PutDown(new Vector2(120, 80));
+ // WeaponManager.GetGun("1001").PutDown(new Vector2(80, 100));
+ // WeaponManager.GetGun("1001").PutDown(new Vector2(80, 80));
+ // WeaponManager.GetGun("1002").PutDown(new Vector2(80, 120));
+ // WeaponManager.GetGun("1003").PutDown(new Vector2(120, 80));
WeaponManager.GetGun("1003").PutDown(new Vector2(180, 80));
WeaponManager.GetGun("1003").PutDown(new Vector2(180, 180));