diff --git a/DungeonShooting_Godot/prefab/role/Player.tscn b/DungeonShooting_Godot/prefab/role/Player.tscn index abab257..b67a1c6 100644 --- a/DungeonShooting_Godot/prefab/role/Player.tscn +++ b/DungeonShooting_Godot/prefab/role/Player.tscn @@ -2,7 +2,7 @@ [ext_resource path="res://prefab/role/Role.tscn" type="PackedScene" id=1] [ext_resource path="res://src/role/Player.cs" type="Script" id=2] -[ext_resource path="res://prefab/weapon/Gun.tscn" type="PackedScene" id=4] +[ext_resource path="res://prefab/weapon/Weapon.tscn" type="PackedScene" id=4] [node name="Player" instance=ExtResource( 1 )] collision_layer = 8 diff --git a/DungeonShooting_Godot/prefab/role/Role.tscn b/DungeonShooting_Godot/prefab/role/Role.tscn index 0f4dd8e..a3c93fe 100644 --- a/DungeonShooting_Godot/prefab/role/Role.tscn +++ b/DungeonShooting_Godot/prefab/role/Role.tscn @@ -88,7 +88,6 @@ position = Vector2( 0, -12 ) frames = SubResource( 6 ) animation = "idle" -frame = 1 playing = true [node name="Collision" type="CollisionShape2D" parent="."] diff --git a/DungeonShooting_Godot/prefab/ui/bar/ReloadBar.tscn b/DungeonShooting_Godot/prefab/ui/bar/ReloadBar.tscn index d34b274..b9af2ad 100644 --- a/DungeonShooting_Godot/prefab/ui/bar/ReloadBar.tscn +++ b/DungeonShooting_Godot/prefab/ui/bar/ReloadBar.tscn @@ -4,12 +4,12 @@ [ext_resource path="res://resource/sprite/ui/reloadBarBlock.png" type="Texture" id=2] [ext_resource path="res://resource/sprite/ui/reloadBar.png" type="Texture" id=3] -[node name="ReloadBar" type="Sprite"] -visible = false -position = Vector2( 0, -26 ) -texture = ExtResource( 3 ) +[node name="ReloadBar" type="Node2D"] script = ExtResource( 1 ) -[node name="ReloadBarBlock" type="Sprite" parent="."] -position = Vector2( -13, 0 ) +[node name="Slot" type="Sprite" parent="."] +position = Vector2( 0, -24 ) +texture = ExtResource( 3 ) + +[node name="Block" type="Sprite" parent="Slot"] texture = ExtResource( 2 ) diff --git a/DungeonShooting_Godot/prefab/weapon/Gun.tscn b/DungeonShooting_Godot/prefab/weapon/Gun.tscn deleted file mode 100644 index 2c54084..0000000 --- a/DungeonShooting_Godot/prefab/weapon/Gun.tscn +++ /dev/null @@ -1,103 +0,0 @@ -[gd_scene load_steps=8 format=2] - -[ext_resource path="res://src/weapon/gun/OrdinaryGun.cs" type="Script" id=1] -[ext_resource path="res://resource/materlal/Shadow.gdshader" type="Shader" id=2] - -[sub_resource type="ShaderMaterial" id=9] -resource_local_to_scene = true -shader = ExtResource( 2 ) -shader_param/shadowColor = Color( 1, 1, 1, 1 ) -shader_param/schedule = 0.0 - -[sub_resource type="StreamTexture" id=8] -load_path = "res://.import/gun1.png-f7bc3e27b4b477d47c7353ffb91687ea.stex" - -[sub_resource type="Animation" id=3] -resource_name = "Floodlight" -length = 3.0 -loop = true -step = 0.5 -tracks/0/type = "value" -tracks/0/path = NodePath("GunSprite:material:shader_param/shadowColor") -tracks/0/interp = 1 -tracks/0/loop_wrap = true -tracks/0/imported = false -tracks/0/enabled = true -tracks/0/keys = { -"times": PoolRealArray( 0 ), -"transitions": PoolRealArray( 1 ), -"update": 0, -"values": [ Color( 1, 1, 1, 1 ) ] -} -tracks/1/type = "value" -tracks/1/path = NodePath("GunSprite:material:shader_param/schedule") -tracks/1/interp = 1 -tracks/1/loop_wrap = true -tracks/1/imported = false -tracks/1/enabled = true -tracks/1/keys = { -"times": PoolRealArray( 0, 1.9, 2.4, 2.5, 3 ), -"transitions": PoolRealArray( 1, 1, 1, 1, 1 ), -"update": 0, -"values": [ 0.0, 0.0, 1.0, 1.0, 0.0 ] -} - -[sub_resource type="Animation" id=4] -length = 0.001 -tracks/0/type = "value" -tracks/0/path = NodePath("GunSprite:material:shader_param/shadowColor") -tracks/0/interp = 1 -tracks/0/loop_wrap = true -tracks/0/imported = false -tracks/0/enabled = true -tracks/0/keys = { -"times": PoolRealArray( 0 ), -"transitions": PoolRealArray( 1 ), -"update": 0, -"values": [ Color( 1, 1, 1, 1 ) ] -} -tracks/1/type = "value" -tracks/1/path = NodePath("GunSprite:material:shader_param/schedule") -tracks/1/interp = 1 -tracks/1/loop_wrap = true -tracks/1/imported = false -tracks/1/enabled = true -tracks/1/keys = { -"times": PoolRealArray( 0 ), -"transitions": PoolRealArray( 1 ), -"update": 0, -"values": [ 0.0 ] -} - -[sub_resource type="RectangleShape2D" id=1] -extents = Vector2( 7.8, 3.5 ) - -[node name="Gun" type="Area2D"] -collision_layer = 4 -collision_mask = 0 -script = ExtResource( 1 ) - -[node name="GunSprite" type="Sprite" parent="."] -material = SubResource( 9 ) -position = Vector2( 0.4, -2.6 ) -scale = Vector2( 0.8, 0.8 ) -texture = SubResource( 8 ) - -[node name="AnimationPlayer" type="AnimationPlayer" parent="."] -autoplay = "Floodlight" -playback_process_mode = 0 -anims/Floodlight = SubResource( 3 ) -anims/RESET = SubResource( 4 ) - -[node name="OriginPoint" type="Position2D" parent="."] -position = Vector2( -3.60001, -1.1 ) - -[node name="ShellPoint" type="Position2D" parent="."] -position = Vector2( -2.60001, -2.60001 ) - -[node name="FirePoint" type="Position2D" parent="."] -position = Vector2( 7.39999, -1.1 ) - -[node name="Collision" type="CollisionShape2D" parent="."] -position = Vector2( 0.59999, 0.199997 ) -shape = SubResource( 1 ) diff --git a/DungeonShooting_Godot/prefab/weapon/Weapon.tscn b/DungeonShooting_Godot/prefab/weapon/Weapon.tscn new file mode 100644 index 0000000..bb56e3c --- /dev/null +++ b/DungeonShooting_Godot/prefab/weapon/Weapon.tscn @@ -0,0 +1,103 @@ +[gd_scene load_steps=8 format=2] + +[ext_resource path="res://src/weapon/gun/OrdinaryGun.cs" type="Script" id=1] +[ext_resource path="res://resource/materlal/Shadow.gdshader" type="Shader" id=2] + +[sub_resource type="ShaderMaterial" id=9] +resource_local_to_scene = true +shader = ExtResource( 2 ) +shader_param/shadowColor = Color( 1, 1, 1, 1 ) +shader_param/schedule = 0.0 + +[sub_resource type="StreamTexture" id=8] +load_path = "res://.import/gun1.png-f7bc3e27b4b477d47c7353ffb91687ea.stex" + +[sub_resource type="Animation" id=3] +resource_name = "Floodlight" +length = 3.0 +loop = true +step = 0.5 +tracks/0/type = "value" +tracks/0/path = NodePath("WeaponSprite:material:shader_param/shadowColor") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0 ), +"transitions": PoolRealArray( 1 ), +"update": 0, +"values": [ Color( 1, 1, 1, 1 ) ] +} +tracks/1/type = "value" +tracks/1/path = NodePath("WeaponSprite:material:shader_param/schedule") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/keys = { +"times": PoolRealArray( 0, 1.9, 2.4, 2.5, 3 ), +"transitions": PoolRealArray( 1, 1, 1, 1, 1 ), +"update": 0, +"values": [ 0.0, 0.0, 1.0, 1.0, 0.0 ] +} + +[sub_resource type="Animation" id=4] +length = 0.001 +tracks/0/type = "value" +tracks/0/path = NodePath("WeaponSprite:material:shader_param/shadowColor") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0 ), +"transitions": PoolRealArray( 1 ), +"update": 0, +"values": [ Color( 1, 1, 1, 1 ) ] +} +tracks/1/type = "value" +tracks/1/path = NodePath("WeaponSprite:material:shader_param/schedule") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/keys = { +"times": PoolRealArray( 0 ), +"transitions": PoolRealArray( 1 ), +"update": 0, +"values": [ 0.0 ] +} + +[sub_resource type="RectangleShape2D" id=1] +extents = Vector2( 7.8, 3.5 ) + +[node name="Weapon" type="Area2D"] +collision_layer = 4 +collision_mask = 0 +script = ExtResource( 1 ) + +[node name="WeaponSprite" type="Sprite" parent="."] +material = SubResource( 9 ) +position = Vector2( 0.4, -2.6 ) +scale = Vector2( 0.8, 0.8 ) +texture = SubResource( 8 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +autoplay = "Floodlight" +playback_process_mode = 0 +anims/Floodlight = SubResource( 3 ) +anims/RESET = SubResource( 4 ) + +[node name="OriginPoint" type="Position2D" parent="."] +position = Vector2( -3.60001, -1.1 ) + +[node name="ShellPoint" type="Position2D" parent="."] +position = Vector2( -2.60001, -2.60001 ) + +[node name="FirePoint" type="Position2D" parent="."] +position = Vector2( 7.39999, -1.1 ) + +[node name="Collision" type="CollisionShape2D" parent="."] +position = Vector2( 0.59999, 0.199997 ) +shape = SubResource( 1 ) diff --git a/DungeonShooting_Godot/resource/sprite/ui/reloadBar.png b/DungeonShooting_Godot/resource/sprite/ui/reloadBar.png index b139125..0803903 100644 --- a/DungeonShooting_Godot/resource/sprite/ui/reloadBar.png +++ b/DungeonShooting_Godot/resource/sprite/ui/reloadBar.png Binary files differ diff --git a/DungeonShooting_Godot/resource/sprite/ui/reloadBarBlock.png b/DungeonShooting_Godot/resource/sprite/ui/reloadBarBlock.png index 9062297..a142dea 100644 --- a/DungeonShooting_Godot/resource/sprite/ui/reloadBarBlock.png +++ b/DungeonShooting_Godot/resource/sprite/ui/reloadBarBlock.png Binary files differ diff --git a/DungeonShooting_Godot/src/common/NodeExtend.cs b/DungeonShooting_Godot/src/common/NodeExtend.cs index 7ad30d8..f408367 100644 --- a/DungeonShooting_Godot/src/common/NodeExtend.cs +++ b/DungeonShooting_Godot/src/common/NodeExtend.cs @@ -56,12 +56,12 @@ return false; } - public static ThrowGun StartThrowGun(this Gun gun, Role master) + public static ThrowWeapon StartThrowWeapon(this Weapon weapon, Role master) { if (master.Face == FaceDirection.Left) { - gun.Scale *= new Vector2(1, -1); - gun.RotationDegrees = 180; + weapon.Scale *= new Vector2(1, -1); + weapon.RotationDegrees = 180; } var startPos = master.GlobalPosition;// + new Vector2(0, 0); var startHeight = 6; @@ -69,7 +69,7 @@ var xf = 30; var yf = MathUtils.RandRangeInt(60, 120); var rotate = MathUtils.RandRangeInt(-180, 180); - gun.Position = Vector2.Zero; - return gun.StartThrow(new Vector2(20, 20), startPos, startHeight, direction, xf, yf, rotate, gun.GunSprite); + weapon.Position = Vector2.Zero; + return weapon.StartThrow(new Vector2(20, 20), startPos, startHeight, direction, xf, yf, rotate, weapon.WeaponSprite); } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/effect/Cursor.cs b/DungeonShooting_Godot/src/effect/Cursor.cs index 06f6894..a2d6dd4 100644 --- a/DungeonShooting_Godot/src/effect/Cursor.cs +++ b/DungeonShooting_Godot/src/effect/Cursor.cs @@ -21,7 +21,7 @@ public override void _Process(float delta) { - var targetGun = RoomManager.Current?.Player?.Holster.ActiveGun; + var targetGun = RoomManager.Current?.Player?.Holster.ActiveWeapon; if (targetGun != null) { SetScope(targetGun.CurrScatteringRange, targetGun); @@ -36,7 +36,7 @@ /// /// 设置光标半径范围 /// - private void SetScope(float scope, Gun targetGun) + private void SetScope(float scope, Weapon targetGun) { if (targetGun != null) { diff --git a/DungeonShooting_Godot/src/manager/ResourceManager.cs b/DungeonShooting_Godot/src/manager/ResourceManager.cs index 83f9688..4eaacac 100644 --- a/DungeonShooting_Godot/src/manager/ResourceManager.cs +++ b/DungeonShooting_Godot/src/manager/ResourceManager.cs @@ -64,12 +64,12 @@ /// 加载并实例化一个武器对象 /// /// 资源路径 - public static Gun LoadGunAndInstance(string path) + public static Weapon LoadWeaponAndInstance(string path) { var pack = Load(path); if (pack != null) { - return pack.Instance(); + return pack.Instance(); } return null; } diff --git a/DungeonShooting_Godot/src/package/Holster.cs b/DungeonShooting_Godot/src/package/Holster.cs index 3ce60be..6de869c 100644 --- a/DungeonShooting_Godot/src/package/Holster.cs +++ b/DungeonShooting_Godot/src/package/Holster.cs @@ -1,14 +1,14 @@ using Godot; /// -/// 角色身上的枪套, 存储角色携带的武器 +/// 角色身上的武器袋, 存储角色携带的武器 /// public class Holster { /// /// 插槽类 /// - public class GunSlot + public class WeaponSlot { /// /// 是否启用 @@ -17,11 +17,11 @@ /// /// 当前插槽存放的武器类型 /// - public GunWeightType Type = GunWeightType.MainWeapon; + public WeaponWeightType Type = WeaponWeightType.MainWeapon; /// /// 插槽存放的武器 /// - public Gun Gun; + public Weapon Weapon; } /// @@ -32,58 +32,58 @@ /// /// 当前使用的武器对象 /// - public Gun ActiveGun { get; private set; } + public Weapon ActiveWeapon { get; private set; } /// /// 当前使用的武器的索引 /// public int ActiveIndex { get; private set; } = 0; - public GunSlot[] SlotList { get; } = new GunSlot[4]; + public WeaponSlot[] SlotList { get; } = new WeaponSlot[4]; public Holster(Role master) { Master = master; - //创建枪的插槽, 默认前两个都是启用的 - GunSlot slot1 = new GunSlot(); + //创建武器的插槽, 默认前两个都是启用的 + WeaponSlot slot1 = new WeaponSlot(); slot1.Enable = true; SlotList[0] = slot1; - GunSlot slot2 = new GunSlot(); + WeaponSlot slot2 = new WeaponSlot(); slot2.Enable = true; - slot2.Type = GunWeightType.DeputyWeapon; + slot2.Type = WeaponWeightType.DeputyWeapon; SlotList[1] = slot2; - GunSlot slot3 = new GunSlot(); + WeaponSlot slot3 = new WeaponSlot(); SlotList[2] = slot3; - GunSlot slot4 = new GunSlot(); - slot4.Type = GunWeightType.DeputyWeapon; + WeaponSlot slot4 = new WeaponSlot(); + slot4.Type = WeaponWeightType.DeputyWeapon; SlotList[3] = slot4; } /// /// 根据索引获取武器 /// - public Gun GetGun(int index) { + public Weapon GetWeapon(int index) { if (index >= SlotList.Length) { return null; } - return SlotList[index].Gun; + return SlotList[index].Weapon; } /// - /// 根据武器id查找枪套中该武器所在的位置, 如果没有, 则返回 -1 + /// 根据武器id查找武器袋中该武器所在的位置, 如果没有, 则返回 -1 /// /// 武器id - public int FindGun(string id) + public int FindWeapon(string id) { for (int i = 0; i < SlotList.Length; i++) { var item = SlotList[i]; - if (item.Gun != null && item.Gun.Attribute.Id == id) + if (item.Weapon != null && item.Weapon.Attribute.Id == id) { return i; } @@ -94,13 +94,13 @@ /// /// 返回是否能放入武器 /// - /// 武器对象 - public bool CanPickupGun(Gun gun) + /// 武器对象 + public bool CanPickupWeapon(Weapon weapon) { for (int i = 0; i < SlotList.Length; i++) { var item = SlotList[i]; - if (item.Enable && gun.Attribute.WeightType == item.Type && item.Gun == null) + if (item.Enable && weapon.Attribute.WeightType == item.Type && item.Weapon == null) { return true; } @@ -109,20 +109,20 @@ } /// - /// 拾起武器, 存入枪套中, 返回存放在枪套的位置, 如果容不下这把武器, 则会返回 -1 + /// 拾起武器, 存入武器袋中, 返回存放在武器袋的位置, 如果容不下这把武器, 则会返回 -1 /// - /// 武器对象 - public int PickupGun(Gun gun) + /// 武器对象 + public int PickupWeapon(Weapon weapon) { for (int i = 0; i < SlotList.Length; i++) { var item = SlotList[i]; - if (item.Enable && gun.Attribute.WeightType == item.Type && item.Gun == null) + if (item.Enable && weapon.Attribute.WeightType == item.Type && item.Weapon == null) { - gun.Pickup(); - item.Gun = gun; + weapon.Pickup(); + item.Weapon = weapon; ExchangeByIndex(i); - gun._PickUpGun(Master); + weapon._PickUpWeapon(Master); return i; } } @@ -132,21 +132,21 @@ /// /// 移除指定位置的武器, 并返回这个武器对象, 如果移除正在使用的这把武器, 则会自动切换到上一把武器 /// - /// 所在枪套的位置索引 - public Gun RmoveGun(int index) + /// 所在武器袋的位置索引 + public Weapon RmoveWeapon(int index) { if (index < 0 || index >= SlotList.Length) { return null; } var slot = SlotList[index]; - if (slot.Gun == null) + if (slot.Weapon == null) { return null; } - var gun = slot.Gun; - gun.GetParent().RemoveChild(gun); - slot.Gun = null; + var weapon = slot.Weapon; + weapon.GetParent().RemoveChild(weapon); + slot.Weapon = null; //如果是当前手持的武器, 就需要调用切换武器操作 if (index == ActiveIndex) @@ -155,11 +155,11 @@ if (ExchangePrev() == index) { ActiveIndex = 0; - ActiveGun = null; + ActiveWeapon = null; } } - gun._ThrowOutGun(); - return gun; + weapon._ThrowOutWeapon(); + return weapon; } /// @@ -208,65 +208,65 @@ /// public bool ExchangeByIndex(int index) { - if (index == ActiveIndex && ActiveGun != null) return true; + if (index == ActiveIndex && ActiveWeapon != null) return true; if (index < 0 || index > SlotList.Length) return false; var slot = SlotList[index]; - if (slot == null || slot.Gun == null) return false; + if (slot == null || slot.Weapon == null) return false; //将上一把武器放到背后 - if (ActiveGun != null) + if (ActiveWeapon != null) { - var tempParent = ActiveGun.GetParentOrNull(); + var tempParent = ActiveWeapon.GetParentOrNull(); if (tempParent != null) { - tempParent.RemoveChild(ActiveGun); - Master.BackMountPoint.AddChild(ActiveGun); + tempParent.RemoveChild(ActiveWeapon); + Master.BackMountPoint.AddChild(ActiveWeapon); if (ActiveIndex == 0) { - ActiveGun.Position = new Vector2(0, 5); - ActiveGun.RotationDegrees = 50; - ActiveGun.Scale = new Vector2(-1, 1); + ActiveWeapon.Position = new Vector2(0, 5); + ActiveWeapon.RotationDegrees = 50; + ActiveWeapon.Scale = new Vector2(-1, 1); } else if (ActiveIndex == 1) { - ActiveGun.Position = new Vector2(0, 0); - ActiveGun.RotationDegrees = 120; - ActiveGun.Scale = new Vector2(1, -1); + ActiveWeapon.Position = new Vector2(0, 0); + ActiveWeapon.RotationDegrees = 120; + ActiveWeapon.Scale = new Vector2(1, -1); } else if (ActiveIndex == 2) { - ActiveGun.Position = new Vector2(0, 5); - ActiveGun.RotationDegrees = 310; - ActiveGun.Scale = new Vector2(1, 1); + ActiveWeapon.Position = new Vector2(0, 5); + ActiveWeapon.RotationDegrees = 310; + ActiveWeapon.Scale = new Vector2(1, 1); } else if (ActiveIndex == 3) { - ActiveGun.Position = new Vector2(0, 0); - ActiveGun.RotationDegrees = 60; - ActiveGun.Scale = new Vector2(1, 1); + ActiveWeapon.Position = new Vector2(0, 0); + ActiveWeapon.RotationDegrees = 60; + ActiveWeapon.Scale = new Vector2(1, 1); } - ActiveGun._Conceal(); + ActiveWeapon._Conceal(); } } //更改父节点 - var parent = slot.Gun.GetParentOrNull(); + var parent = slot.Weapon.GetParentOrNull(); if (parent == null) { - Master.MountPoint.AddChild(slot.Gun); + Master.MountPoint.AddChild(slot.Weapon); } else if (parent != Master.MountPoint) { - parent.RemoveChild(slot.Gun); - Master.MountPoint.AddChild(slot.Gun); + parent.RemoveChild(slot.Weapon); + Master.MountPoint.AddChild(slot.Weapon); } - slot.Gun.Position = Vector2.Zero; - slot.Gun.Scale = Vector2.One; - slot.Gun.RotationDegrees = 0; - ActiveGun = slot.Gun; + slot.Weapon.Position = Vector2.Zero; + slot.Weapon.Scale = Vector2.One; + slot.Weapon.RotationDegrees = 0; + ActiveWeapon = slot.Weapon; ActiveIndex = index; - ActiveGun._Active(); + ActiveWeapon._Active(); return true; } } diff --git a/DungeonShooting_Godot/src/role/Player.cs b/DungeonShooting_Godot/src/role/Player.cs index fdb4bd7..8735cde 100644 --- a/DungeonShooting_Godot/src/role/Player.cs +++ b/DungeonShooting_Godot/src/role/Player.cs @@ -60,10 +60,10 @@ base._Ready(); Holster.SlotList[2].Enable = true; Holster.SlotList[3].Enable = true; - PickUpGun(GunManager.GetGun1()); //0 - PickUpGun(GunManager.GetGun2()); //1 - PickUpGun(GunManager.GetGun3()); //2 - PickUpGun(GunManager.GetGun4()); //3 + PickUpWeapon(WeaponManager.GetGun1()); //0 + PickUpWeapon(WeaponManager.GetGun2()); //1 + PickUpWeapon(WeaponManager.GetGun3()); //2 + PickUpWeapon(WeaponManager.GetGun4()); //3 RefreshGunTexture(); MaxHp = 50; @@ -96,13 +96,13 @@ } else if (Input.IsActionJustPressed("throw")) //扔掉武器 { - TriggerThrowGun(); + TriggerThrowWeapon(); RefreshGunTexture(); } else if (Input.IsActionJustPressed("interactive")) //互动物体 { var item = TriggerTnteractive(); - if (item is Gun) + if (item is Weapon) { RefreshGunTexture(); } @@ -118,9 +118,9 @@ //刷新显示的弹药剩余量 RefreshGunAmmunition(); - if (Holster.ActiveGun != null && Holster.ActiveGun.Reloading) + if (Holster.ActiveWeapon != null && Holster.ActiveWeapon.Reloading) { - RoomUI.Current.ReloadBar.ShowBar(GlobalPosition); + RoomUI.Current.ReloadBar.ShowBar(GlobalPosition, 1 - Holster.ActiveWeapon.ReloadProgress); } else { @@ -155,7 +155,7 @@ } else { - if (InteractiveItem is Gun gun) + if (InteractiveItem is Weapon gun) { //显示互动提示 RoomUI.Current.InteractiveTipBar.ShowBar(result.Target.GetItemPosition(), result.ShowIcon, result.Message); @@ -178,7 +178,7 @@ /// private void RefreshGunTexture() { - var gun = Holster.ActiveGun; + var gun = Holster.ActiveWeapon; if (gun != null) { RoomUI.Current.SetGunTexture(gun.Attribute.Sprite); @@ -194,7 +194,7 @@ /// private void RefreshGunAmmunition() { - var gun = Holster.ActiveGun; + var gun = Holster.ActiveWeapon; if (gun != null) { RoomUI.Current.SetAmmunition(gun.CurrAmmo, gun.ResidueAmmo); diff --git a/DungeonShooting_Godot/src/role/Role.cs b/DungeonShooting_Godot/src/role/Role.cs index 1f37b51..a8e715a 100644 --- a/DungeonShooting_Godot/src/role/Role.cs +++ b/DungeonShooting_Godot/src/role/Role.cs @@ -176,13 +176,13 @@ /// /// 拾起一个武器, 并且切换到这个武器 /// - /// 武器对象 - public void PickUpGun(Gun gun) + /// 武器对象 + public void PickUpWeapon(Weapon weapon) { - if (Holster.PickupGun(gun) != -1) + if (Holster.PickupWeapon(weapon) != -1) { //从可互动队列中移除 - InteractiveItemList.Remove(gun); + InteractiveItemList.Remove(weapon); } } @@ -205,13 +205,13 @@ /// /// 扔掉当前使用的武器, 切换到上一个武器 /// - public void TriggerThrowGun() + public void TriggerThrowWeapon() { - var gun = Holster.RmoveGun(Holster.ActiveIndex); + var weapon = Holster.RmoveWeapon(Holster.ActiveIndex); //播放抛出效果 - if (gun != null) + if (weapon != null) { - gun.StartThrowGun(this); + weapon.StartThrowWeapon(this); } } @@ -242,9 +242,9 @@ /// public void TriggerReload() { - if (Holster.ActiveGun != null) + if (Holster.ActiveWeapon != null) { - Holster.ActiveGun._Reload(); + Holster.ActiveWeapon._Reload(); } } @@ -253,9 +253,9 @@ /// public void TriggerAttack() { - if (Holster.ActiveGun != null) + if (Holster.ActiveWeapon != null) { - Holster.ActiveGun.Trigger(); + Holster.ActiveWeapon.Trigger(); } } diff --git a/DungeonShooting_Godot/src/room/RoomManager.cs b/DungeonShooting_Godot/src/room/RoomManager.cs index 2697778..77e4f24 100644 --- a/DungeonShooting_Godot/src/room/RoomManager.cs +++ b/DungeonShooting_Godot/src/room/RoomManager.cs @@ -43,21 +43,21 @@ { //播放bgm SoundManager.PlayeMusic("intro.ogg", this, -17f); - var gun1 = GunManager.GetGun1(); + var gun1 = WeaponManager.GetGun1(); gun1.Position = new Vector2(80, 80); - gun1.PutDown(gun1.GunSprite); - var gun2 = GunManager.GetGun2(); + gun1.PutDown(gun1.WeaponSprite); + var gun2 = WeaponManager.GetGun2(); gun2.Position = new Vector2(80, 120); - gun2.PutDown(gun2.GunSprite); - var gun3 = GunManager.GetGun3(); + gun2.PutDown(gun2.WeaponSprite); + var gun3 = WeaponManager.GetGun3(); gun3.Position = new Vector2(120, 80); - gun3.PutDown(gun3.GunSprite); - var gun4 = GunManager.GetGun4(); + gun3.PutDown(gun3.WeaponSprite); + var gun4 = WeaponManager.GetGun4(); gun4.Position = new Vector2(120, 120); - gun4.PutDown(gun4.GunSprite); - var gun5 = GunManager.GetGun5(); + gun4.PutDown(gun4.WeaponSprite); + var gun5 = WeaponManager.GetGun5(); gun5.Position = new Vector2(160, 160); - gun5.PutDown(gun5.GunSprite); + gun5.PutDown(gun5.WeaponSprite); } public override void _Process(float delta) diff --git a/DungeonShooting_Godot/src/ui/ReloadBar.cs b/DungeonShooting_Godot/src/ui/ReloadBar.cs index f6b64ad..f496360 100644 --- a/DungeonShooting_Godot/src/ui/ReloadBar.cs +++ b/DungeonShooting_Godot/src/ui/ReloadBar.cs @@ -1,23 +1,43 @@ using Godot; -public class ReloadBar : Sprite +/// +/// 换弹进度组件 +/// +public class ReloadBar : Node2D { + private Sprite slot; private Sprite block; + private int width; + private float startX; + public override void _Ready() { - block = GetNode("ReloadBarBlock"); + slot = GetNode("Slot"); + block = GetNode("Slot/Block"); + width = slot.Texture.GetWidth(); + startX = -(width - 3) / 2; } + /// + /// 隐藏换弹进度组件 + /// public void HideBar() { Visible = false; } - public void ShowBar(Vector2 position) + /// + /// 显示换弹进度组件 + /// + /// 坐标 + /// 进度, 0 - 1 + public void ShowBar(Vector2 position, float progress) { Visible = true; GlobalPosition = position; + progress = Mathf.Clamp(progress, 0, 1); + block.Position = new Vector2(startX + (width - 3) * progress, 0); } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/weapon/RegisterWeapon.cs b/DungeonShooting_Godot/src/weapon/RegisterWeapon.cs new file mode 100644 index 0000000..8399b7e --- /dev/null +++ b/DungeonShooting_Godot/src/weapon/RegisterWeapon.cs @@ -0,0 +1,10 @@ +using System; + +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] +public class RegisterWeapon : Attribute +{ + public RegisterWeapon(string id) + { + + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/weapon/ThrowGun.cs b/DungeonShooting_Godot/src/weapon/ThrowGun.cs new file mode 100644 index 0000000..d3c652a --- /dev/null +++ b/DungeonShooting_Godot/src/weapon/ThrowGun.cs @@ -0,0 +1,44 @@ +using Godot; + +public class ThrowWeapon : ThrowNode +{ + + private bool fristOver = true; + + public override void _Ready() + { + base._Ready(); + ZIndex = 2; + } + + public override void StartThrow(Vector2 size, Vector2 start, float startHeight, float direction, float xSpeed, float ySpeed, float rotate, Node2D mount) + { + base.StartThrow(size, start, startHeight, direction, xSpeed, ySpeed, rotate, mount); + fristOver = true; + } + + protected override void OnOver() + { + if (fristOver) + { + fristOver = false; + if (Mount is Weapon gun) + { + gun._FallToGround(); + } + } + //如果落地高度不够低, 再抛一次 + if (StartYSpeed > 1) + { + StartThrow(Size, GlobalPosition, 0, Direction, XSpeed * 0.8f, StartYSpeed * 0.5f, RotateSpeed * 0.5f, null); + } + else //结束 + { + base.OnOver(); + } + } + protected override void OnMaxHeight(float height) + { + ZIndex = 0; + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/weapon/Weapon.cs b/DungeonShooting_Godot/src/weapon/Weapon.cs new file mode 100644 index 0000000..31ff532 --- /dev/null +++ b/DungeonShooting_Godot/src/weapon/Weapon.cs @@ -0,0 +1,696 @@ +using Godot; +using System; + +/// +/// 武器的基类 +/// +public abstract class Weapon : Area2D, IProp +{ + /// + /// 开火回调事件 + /// + public event Action FireEvent; + + /// + /// 属性数据 + /// + public WeaponAttribute Attribute + { + get + { + if (_attribute == null) + { + throw new Exception("请先调用Init来初始化武器的属性"); + } + return _attribute; + } + private set => _attribute = value; + } + private WeaponAttribute _attribute; + + /// + /// 武器的图片 + /// + public Sprite WeaponSprite { get; private set; } + + /// + /// 动画播放器 + /// + /// + public AnimationPlayer AnimationPlayer { get; private set; } + + /// + /// 武器攻击的目标阵营 + /// + public CampEnum TargetCamp { get; set; } + + /// + /// 该武器的拥有者 + /// + public Role Master { get; private set; } + + /// + /// 当前弹夹弹药剩余量 + /// + public int CurrAmmo { get; private set; } + /// + /// 剩余弹药量 + /// + public int ResidueAmmo { get; private set; } + + /// + /// 武器管的开火点 + /// + public Position2D FirePoint { get; private set; } + /// + /// 武器管的原点 + /// + public Position2D OriginPoint { get; private set; } + /// + /// 弹壳抛出的点 + /// + public Position2D ShellPoint { get; private set; } + /// + /// 碰撞器节点 + /// + /// + public CollisionShape2D CollisionShape2D { get; private set; } + /// + /// 武器的当前散射半径 + /// + public float CurrScatteringRange { get; private set; } = 0; + /// + /// 是否在换弹中 + /// + /// + public bool Reloading { get; private set; } = false; + /// + /// 换弹计时器 + /// + public float ReloadTimer { get; private set; } = 0; + /// + /// 换弹进度 (0 - 1) + /// + public float ReloadProgress => ReloadTimer / Attribute.ReloadTime; + + //是否按下 + private bool triggerFlag = false; + //扳机计时器 + private float triggerTimer = 0; + //开火前延时时间 + private float delayedTime = 0; + //开火间隙时间 + private float fireInterval = 0; + //开火武器口角度 + private float fireAngle = 0; + //攻击冷却计时 + private float attackTimer = 0; + //攻击状态 + private bool attackFlag = false; + //按下的时间 + private float downTimer = 0; + //松开的时间 + private float upTimer = 0; + //连发次数 + private float continuousCount = 0; + //连发状态记录 + private bool continuousShootFlag = false; + + /// + /// 初始化时调用 + /// + protected abstract void Init(); + + /// + /// 单次开火时调用的函数 + /// + protected abstract void OnFire(); + + /// + /// 换弹时调用 + /// + protected abstract void OnReload(); + + /// + /// 发射子弹时调用的函数, 每发射一枚子弹调用一次, + /// 如果做霰弹武器效果, 一次开火发射5枚子弹, 则该函数调用5次 + /// + protected abstract void OnShootBullet(); + + /// + /// 当武器被拾起时调用 + /// + /// 拾起该武器的角色 + protected abstract void OnPickUp(Role master); + + /// + /// 当武器被扔掉时调用 + /// + protected abstract void OnThrowOut(); + + /// + /// 当武器被激活时调用, 也就是使用当武器是调用 + /// + protected abstract void OnActive(); + + /// + /// 当武器被收起时调用 + /// + protected abstract void OnConceal(); + + public override void _Process(float delta) + { + if (Master == null) //这把武器被扔在地上 + { + Reloading = false; + triggerTimer = triggerTimer > 0 ? triggerTimer - delta : 0; + triggerFlag = false; + attackFlag = false; + attackTimer = attackTimer > 0 ? attackTimer - delta : 0; + CurrScatteringRange = Mathf.Max(CurrScatteringRange - Attribute.ScatteringRangeBackSpeed * delta, Attribute.StartScatteringRange); + continuousCount = 0; + delayedTime = 0; + } + else if (Master.Holster.ActiveWeapon != this) //当前武器没有被使用 + { + Reloading = false; + triggerTimer = triggerTimer > 0 ? triggerTimer - delta : 0; + triggerFlag = false; + attackFlag = false; + attackTimer = attackTimer > 0 ? attackTimer - delta : 0; + CurrScatteringRange = Mathf.Max(CurrScatteringRange - Attribute.ScatteringRangeBackSpeed * delta, Attribute.StartScatteringRange); + continuousCount = 0; + delayedTime = 0; + } + else //正在使用中 + { + + //换弹 + if (Reloading) + { + ReloadTimer -= delta; + if (ReloadTimer <= 0) + { + ReloadTimer = 0; + ReloadSuccess(); + } + } + + if (triggerFlag) + { + if (upTimer > 0) //第一帧按下扳机 + { + upTimer = 0; + DownTrigger(); + } + downTimer += delta; + } + else + { + if (downTimer > 0) //第一帧松开扳机 + { + downTimer = 0; + UpTriggern(); + } + upTimer += delta; + } + + // 攻击的计时器 + if (attackTimer > 0) + { + attackTimer -= delta; + if (attackTimer < 0) + { + delayedTime += attackTimer; + attackTimer = 0; + } + } + else if (delayedTime > 0) //攻击延时 + { + delayedTime -= delta; + if (attackTimer < 0) + { + delayedTime = 0; + } + } + + //连发判断 + if (continuousCount > 0 && delayedTime <= 0 && attackTimer <= 0) + { + //开火 + TriggernFire(); + } + + if (!attackFlag && attackTimer <= 0) + { + CurrScatteringRange = Mathf.Max(CurrScatteringRange - Attribute.ScatteringRangeBackSpeed * delta, Attribute.StartScatteringRange); + } + triggerTimer = triggerTimer > 0 ? triggerTimer - delta : 0; + triggerFlag = false; + attackFlag = false; + + //武器身回归 + Position = Position.MoveToward(Vector2.Zero, 35 * delta); + if (fireInterval == 0) + { + RotationDegrees = 0; + } + else + { + RotationDegrees = Mathf.Lerp(0, fireAngle, attackTimer / fireInterval); + } + } + } + + public void Init(WeaponAttribute attribute) + { + if (_attribute != null) + { + throw new Exception("当前武器已经初始化过了!"); + } + + WeaponSprite = GetNode("WeaponSprite"); + FirePoint = GetNode("FirePoint"); + OriginPoint = GetNode("OriginPoint"); + ShellPoint = GetNode("ShellPoint"); + AnimationPlayer = GetNode("AnimationPlayer"); + CollisionShape2D = GetNode("Collision"); + + Attribute = attribute; + //更新图片 + WeaponSprite.Texture = attribute.Sprite; + WeaponSprite.Position = Attribute.CenterPosition; + //开火位置 + FirePoint.Position = new Vector2(attribute.FirePosition.x, -attribute.FirePosition.y); + OriginPoint.Position = new Vector2(0, -attribute.FirePosition.y); + + //弹药量 + CurrAmmo = attribute.AmmoCapacity; + //剩余弹药量 + ResidueAmmo = attribute.MaxAmmoCapacity - attribute.AmmoCapacity; + + Init(); + } + + /// + /// 扳机函数, 调用即视为扣动扳机 + /// + public void Trigger() + { + //是否第一帧按下 + var justDown = downTimer == 0; + //是否能发射 + var flag = false; + if (continuousCount <= 0) //不能处于连发状态下 + { + if (Attribute.ContinuousShoot) //自动射击 + { + if (triggerTimer > 0) + { + if (continuousShootFlag) + { + flag = true; + } + } + else + { + flag = true; + if (delayedTime <= 0 && attackTimer <= 0) + { + continuousShootFlag = true; + } + } + } + else //半自动 + { + if (justDown && triggerTimer <= 0) + { + flag = true; + } + } + } + + if (flag) + { + if (Reloading) + { + //换弹中 + + } + else if (CurrAmmo <= 0) + { + //子弹不够 + _Reload(); + } + else + { + if (justDown) + { + //开火前延时 + delayedTime = Attribute.DelayedTime; + //扳机按下间隔 + triggerTimer = Attribute.TriggerInterval; + //连发数量 + if (!Attribute.ContinuousShoot) + { + continuousCount = MathUtils.RandRangeInt(Attribute.MinContinuousCount, Attribute.MaxContinuousCount); + } + } + if (delayedTime <= 0 && attackTimer <= 0) + { + TriggernFire(); + } + attackFlag = true; + } + + } + triggerFlag = true; + } + + /// + /// 刚按下扳机 + /// + private void DownTrigger() + { + + } + + /// + /// 刚松开扳机 + /// + private void UpTriggern() + { + continuousShootFlag = false; + if (delayedTime > 0) + { + continuousCount = 0; + } + } + + /// + /// 触发开火 + /// + private void TriggernFire() + { + continuousCount = continuousCount > 0 ? continuousCount - 1 : 0; + + //减子弹数量 + CurrAmmo--; + //开火间隙 + fireInterval = 60 / Attribute.StartFiringSpeed; + //攻击冷却 + attackTimer += fireInterval; + + //触发开火函数 + OnFire(); + + //开火发射的子弹数量 + var bulletCount = MathUtils.RandRangeInt(Attribute.MaxFireBulletCount, Attribute.MinFireBulletCount); + //武器口角度 + var angle = new Vector2(GameConfig.ScatteringDistance, CurrScatteringRange).Angle(); + + //创建子弹 + for (int i = 0; i < bulletCount; i++) + { + //先算武器口方向 + Rotation = (float)GD.RandRange(-angle, angle); + //发射子弹 + OnShootBullet(); + } + + //当前的散射半径 + CurrScatteringRange = Mathf.Min(CurrScatteringRange + Attribute.ScatteringRangeAddValue, Attribute.FinalScatteringRange); + //武器的旋转角度 + RotationDegrees -= Attribute.UpliftAngle; + fireAngle = RotationDegrees; + //武器身位置 + Position = new Vector2(Mathf.Max(-Attribute.MaxBacklash, Position.x - MathUtils.RandRange(Attribute.MinBacklash, Attribute.MaxBacklash)), Position.y); + + if (FireEvent != null) + { + FireEvent(this); + } + } + + /// + /// 返回弹药是否到达上限 + /// + public bool IsFullAmmo() + { + return CurrAmmo + ResidueAmmo >= Attribute.MaxAmmoCapacity; + } + + /// + /// 返回是否弹药耗尽 + /// + public bool IsEmptyAmmo() + { + return CurrAmmo + ResidueAmmo == 0; + } + + /// + /// 拾起的弹药数量, 如果到达容量上限, 则返回拾取完毕后剩余的弹药数量 + /// + /// 弹药数量 + public int PickUpAmmo(int count) + { + var num = ResidueAmmo; + ResidueAmmo = Mathf.Min(ResidueAmmo + count, Attribute.MaxAmmoCapacity - CurrAmmo); + return count - ResidueAmmo + num; + } + + /// + /// 触发换弹 + /// + public void _Reload() + { + if (CurrAmmo < Attribute.AmmoCapacity && ResidueAmmo > 0 && !Reloading) + { + Reloading = true; + ReloadTimer = Attribute.ReloadTime; + OnReload(); + } + } + + /// + /// 换弹计时器时间到, 执行换弹操作 + /// + private void ReloadSuccess() + { + if (Attribute.AloneReload) //单独装填 + { + + } + else //换弹结束 + { + Reloading = false; + if (ResidueAmmo >= Attribute.AmmoCapacity) + { + ResidueAmmo -= Attribute.AmmoCapacity - CurrAmmo; + CurrAmmo = Attribute.AmmoCapacity; + } + else + { + CurrAmmo = ResidueAmmo; + ResidueAmmo = 0; + } + } + } + + public CheckInteractiveResult CheckInteractive(Role master) + { + var result = new CheckInteractiveResult(this); + if (Master == null) + { + var masterWeapon = master.Holster.ActiveWeapon; + //查找是否有同类型武器 + var index = master.Holster.FindWeapon(Attribute.Id); + if (index != -1) //如果有这个武器 + { + if (CurrAmmo + ResidueAmmo != 0) //子弹不为空 + { + var targetWeapon = master.Holster.GetWeapon(index); + if (!targetWeapon.IsFullAmmo()) //背包里面的武器子弹未满 + { + //可以互动拾起弹药 + result.CanInteractive = true; + result.Message = Attribute.Name; + result.ShowIcon = "res://resource/sprite/ui/icon/icon_bullet.png"; + return result; + } + } + } + else //没有武器 + { + if (master.Holster.CanPickupWeapon(this)) //能拾起武器 + { + //可以互动, 拾起武器 + result.CanInteractive = true; + result.Message = Attribute.Name; + result.ShowIcon = "res://resource/sprite/ui/icon/icon_pickup.png"; + return result; + } + else if (masterWeapon != null && masterWeapon.Attribute.WeightType == Attribute.WeightType) //替换武器 + { + //可以互动, 切换武器 + result.CanInteractive = true; + result.Message = Attribute.Name; + result.ShowIcon = "res://resource/sprite/ui/icon/icon_replace.png"; + return result; + } + } + } + return result; + } + + public void Interactive(Role master) + { + //查找是否有同类型武器 + var index = master.Holster.FindWeapon(Attribute.Id); + if (index != -1) //如果有这个武器 + { + if (CurrAmmo + ResidueAmmo == 0) //没有子弹了 + { + return; + } + var weapon = master.Holster.GetWeapon(index); + //子弹上限 + var maxCount = Attribute.MaxAmmoCapacity; + //是否捡到子弹 + var flag = false; + if (ResidueAmmo > 0 && weapon.CurrAmmo + weapon.ResidueAmmo < maxCount) + { + var count = weapon.PickUpAmmo(ResidueAmmo); + if (count != ResidueAmmo) + { + ResidueAmmo = count; + flag = true; + } + } + if (CurrAmmo > 0 && weapon.CurrAmmo + weapon.ResidueAmmo < maxCount) + { + var count = weapon.PickUpAmmo(CurrAmmo); + if (count != CurrAmmo) + { + CurrAmmo = count; + flag = true; + } + } + //播放互动效果 + if (flag) + { + this.StartThrow(new Vector2(20, 20), GlobalPosition, 0, 0, + MathUtils.RandRangeInt(-20, 20), MathUtils.RandRangeInt(20, 50), + MathUtils.RandRangeInt(-180, 180), WeaponSprite); + } + } + else //没有武器 + { + if (master.Holster.PickupWeapon(this) == -1) + { + var slot = master.Holster.SlotList[master.Holster.ActiveIndex]; + if (slot.Type == Attribute.WeightType) + { + var weapon = master.Holster.RmoveWeapon(master.Holster.ActiveIndex); + weapon.StartThrowWeapon(master); + master.PickUpWeapon(this); + } + } + } + } + + public Vector2 GetItemPosition() + { + return GlobalPosition; + } + + /// + /// 触发落到地面 + /// + public void _FallToGround() + { + //启用碰撞 + CollisionShape2D.Disabled = false; + } + + /// + /// 触发拾起 + /// + public void _PickUpWeapon(Role master) + { + Master = master; + //握把位置 + WeaponSprite.Position = Attribute.HoldPosition; + //清除泛白效果 + ShaderMaterial sm = WeaponSprite.Material as ShaderMaterial; + sm.SetShaderParam("schedule", 0); + //停止动画 + AnimationPlayer.Stop(); + ZIndex = 0; + //禁用碰撞 + CollisionShape2D.Disabled = true; + OnPickUp(master); + } + + /// + /// 触发抛出 + /// + public void _ThrowOutWeapon() + { + Master = null; + WeaponSprite.Position = Attribute.CenterPosition; + AnimationPlayer.Play("Floodlight"); + OnThrowOut(); + } + + /// + /// 触发启用武器 + /// + public void _Active() + { + OnActive(); + } + + /// + /// 触发收起武器 + /// + public void _Conceal() + { + OnConceal(); + } + + /// + /// 实例化并返回子弹对象 + /// + /// 子弹的预制体 + protected T CreateBullet(PackedScene bulletPack, Vector2 globalPostion, float globalRotation, Node parent = null) where T : Node2D, IBullet + { + return (T)CreateBullet(bulletPack, globalPostion, globalRotation, parent); + } + + /// + /// 实例化并返回子弹对象 + /// + /// 子弹的预制体 + protected IBullet CreateBullet(PackedScene bulletPack, Vector2 globalPostion, float globalRotation, Node parent = null) + { + // 实例化子弹 + Node2D bullet = bulletPack.Instance(); + // 设置坐标 + bullet.GlobalPosition = globalPostion; + // 旋转角度 + bullet.GlobalRotation = globalRotation; + if (parent == null) + { + RoomManager.Current.SortRoot.AddChild(bullet); + } + else + { + parent.AddChild(bullet); + } + // 调用初始化 + IBullet result = (IBullet)bullet; + result.Init(TargetCamp, this, null); + return result; + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/weapon/WeaponAttribute.cs b/DungeonShooting_Godot/src/weapon/WeaponAttribute.cs new file mode 100644 index 0000000..7480d56 --- /dev/null +++ b/DungeonShooting_Godot/src/weapon/WeaponAttribute.cs @@ -0,0 +1,161 @@ +using Godot; + +/// +/// 武器上的属性 +/// +public class WeaponAttribute +{ + /// + /// 武器的唯一id + /// + public string Id = "1"; + /// + /// 武器显示的名称 + /// + public string Name = "Gun1"; + /// + /// 武器类型 + /// + public WeaponWeightType WeightType = WeaponWeightType.MainWeapon; + /// + /// 武器的图片 + /// + public Texture Sprite; + /// + /// 子弹预制体 + /// + public PackedScene BulletPack; + /// + /// 弹壳预制体 + /// + public PackedScene ShellPack; + /// + /// 是否连续发射, 如果为false, 则每次发射都需要扣动扳机 + /// + public bool ContinuousShoot = true; + /// + /// 弹夹容量 + /// + public int AmmoCapacity = 30; + /// + /// 弹药容量上限 + /// + public int MaxAmmoCapacity = 90; + /// + /// 装弹时间 + /// + public float ReloadTime = 1.5f; + /// + /// 每粒子弹是否是单独装填, 如果是, 那么每上一发子弹的时间就是 ReloadTime, 可以做霰弹武器装填效果 + /// + public bool AloneReload = false; + /// + /// 单独装填的子弹时可以立即射击, 必须要将 'AloneReload' 属性设置为 true + /// + public bool AloneReloadCanShoot = false; + /// + /// 是否为松发开火, 也就是松开扳机才开火, 若要启用该属性, 必须将 'ContinuousShoot' 设置为 false + /// + public bool LooseShoot = false; + /// + /// 连续发射最小次数, 仅当 ContinuousShoot 为 false 时生效 + /// + public int MinContinuousCount = 3; + /// + /// 连续发射最大次数, 仅当 ContinuousShoot 为 false 时生效 + /// + public int MaxContinuousCount = 3; + /// + /// 按下一次扳机后需要多长时间才能再次按下 + /// + public float TriggerInterval = 0; + /// + /// 初始射速, 初始每秒分钟能发射多少发子弹 + /// + public float StartFiringSpeed = 300; + /// + /// 最终射速, 最终每秒分钟能发射多少发子弹 + /// + public float FinalFiringSpeed = 300; + /// + /// 按下扳机并开火后射速增加速率 + /// + public float FiringSpeedAddSpeed = 2; + /// + /// 松开扳机后射速消散速率 + /// + public float FiringSpeedBackSpeed = 10; + /// + /// 单次开火发射子弹最小数量 + /// + public int MinFireBulletCount = 1; + /// + /// 单次开火发射子弹最大数量 + /// + public int MaxFireBulletCount = 1; + /// + /// 开火前延时 + /// + public float DelayedTime = 0f; + /// + /// 初始散射半径 + /// + public float StartScatteringRange = 0; + /// + /// 最终散射半径 + /// + public float FinalScatteringRange = 20; + /// + /// 每次发射后散射增加值 + /// + public float ScatteringRangeAddValue = 2; + /// + /// 松开扳机后散射销退速率 + /// + public float ScatteringRangeBackSpeed = 10; + /// + /// 子弹飞行最大距离 + /// + public float MaxDistance = 600; + /// + /// 子弹飞行最小距离 + /// + public float MinDistance = 800; + /// + /// 武器精灵的旋转中心坐标 + /// + public Vector2 CenterPosition = new Vector2(0, 0); + /// + /// 开火位置 + /// + public Vector2 FirePosition = new Vector2(11, 0); + /// + /// 握把位置 + /// + public Vector2 HoldPosition = new Vector2(4, -3); + /// + /// 重量 + /// + public float Weight = 11; + /// + /// 最大后坐力 (仅用于开火后武器身抖动) + /// + public float MaxBacklash = 4; + /// + /// 最小后坐力 (仅用于开火后武器身抖动) + /// + public float MinBacklash = 2; + /// + /// 开火后武器口上抬角度 + /// + public float UpliftAngle = 30; + /// + /// 开火后武器口角度恢复速度倍数 + /// + public float UpliftAngleRestore = 1; + + public WeaponAttribute() + { + + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/weapon/WeaponManager.cs b/DungeonShooting_Godot/src/weapon/WeaponManager.cs new file mode 100644 index 0000000..013f73a --- /dev/null +++ b/DungeonShooting_Godot/src/weapon/WeaponManager.cs @@ -0,0 +1,235 @@ +using System.Collections.Generic; +using Godot; + +public static class WeaponManager +{ + + public static void RegisterWeapon() + { + + } + + public static Weapon GetGun(string id) + { + return null; + } + + public static T GetGun(string id) where T : Weapon + { + return (T)GetGun(id); + } + + + //----------------------------- 以下均为临时处理 ------------------------------- + + public static Weapon GetGun1() + { + //加载枪的 prefab + var gun = ResourceManager.LoadWeaponAndInstance("res://prefab/weapon/Weapon.tscn"); + //设置基础属性 + var attr = new WeaponAttribute(); + attr.Id = "1"; + attr.Name = "Gun1"; + attr.Weight = 40; + attr.CenterPosition = new Vector2(0.4f, -2.6f); + attr.StartFiringSpeed = 480; + attr.StartScatteringRange = 30; + attr.FinalScatteringRange = 90; + attr.ScatteringRangeAddValue = 2f; + attr.ScatteringRangeBackSpeed = 40; + //连发 + attr.ContinuousShoot = true; + //扳机检测间隔 + attr.TriggerInterval = 0f; + //连发数量 + attr.MinContinuousCount = 3; + attr.MaxContinuousCount = 3; + //开火前延时 + attr.DelayedTime = 0f; + //攻击距离 + attr.MinDistance = 500; + attr.MaxDistance = 600; + //发射子弹数量 + attr.MinFireBulletCount = 1; + attr.MaxFireBulletCount = 1; + //抬起角度 + attr.UpliftAngle = 10; + //枪身长度 + attr.FirePosition = new Vector2(16, 1.5f); + attr.Sprite = ResourceManager.Load("res://resource/sprite/gun/gun4.png"); + attr.BulletPack = ResourceManager.Load("res://prefab/weapon/bullet/OrdinaryBullets.tscn"); + attr.ShellPack = ResourceManager.Load("res://prefab/weapon/shell/ShellCase.tscn"); + gun.Init(attr); + return gun; + } + + public static Weapon GetGun2() + { + //加载枪的 prefab + var gun = ResourceManager.LoadWeaponAndInstance("res://prefab/weapon/Weapon.tscn"); + //设置基础属性 + var attr = new WeaponAttribute(); + attr.Id = "2"; + attr.Name = "Gun2"; + attr.Weight = 20; + attr.CenterPosition = new Vector2(0.4f, -2.6f); + attr.WeightType = WeaponWeightType.DeputyWeapon; + attr.StartFiringSpeed = 600; + attr.StartScatteringRange = 5; + attr.FinalScatteringRange = 60; + attr.ScatteringRangeAddValue = 8f; + attr.ScatteringRangeBackSpeed = 40; + //连发 + attr.ContinuousShoot = false; + //扳机检测间隔 + attr.TriggerInterval = 0.4f; + //连发数量 + attr.MinContinuousCount = 3; + attr.MaxContinuousCount = 3; + //开火前延时 + attr.DelayedTime = 0f; + //攻击距离 + attr.MinDistance = 500; + attr.MaxDistance = 600; + //发射子弹数量 + attr.MinFireBulletCount = 1; + attr.MaxFireBulletCount = 1; + //抬起角度 + attr.UpliftAngle = 30; + //枪身长度 + attr.FirePosition = new Vector2(10, 1.5f); + attr.Sprite = ResourceManager.Load("res://resource/sprite/gun/gun3.png"); + attr.BulletPack = ResourceManager.Load("res://prefab/weapon/bullet/HighSpeedBullet.tscn"); + attr.ShellPack = ResourceManager.Load("res://prefab/weapon/shell/ShellCase.tscn"); + gun.Init(attr); + return gun; + } + + public static Weapon GetGun3() + { + //加载枪的 prefab + var gun = ResourceManager.LoadWeaponAndInstance("res://prefab/weapon/Weapon.tscn"); + //设置基础属性 + var attr = new WeaponAttribute(); + attr.Id = "3"; + attr.Name = "Gun3"; + attr.Weight = 30; + attr.CenterPosition = new Vector2(0.4f, -2.6f); + attr.StartFiringSpeed = 480; + attr.StartScatteringRange = 30; + attr.FinalScatteringRange = 90; + attr.ScatteringRangeAddValue = 2f; + attr.ScatteringRangeBackSpeed = 40; + //连发 + attr.ContinuousShoot = false; + //扳机检测间隔 + attr.TriggerInterval = 0f; + //连发数量 + attr.MinContinuousCount = 3; + attr.MaxContinuousCount = 3; + //开火前延时 + attr.DelayedTime = 0f; + //攻击距离 + attr.MinDistance = 500; + attr.MaxDistance = 600; + //发射子弹数量 + attr.MinFireBulletCount = 1; + attr.MaxFireBulletCount = 1; + //抬起角度 + attr.UpliftAngle = 10; + //枪身长度 + attr.FirePosition = new Vector2(16, 1.5f); + attr.Sprite = ResourceManager.Load("res://resource/sprite/gun/gun2.png"); + attr.BulletPack = ResourceManager.Load("res://prefab/weapon/bullet/OrdinaryBullets.tscn"); + attr.ShellPack = ResourceManager.Load("res://prefab/weapon/shell/ShellCase.tscn"); + gun.Init(attr); + return gun; + } + + public static Weapon GetGun4() + { + //加载枪的 prefab + var gun = ResourceManager.LoadWeaponAndInstance("res://prefab/weapon/Weapon.tscn"); + //设置基础属性 + var attr = new WeaponAttribute(); + attr.Id = "4"; + attr.Name = "Gun4"; + attr.Weight = 10; + attr.CenterPosition = new Vector2(0.4f, -2.6f); + attr.WeightType = WeaponWeightType.DeputyWeapon; + attr.StartFiringSpeed = 600; + attr.StartScatteringRange = 5; + attr.FinalScatteringRange = 60; + attr.ScatteringRangeAddValue = 8f; + attr.ScatteringRangeBackSpeed = 40; + //连发 + attr.ContinuousShoot = false; + //扳机检测间隔 + attr.TriggerInterval = 0.4f; + //连发数量 + attr.MinContinuousCount = 3; + attr.MaxContinuousCount = 3; + //开火前延时 + attr.DelayedTime = 0f; + //攻击距离 + attr.MinDistance = 500; + attr.MaxDistance = 600; + //发射子弹数量 + attr.MinFireBulletCount = 1; + attr.MaxFireBulletCount = 1; + //抬起角度 + attr.UpliftAngle = 30; + //枪身长度 + attr.FirePosition = new Vector2(10, 1.5f); + attr.Sprite = ResourceManager.Load("res://resource/sprite/gun/gun7.png"); + attr.BulletPack = ResourceManager.Load("res://prefab/weapon/bullet/HighSpeedBullet.tscn"); + attr.ShellPack = ResourceManager.Load("res://prefab/weapon/shell/ShellCase.tscn"); + gun.Init(attr); + return gun; + } + + public static Weapon GetGun5() + { + //加载枪的 prefab + var gun = ResourceManager.LoadWeaponAndInstance("res://prefab/weapon/Weapon.tscn"); + //设置基础属性 + var attr = new WeaponAttribute(); + attr.Id = "5"; + attr.Name = "Gun5"; + attr.Weight = 10; + attr.CenterPosition = new Vector2(0.4f, -2.6f); + attr.WeightType = WeaponWeightType.DeputyWeapon; + attr.StartFiringSpeed = 480; + attr.StartScatteringRange = 5; + attr.FinalScatteringRange = 30; + attr.ScatteringRangeAddValue = 8f; + attr.ScatteringRangeBackSpeed = 40; + //连发 + attr.ContinuousShoot = true; + //扳机检测间隔 + attr.TriggerInterval = 0.4f; + //连发数量 + attr.MinContinuousCount = 1; + attr.MaxContinuousCount = 1; + //开火前延时 + attr.DelayedTime = 0f; + //攻击距离 + attr.MinDistance = 500; + attr.MaxDistance = 600; + //发射子弹数量 + attr.MinFireBulletCount = 1; + attr.MaxFireBulletCount = 1; + //弹夹容量 + attr.AmmoCapacity = 120; + attr.MaxAmmoCapacity = 360; + //抬起角度 + attr.UpliftAngle = 30; + //枪身长度 + attr.FirePosition = new Vector2(10, 1.5f); + attr.Sprite = ResourceManager.Load("res://resource/sprite/gun/gun5.png"); + attr.BulletPack = ResourceManager.Load("res://prefab/weapon/bullet/HighSpeedBullet.tscn"); + attr.ShellPack = ResourceManager.Load("res://prefab/weapon/shell/ShellCase.tscn"); + gun.Init(attr); + return gun; + } +} diff --git a/DungeonShooting_Godot/src/weapon/WeaponWeightType.cs b/DungeonShooting_Godot/src/weapon/WeaponWeightType.cs new file mode 100644 index 0000000..5528683 --- /dev/null +++ b/DungeonShooting_Godot/src/weapon/WeaponWeightType.cs @@ -0,0 +1,19 @@ + +/// +/// 根据重量划分的武器类型 +/// +public enum WeaponWeightType +{ + /// + /// 副武器 + /// + DeputyWeapon = 1, + /// + /// 主武器 + /// + MainWeapon = 2, + /// + /// 重型武器 + /// + HeavyWeapon = 3 +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/weapon/bullet/Bullet.cs b/DungeonShooting_Godot/src/weapon/bullet/Bullet.cs index ec5ac06..4c19b4b 100644 --- a/DungeonShooting_Godot/src/weapon/bullet/Bullet.cs +++ b/DungeonShooting_Godot/src/weapon/bullet/Bullet.cs @@ -12,7 +12,7 @@ /// /// 发射该子弹的武器 /// - Gun Gun { get; } + Weapon Gun { get; } /// /// 发射该子弹的物体对象 /// @@ -23,5 +23,5 @@ /// 攻击的目标阵营 /// 发射该子弹的枪对象 /// 发射该子弹的角色 - void Init(CampEnum target, Gun gun, Node2D master); + void Init(CampEnum target, Weapon gun, Node2D master); } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/weapon/bullet/HighSpeedBullet.cs b/DungeonShooting_Godot/src/weapon/bullet/HighSpeedBullet.cs index 039c416..53ef711 100644 --- a/DungeonShooting_Godot/src/weapon/bullet/HighSpeedBullet.cs +++ b/DungeonShooting_Godot/src/weapon/bullet/HighSpeedBullet.cs @@ -7,7 +7,7 @@ { public CampEnum TargetCamp { get; private set; } - public Gun Gun { get; private set; } + public Weapon Gun { get; private set; } public Node2D Master { get; private set; } @@ -21,7 +21,7 @@ private Line2D Line; private float ca = 1; - public void Init(CampEnum target, Gun gun, Node2D master) + public void Init(CampEnum target, Weapon gun, Node2D master) { TargetCamp = target; Gun = gun; diff --git a/DungeonShooting_Godot/src/weapon/bullet/OrdinaryBullets.cs b/DungeonShooting_Godot/src/weapon/bullet/OrdinaryBullets.cs index 7e65b85..4458e5f 100644 --- a/DungeonShooting_Godot/src/weapon/bullet/OrdinaryBullets.cs +++ b/DungeonShooting_Godot/src/weapon/bullet/OrdinaryBullets.cs @@ -8,7 +8,7 @@ { public CampEnum TargetCamp { get; private set; } - public Gun Gun { get; private set; } + public Weapon Gun { get; private set; } public Node2D Master { get; private set; } @@ -34,7 +34,7 @@ private int frame = 0; - public void Init(CampEnum target, Gun gun, Node2D master) + public void Init(CampEnum target, Weapon gun, Node2D master) { TargetCamp = target; Gun = gun; diff --git a/DungeonShooting_Godot/src/weapon/gun/Gun.cs b/DungeonShooting_Godot/src/weapon/gun/Gun.cs deleted file mode 100644 index d8b63b5..0000000 --- a/DungeonShooting_Godot/src/weapon/gun/Gun.cs +++ /dev/null @@ -1,696 +0,0 @@ -using Godot; -using System; - -/// -/// 枪的基类 -/// -public abstract class Gun : Area2D, IProp -{ - /// - /// 开火回调事件 - /// - public event Action FireEvent; - - /// - /// 属性数据 - /// - public GunAttribute Attribute - { - get - { - if (_attribute == null) - { - throw new Exception("请先调用Init来初始化枪的属性"); - } - return _attribute; - } - private set => _attribute = value; - } - private GunAttribute _attribute; - - /// - /// 枪的图片 - /// - public Sprite GunSprite { get; private set; } - - /// - /// 动画播放器 - /// - /// - public AnimationPlayer AnimationPlayer { get; private set; } - - /// - /// 枪攻击的目标阵营 - /// - public CampEnum TargetCamp { get; set; } - - /// - /// 该武器的拥有者 - /// - public Role Master { get; private set; } - - /// - /// 当前弹夹弹药剩余量 - /// - public int CurrAmmo { get; private set; } - /// - /// 剩余弹药量 - /// - public int ResidueAmmo { get; private set; } - - /// - /// 枪管的开火点 - /// - public Position2D FirePoint { get; private set; } - /// - /// 枪管的原点 - /// - public Position2D OriginPoint { get; private set; } - /// - /// 弹壳抛出的点 - /// - public Position2D ShellPoint { get; private set; } - /// - /// 碰撞器节点 - /// - /// - public CollisionShape2D CollisionShape2D { get; private set; } - /// - /// 枪的当前散射半径 - /// - public float CurrScatteringRange { get; private set; } = 0; - /// - /// 是否在换弹中 - /// - /// - public bool Reloading { get; private set; } = false; - /// - /// 换弹计时器 - /// - public float ReloadTimer { get; private set; } = 0; - /// - /// 换弹进度 (0 - 1) - /// - public float ReloadProgress => ReloadTimer / Attribute.ReloadTime; - - //是否按下 - private bool triggerFlag = false; - //扳机计时器 - private float triggerTimer = 0; - //开火前延时时间 - private float delayedTime = 0; - //开火间隙时间 - private float fireInterval = 0; - //开火枪口角度 - private float fireAngle = 0; - //攻击冷却计时 - private float attackTimer = 0; - //攻击状态 - private bool attackFlag = false; - //按下的时间 - private float downTimer = 0; - //松开的时间 - private float upTimer = 0; - //连发次数 - private float continuousCount = 0; - //连发状态记录 - private bool continuousShootFlag = false; - - /// - /// 初始化时调用 - /// - protected abstract void Init(); - - /// - /// 单次开火时调用的函数 - /// - protected abstract void OnFire(); - - /// - /// 换弹时调用 - /// - protected abstract void OnReload(); - - /// - /// 发射子弹时调用的函数, 每发射一枚子弹调用一次, - /// 如果做霰弹枪效果, 一次开火发射5枚子弹, 则该函数调用5次 - /// - protected abstract void OnShootBullet(); - - /// - /// 当武器被拾起时调用 - /// - /// 拾起该武器的角色 - protected abstract void OnPickUp(Role master); - - /// - /// 当武器被扔掉时调用 - /// - protected abstract void OnThrowOut(); - - /// - /// 当武器被激活时调用, 也就是使用当武器是调用 - /// - protected abstract void OnActive(); - - /// - /// 当武器被收起时调用 - /// - protected abstract void OnConceal(); - - public override void _Process(float delta) - { - if (Master == null) //这把武器被扔在地上 - { - Reloading = false; - triggerTimer = triggerTimer > 0 ? triggerTimer - delta : 0; - triggerFlag = false; - attackFlag = false; - attackTimer = attackTimer > 0 ? attackTimer - delta : 0; - CurrScatteringRange = Mathf.Max(CurrScatteringRange - Attribute.ScatteringRangeBackSpeed * delta, Attribute.StartScatteringRange); - continuousCount = 0; - delayedTime = 0; - } - else if (Master.Holster.ActiveGun != this) //当前武器没有被使用 - { - Reloading = false; - triggerTimer = triggerTimer > 0 ? triggerTimer - delta : 0; - triggerFlag = false; - attackFlag = false; - attackTimer = attackTimer > 0 ? attackTimer - delta : 0; - CurrScatteringRange = Mathf.Max(CurrScatteringRange - Attribute.ScatteringRangeBackSpeed * delta, Attribute.StartScatteringRange); - continuousCount = 0; - delayedTime = 0; - } - else //正在使用中 - { - - //换弹 - if (Reloading) - { - ReloadTimer -= delta; - if (ReloadTimer <= 0) - { - ReloadTimer = 0; - ReloadSuccess(); - } - } - - if (triggerFlag) - { - if (upTimer > 0) //第一帧按下扳机 - { - upTimer = 0; - DownTrigger(); - } - downTimer += delta; - } - else - { - if (downTimer > 0) //第一帧松开扳机 - { - downTimer = 0; - UpTriggern(); - } - upTimer += delta; - } - - // 攻击的计时器 - if (attackTimer > 0) - { - attackTimer -= delta; - if (attackTimer < 0) - { - delayedTime += attackTimer; - attackTimer = 0; - } - } - else if (delayedTime > 0) //攻击延时 - { - delayedTime -= delta; - if (attackTimer < 0) - { - delayedTime = 0; - } - } - - //连发判断 - if (continuousCount > 0 && delayedTime <= 0 && attackTimer <= 0) - { - //开火 - TriggernFire(); - } - - if (!attackFlag && attackTimer <= 0) - { - CurrScatteringRange = Mathf.Max(CurrScatteringRange - Attribute.ScatteringRangeBackSpeed * delta, Attribute.StartScatteringRange); - } - triggerTimer = triggerTimer > 0 ? triggerTimer - delta : 0; - triggerFlag = false; - attackFlag = false; - - //枪身回归 - Position = Position.MoveToward(Vector2.Zero, 35 * delta); - if (fireInterval == 0) - { - RotationDegrees = 0; - } - else - { - RotationDegrees = Mathf.Lerp(0, fireAngle, attackTimer / fireInterval); - } - } - } - - public void Init(GunAttribute attribute) - { - if (_attribute != null) - { - throw new Exception("当前武器已经初始化过了!"); - } - - GunSprite = GetNode("GunSprite"); - FirePoint = GetNode("FirePoint"); - OriginPoint = GetNode("OriginPoint"); - ShellPoint = GetNode("ShellPoint"); - AnimationPlayer = GetNode("AnimationPlayer"); - CollisionShape2D = GetNode("Collision"); - - Attribute = attribute; - //更新图片 - GunSprite.Texture = attribute.Sprite; - GunSprite.Position = Attribute.CenterPosition; - //开火位置 - FirePoint.Position = new Vector2(attribute.FirePosition.x, -attribute.FirePosition.y); - OriginPoint.Position = new Vector2(0, -attribute.FirePosition.y); - - //弹药量 - CurrAmmo = attribute.AmmoCapacity; - //剩余弹药量 - ResidueAmmo = attribute.MaxAmmoCapacity - attribute.AmmoCapacity; - - Init(); - } - - /// - /// 扳机函数, 调用即视为扣动扳机 - /// - public void Trigger() - { - //是否第一帧按下 - var justDown = downTimer == 0; - //是否能发射 - var flag = false; - if (continuousCount <= 0) //不能处于连发状态下 - { - if (Attribute.ContinuousShoot) //自动射击 - { - if (triggerTimer > 0) - { - if (continuousShootFlag) - { - flag = true; - } - } - else - { - flag = true; - if (delayedTime <= 0 && attackTimer <= 0) - { - continuousShootFlag = true; - } - } - } - else //半自动 - { - if (justDown && triggerTimer <= 0) - { - flag = true; - } - } - } - - if (flag) - { - if (Reloading) - { - //换弹中 - GD.Print("换弹中..." + ReloadProgress); - } - else if (CurrAmmo <= 0) - { - //子弹不够 - GD.Print("弹夹打空了, 按R换弹!"); - } - else - { - if (justDown) - { - //开火前延时 - delayedTime = Attribute.DelayedTime; - //扳机按下间隔 - triggerTimer = Attribute.TriggerInterval; - //连发数量 - if (!Attribute.ContinuousShoot) - { - continuousCount = MathUtils.RandRangeInt(Attribute.MinContinuousCount, Attribute.MaxContinuousCount); - } - } - if (delayedTime <= 0 && attackTimer <= 0) - { - TriggernFire(); - } - attackFlag = true; - } - - } - triggerFlag = true; - } - - /// - /// 刚按下扳机 - /// - private void DownTrigger() - { - - } - - /// - /// 刚松开扳机 - /// - private void UpTriggern() - { - continuousShootFlag = false; - if (delayedTime > 0) - { - continuousCount = 0; - } - } - - /// - /// 触发开火 - /// - private void TriggernFire() - { - continuousCount = continuousCount > 0 ? continuousCount - 1 : 0; - - //减子弹数量 - CurrAmmo--; - //开火间隙 - fireInterval = 60 / Attribute.StartFiringSpeed; - //攻击冷却 - attackTimer += fireInterval; - - //触发开火函数 - OnFire(); - - //开火发射的子弹数量 - var bulletCount = MathUtils.RandRangeInt(Attribute.MaxFireBulletCount, Attribute.MinFireBulletCount); - //枪口角度 - var angle = new Vector2(GameConfig.ScatteringDistance, CurrScatteringRange).Angle(); - - //创建子弹 - for (int i = 0; i < bulletCount; i++) - { - //先算枪口方向 - Rotation = (float)GD.RandRange(-angle, angle); - //发射子弹 - OnShootBullet(); - } - - //当前的散射半径 - CurrScatteringRange = Mathf.Min(CurrScatteringRange + Attribute.ScatteringRangeAddValue, Attribute.FinalScatteringRange); - //枪的旋转角度 - RotationDegrees -= Attribute.UpliftAngle; - fireAngle = RotationDegrees; - //枪身位置 - Position = new Vector2(Mathf.Max(-Attribute.MaxBacklash, Position.x - MathUtils.RandRange(Attribute.MinBacklash, Attribute.MaxBacklash)), Position.y); - - if (FireEvent != null) - { - FireEvent(this); - } - } - - /// - /// 返回弹药是否到达上限 - /// - public bool IsFullAmmo() - { - return CurrAmmo + ResidueAmmo >= Attribute.MaxAmmoCapacity; - } - - /// - /// 返回是否弹药耗尽 - /// - public bool IsEmptyAmmo() - { - return CurrAmmo + ResidueAmmo == 0; - } - - /// - /// 拾起的弹药数量, 如果到达容量上限, 则返回拾取完毕后剩余的弹药数量 - /// - /// 弹药数量 - public int PickUpAmmo(int count) - { - var num = ResidueAmmo; - ResidueAmmo = Mathf.Min(ResidueAmmo + count, Attribute.MaxAmmoCapacity - CurrAmmo); - return count - ResidueAmmo + num; - } - - /// - /// 触发换弹 - /// - public void _Reload() - { - if (CurrAmmo < Attribute.AmmoCapacity && ResidueAmmo > 0 && !Reloading) - { - Reloading = true; - ReloadTimer = Attribute.ReloadTime; - OnReload(); - } - } - - /// - /// 换弹计时器时间到, 执行换弹操作 - /// - private void ReloadSuccess() - { - if (Attribute.AloneReload) //单独装填 - { - - } - else //换弹结束 - { - Reloading = false; - if (ResidueAmmo >= Attribute.AmmoCapacity) - { - ResidueAmmo -= Attribute.AmmoCapacity - CurrAmmo; - CurrAmmo = Attribute.AmmoCapacity; - } - else - { - CurrAmmo = ResidueAmmo; - ResidueAmmo = 0; - } - } - } - - public CheckInteractiveResult CheckInteractive(Role master) - { - var result = new CheckInteractiveResult(this); - if (Master == null) - { - var masterGun = master.Holster.ActiveGun; - //查找是否有同类型武器 - var index = master.Holster.FindGun(Attribute.Id); - if (index != -1) //如果有这个武器 - { - if (CurrAmmo + ResidueAmmo != 0) //子弹不为空 - { - var targetGun = master.Holster.GetGun(index); - if (!targetGun.IsFullAmmo()) //背包里面的武器子弹未满 - { - //可以互动拾起弹药 - result.CanInteractive = true; - result.Message = Attribute.Name; - result.ShowIcon = "res://resource/sprite/ui/icon/icon_bullet.png"; - return result; - } - } - } - else //没有武器 - { - if (master.Holster.CanPickupGun(this)) //能拾起武器 - { - //可以互动, 拾起武器 - result.CanInteractive = true; - result.Message = Attribute.Name; - result.ShowIcon = "res://resource/sprite/ui/icon/icon_pickup.png"; - return result; - } - else if (masterGun != null && masterGun.Attribute.WeightType == Attribute.WeightType) //替换武器 - { - //可以互动, 切换武器 - result.CanInteractive = true; - result.Message = Attribute.Name; - result.ShowIcon = "res://resource/sprite/ui/icon/icon_replace.png"; - return result; - } - } - } - return result; - } - - public void Interactive(Role master) - { - //查找是否有同类型武器 - var index = master.Holster.FindGun(Attribute.Id); - if (index != -1) //如果有这个武器 - { - if (CurrAmmo + ResidueAmmo == 0) //没有子弹了 - { - return; - } - var gun = master.Holster.GetGun(index); - //子弹上限 - var maxCount = Attribute.MaxAmmoCapacity; - //是否捡到子弹 - var flag = false; - if (ResidueAmmo > 0 && gun.CurrAmmo + gun.ResidueAmmo < maxCount) - { - var count = gun.PickUpAmmo(ResidueAmmo); - if (count != ResidueAmmo) - { - ResidueAmmo = count; - flag = true; - } - } - if (CurrAmmo > 0 && gun.CurrAmmo + gun.ResidueAmmo < maxCount) - { - var count = gun.PickUpAmmo(CurrAmmo); - if (count != CurrAmmo) - { - CurrAmmo = count; - flag = true; - } - } - //播放互动效果 - if (flag) - { - this.StartThrow(new Vector2(20, 20), GlobalPosition, 0, 0, - MathUtils.RandRangeInt(-20, 20), MathUtils.RandRangeInt(20, 50), - MathUtils.RandRangeInt(-180, 180), GunSprite); - } - } - else //没有武器 - { - if (master.Holster.PickupGun(this) == -1) - { - var slot = master.Holster.SlotList[master.Holster.ActiveIndex]; - if (slot.Type == Attribute.WeightType) - { - var gun = master.Holster.RmoveGun(master.Holster.ActiveIndex); - gun.StartThrowGun(master); - master.PickUpGun(this); - } - } - } - } - - public Vector2 GetItemPosition() - { - return GlobalPosition; - } - - /// - /// 触发落到地面 - /// - public void _FallToGround() - { - //启用碰撞 - CollisionShape2D.Disabled = false; - } - - /// - /// 触发拾起 - /// - public void _PickUpGun(Role master) - { - Master = master; - //握把位置 - GunSprite.Position = Attribute.HoldPosition; - //清除泛白效果 - ShaderMaterial sm = GunSprite.Material as ShaderMaterial; - sm.SetShaderParam("schedule", 0); - //停止动画 - AnimationPlayer.Stop(); - ZIndex = 0; - //禁用碰撞 - CollisionShape2D.Disabled = true; - OnPickUp(master); - } - - /// - /// 触发抛出 - /// - public void _ThrowOutGun() - { - Master = null; - GunSprite.Position = Attribute.CenterPosition; - AnimationPlayer.Play("Floodlight"); - OnThrowOut(); - } - - /// - /// 触发启用武器 - /// - public void _Active() - { - OnActive(); - } - - /// - /// 触发收起武器 - /// - public void _Conceal() - { - OnConceal(); - } - - /// - /// 实例化并返回子弹对象 - /// - /// 子弹的预制体 - protected T CreateBullet(PackedScene bulletPack, Vector2 globalPostion, float globalRotation, Node parent = null) where T : Node2D, IBullet - { - return (T)CreateBullet(bulletPack, globalPostion, globalRotation, parent); - } - - /// - /// 实例化并返回子弹对象 - /// - /// 子弹的预制体 - protected IBullet CreateBullet(PackedScene bulletPack, Vector2 globalPostion, float globalRotation, Node parent = null) - { - // 实例化子弹 - Node2D bullet = bulletPack.Instance(); - // 设置坐标 - bullet.GlobalPosition = globalPostion; - // 旋转角度 - bullet.GlobalRotation = globalRotation; - if (parent == null) - { - RoomManager.Current.SortRoot.AddChild(bullet); - } - else - { - parent.AddChild(bullet); - } - // 调用初始化 - IBullet result = (IBullet)bullet; - result.Init(TargetCamp, this, null); - return result; - } -} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/weapon/gun/GunAttribute.cs b/DungeonShooting_Godot/src/weapon/gun/GunAttribute.cs deleted file mode 100644 index 8e48069..0000000 --- a/DungeonShooting_Godot/src/weapon/gun/GunAttribute.cs +++ /dev/null @@ -1,161 +0,0 @@ -using Godot; - -/// -/// 枪上的属性 -/// -public class GunAttribute -{ - /// - /// 武器的唯一id - /// - public string Id = "1"; - /// - /// 武器显示的名称 - /// - public string Name = "Gun1"; - /// - /// 武器类型 - /// - public GunWeightType WeightType = GunWeightType.MainWeapon; - /// - /// 枪的图片 - /// - public Texture Sprite; - /// - /// 子弹预制体 - /// - public PackedScene BulletPack; - /// - /// 弹壳预制体 - /// - public PackedScene ShellPack; - /// - /// 是否连续发射, 如果为false, 则每次发射都需要扣动扳机 - /// - public bool ContinuousShoot = true; - /// - /// 弹夹容量 - /// - public int AmmoCapacity = 30; - /// - /// 弹药容量上限 - /// - public int MaxAmmoCapacity = 90; - /// - /// 装弹时间 - /// - public float ReloadTime = 1.5f; - /// - /// 每粒子弹是否是单独装填, 如果是, 那么每上一发子弹的时间就是 ReloadTime, 可以做霰弹枪装填效果 - /// - public bool AloneReload = false; - /// - /// 单独装填的子弹时可以立即射击, 必须要将 'AloneReload' 属性设置为 true - /// - public bool AloneReloadCanShoot = false; - /// - /// 是否为松发开火, 也就是松开扳机才开火, 若要启用该属性, 必须将 'ContinuousShoot' 设置为 false - /// - public bool LooseShoot = false; - /// - /// 连续发射最小次数, 仅当 ContinuousShoot 为 false 时生效 - /// - public int MinContinuousCount = 3; - /// - /// 连续发射最大次数, 仅当 ContinuousShoot 为 false 时生效 - /// - public int MaxContinuousCount = 3; - /// - /// 按下一次扳机后需要多长时间才能再次按下 - /// - public float TriggerInterval = 0; - /// - /// 初始射速, 初始每秒分钟能发射多少发子弹 - /// - public float StartFiringSpeed = 300; - /// - /// 最终射速, 最终每秒分钟能发射多少发子弹 - /// - public float FinalFiringSpeed = 300; - /// - /// 按下扳机并开火后射速增加速率 - /// - public float FiringSpeedAddSpeed = 2; - /// - /// 松开扳机后射速消散速率 - /// - public float FiringSpeedBackSpeed = 10; - /// - /// 单次开火发射子弹最小数量 - /// - public int MinFireBulletCount = 1; - /// - /// 单次开火发射子弹最大数量 - /// - public int MaxFireBulletCount = 1; - /// - /// 开火前延时 - /// - public float DelayedTime = 0f; - /// - /// 初始散射半径 - /// - public float StartScatteringRange = 0; - /// - /// 最终散射半径 - /// - public float FinalScatteringRange = 20; - /// - /// 每次发射后散射增加值 - /// - public float ScatteringRangeAddValue = 2; - /// - /// 松开扳机后散射销退速率 - /// - public float ScatteringRangeBackSpeed = 10; - /// - /// 子弹飞行最大距离 - /// - public float MaxDistance = 600; - /// - /// 子弹飞行最小距离 - /// - public float MinDistance = 800; - /// - /// 武器精灵的旋转中心坐标 - /// - public Vector2 CenterPosition = new Vector2(0, 0); - /// - /// 开火位置 - /// - public Vector2 FirePosition = new Vector2(11, 0); - /// - /// 握把位置 - /// - public Vector2 HoldPosition = new Vector2(4, -3); - /// - /// 重量 - /// - public float Weight = 11; - /// - /// 最大后坐力 (仅用于开火后枪身抖动) - /// - public float MaxBacklash = 4; - /// - /// 最小后坐力 (仅用于开火后枪身抖动) - /// - public float MinBacklash = 2; - /// - /// 开火后枪口上抬角度 - /// - public float UpliftAngle = 30; - /// - /// 开火后枪口角度恢复速度倍数 - /// - public float UpliftAngleRestore = 1; - - public GunAttribute() - { - - } -} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/weapon/gun/GunManager.cs b/DungeonShooting_Godot/src/weapon/gun/GunManager.cs deleted file mode 100644 index 50bc089..0000000 --- a/DungeonShooting_Godot/src/weapon/gun/GunManager.cs +++ /dev/null @@ -1,217 +0,0 @@ -using System.Collections.Generic; -using Godot; - -public static class GunManager -{ - - public static Gun GetGun1() - { - //加载枪的 prefab - var gun = ResourceManager.LoadGunAndInstance("res://prefab/weapon/Gun.tscn"); - //设置基础属性 - var attr = new GunAttribute(); - attr.Id = "1"; - attr.Name = "Gun1"; - attr.Weight = 40; - attr.CenterPosition = new Vector2(0.4f, -2.6f); - attr.StartFiringSpeed = 480; - attr.StartScatteringRange = 30; - attr.FinalScatteringRange = 90; - attr.ScatteringRangeAddValue = 2f; - attr.ScatteringRangeBackSpeed = 40; - //连发 - attr.ContinuousShoot = true; - //扳机检测间隔 - attr.TriggerInterval = 0f; - //连发数量 - attr.MinContinuousCount = 3; - attr.MaxContinuousCount = 3; - //开火前延时 - attr.DelayedTime = 0f; - //攻击距离 - attr.MinDistance = 500; - attr.MaxDistance = 600; - //发射子弹数量 - attr.MinFireBulletCount = 1; - attr.MaxFireBulletCount = 1; - //抬起角度 - attr.UpliftAngle = 10; - //枪身长度 - attr.FirePosition = new Vector2(16, 1.5f); - attr.Sprite = ResourceManager.Load("res://resource/sprite/gun/gun4.png"); - attr.BulletPack = ResourceManager.Load("res://prefab/weapon/bullet/OrdinaryBullets.tscn"); - attr.ShellPack = ResourceManager.Load("res://prefab/weapon/shell/ShellCase.tscn"); - gun.Init(attr); - return gun; - } - - public static Gun GetGun2() - { - //加载枪的 prefab - var gun = ResourceManager.LoadGunAndInstance("res://prefab/weapon/Gun.tscn"); - //设置基础属性 - var attr = new GunAttribute(); - attr.Id = "2"; - attr.Name = "Gun2"; - attr.Weight = 20; - attr.CenterPosition = new Vector2(0.4f, -2.6f); - attr.WeightType = GunWeightType.DeputyWeapon; - attr.StartFiringSpeed = 600; - attr.StartScatteringRange = 5; - attr.FinalScatteringRange = 60; - attr.ScatteringRangeAddValue = 8f; - attr.ScatteringRangeBackSpeed = 40; - //连发 - attr.ContinuousShoot = false; - //扳机检测间隔 - attr.TriggerInterval = 0.4f; - //连发数量 - attr.MinContinuousCount = 3; - attr.MaxContinuousCount = 3; - //开火前延时 - attr.DelayedTime = 0f; - //攻击距离 - attr.MinDistance = 500; - attr.MaxDistance = 600; - //发射子弹数量 - attr.MinFireBulletCount = 1; - attr.MaxFireBulletCount = 1; - //抬起角度 - attr.UpliftAngle = 30; - //枪身长度 - attr.FirePosition = new Vector2(10, 1.5f); - attr.Sprite = ResourceManager.Load("res://resource/sprite/gun/gun3.png"); - attr.BulletPack = ResourceManager.Load("res://prefab/weapon/bullet/HighSpeedBullet.tscn"); - attr.ShellPack = ResourceManager.Load("res://prefab/weapon/shell/ShellCase.tscn"); - gun.Init(attr); - return gun; - } - - public static Gun GetGun3() - { - //加载枪的 prefab - var gun = ResourceManager.LoadGunAndInstance("res://prefab/weapon/Gun.tscn"); - //设置基础属性 - var attr = new GunAttribute(); - attr.Id = "3"; - attr.Name = "Gun3"; - attr.Weight = 30; - attr.CenterPosition = new Vector2(0.4f, -2.6f); - attr.StartFiringSpeed = 480; - attr.StartScatteringRange = 30; - attr.FinalScatteringRange = 90; - attr.ScatteringRangeAddValue = 2f; - attr.ScatteringRangeBackSpeed = 40; - //连发 - attr.ContinuousShoot = false; - //扳机检测间隔 - attr.TriggerInterval = 0f; - //连发数量 - attr.MinContinuousCount = 3; - attr.MaxContinuousCount = 3; - //开火前延时 - attr.DelayedTime = 0f; - //攻击距离 - attr.MinDistance = 500; - attr.MaxDistance = 600; - //发射子弹数量 - attr.MinFireBulletCount = 1; - attr.MaxFireBulletCount = 1; - //抬起角度 - attr.UpliftAngle = 10; - //枪身长度 - attr.FirePosition = new Vector2(16, 1.5f); - attr.Sprite = ResourceManager.Load("res://resource/sprite/gun/gun2.png"); - attr.BulletPack = ResourceManager.Load("res://prefab/weapon/bullet/OrdinaryBullets.tscn"); - attr.ShellPack = ResourceManager.Load("res://prefab/weapon/shell/ShellCase.tscn"); - gun.Init(attr); - return gun; - } - - public static Gun GetGun4() - { - //加载枪的 prefab - var gun = ResourceManager.LoadGunAndInstance("res://prefab/weapon/Gun.tscn"); - //设置基础属性 - var attr = new GunAttribute(); - attr.Id = "4"; - attr.Name = "Gun4"; - attr.Weight = 10; - attr.CenterPosition = new Vector2(0.4f, -2.6f); - attr.WeightType = GunWeightType.DeputyWeapon; - attr.StartFiringSpeed = 600; - attr.StartScatteringRange = 5; - attr.FinalScatteringRange = 60; - attr.ScatteringRangeAddValue = 8f; - attr.ScatteringRangeBackSpeed = 40; - //连发 - attr.ContinuousShoot = false; - //扳机检测间隔 - attr.TriggerInterval = 0.4f; - //连发数量 - attr.MinContinuousCount = 3; - attr.MaxContinuousCount = 3; - //开火前延时 - attr.DelayedTime = 0f; - //攻击距离 - attr.MinDistance = 500; - attr.MaxDistance = 600; - //发射子弹数量 - attr.MinFireBulletCount = 1; - attr.MaxFireBulletCount = 1; - //抬起角度 - attr.UpliftAngle = 30; - //枪身长度 - attr.FirePosition = new Vector2(10, 1.5f); - attr.Sprite = ResourceManager.Load("res://resource/sprite/gun/gun7.png"); - attr.BulletPack = ResourceManager.Load("res://prefab/weapon/bullet/HighSpeedBullet.tscn"); - attr.ShellPack = ResourceManager.Load("res://prefab/weapon/shell/ShellCase.tscn"); - gun.Init(attr); - return gun; - } - - public static Gun GetGun5() - { - //加载枪的 prefab - var gun = ResourceManager.LoadGunAndInstance("res://prefab/weapon/Gun.tscn"); - //设置基础属性 - var attr = new GunAttribute(); - attr.Id = "5"; - attr.Name = "Gun5"; - attr.Weight = 10; - attr.CenterPosition = new Vector2(0.4f, -2.6f); - attr.WeightType = GunWeightType.DeputyWeapon; - attr.StartFiringSpeed = 480; - attr.StartScatteringRange = 5; - attr.FinalScatteringRange = 30; - attr.ScatteringRangeAddValue = 8f; - attr.ScatteringRangeBackSpeed = 40; - //连发 - attr.ContinuousShoot = true; - //扳机检测间隔 - attr.TriggerInterval = 0.4f; - //连发数量 - attr.MinContinuousCount = 1; - attr.MaxContinuousCount = 1; - //开火前延时 - attr.DelayedTime = 0f; - //攻击距离 - attr.MinDistance = 500; - attr.MaxDistance = 600; - //发射子弹数量 - attr.MinFireBulletCount = 1; - attr.MaxFireBulletCount = 1; - //弹夹容量 - attr.AmmoCapacity = 120; - attr.MaxAmmoCapacity = 360; - //抬起角度 - attr.UpliftAngle = 30; - //枪身长度 - attr.FirePosition = new Vector2(10, 1.5f); - attr.Sprite = ResourceManager.Load("res://resource/sprite/gun/gun5.png"); - attr.BulletPack = ResourceManager.Load("res://prefab/weapon/bullet/HighSpeedBullet.tscn"); - attr.ShellPack = ResourceManager.Load("res://prefab/weapon/shell/ShellCase.tscn"); - gun.Init(attr); - return gun; - } -} diff --git a/DungeonShooting_Godot/src/weapon/gun/GunWeightType.cs b/DungeonShooting_Godot/src/weapon/gun/GunWeightType.cs deleted file mode 100644 index 4181693..0000000 --- a/DungeonShooting_Godot/src/weapon/gun/GunWeightType.cs +++ /dev/null @@ -1,19 +0,0 @@ - -/// -/// 根据重量划分的武器类型 -/// -public enum GunWeightType -{ - /// - /// 副武器 - /// - DeputyWeapon = 1, - /// - /// 主武器 - /// - MainWeapon = 2, - /// - /// 重型武器 - /// - HeavyWeapon = 3 -} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/weapon/gun/OrdinaryGun.cs b/DungeonShooting_Godot/src/weapon/gun/OrdinaryGun.cs index 18bc183..30e8c05 100644 --- a/DungeonShooting_Godot/src/weapon/gun/OrdinaryGun.cs +++ b/DungeonShooting_Godot/src/weapon/gun/OrdinaryGun.cs @@ -5,7 +5,7 @@ /// /// 普通的枪 /// -public class OrdinaryGun : Gun +public class OrdinaryGun : Weapon { protected override void Init() { @@ -22,7 +22,7 @@ var yf = MathUtils.RandRangeInt(60, 120); var rotate = MathUtils.RandRangeInt(-720, 720); var sprite = Attribute.ShellPack.Instance(); - sprite.StartThrow(new Vector2(5, 10), startPos, startHeight, direction, xf, yf, rotate, sprite); + sprite.StartThrow(new Vector2(5, 10), startPos, startHeight, direction, xf, yf, rotate, sprite); //创建抖动 MainCamera.Main.ProssesDirectionalShake(Vector2.Right.Rotated(GlobalRotation) * 1.5f); } diff --git a/DungeonShooting_Godot/src/weapon/gun/ThrowGun.cs b/DungeonShooting_Godot/src/weapon/gun/ThrowGun.cs deleted file mode 100644 index 9ea6b86..0000000 --- a/DungeonShooting_Godot/src/weapon/gun/ThrowGun.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Godot; - -public class ThrowGun : ThrowNode -{ - - private bool fristOver = true; - - public override void _Ready() - { - base._Ready(); - ZIndex = 2; - } - - public override void StartThrow(Vector2 size, Vector2 start, float startHeight, float direction, float xSpeed, float ySpeed, float rotate, Node2D mount) - { - base.StartThrow(size, start, startHeight, direction, xSpeed, ySpeed, rotate, mount); - fristOver = true; - } - - protected override void OnOver() - { - if (fristOver) - { - fristOver = false; - if (Mount is Gun gun) - { - gun._FallToGround(); - } - } - //如果落地高度不够低, 再抛一次 - if (StartYSpeed > 1) - { - StartThrow(Size, GlobalPosition, 0, Direction, XSpeed * 0.8f, StartYSpeed * 0.5f, RotateSpeed * 0.5f, null); - } - else //结束 - { - base.OnOver(); - } - } - protected override void OnMaxHeight(float height) - { - ZIndex = 0; - } -} \ No newline at end of file