diff --git a/prefab/Cursor.tscn b/prefab/Cursor.tscn
index 3c2fb6e..1202607 100644
--- a/prefab/Cursor.tscn
+++ b/prefab/Cursor.tscn
@@ -1,7 +1,7 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://resource/sprite/effect/Cursor.png" type="Texture" id=1]
-[ext_resource path="res://src/Cursor.cs" type="Script" id=2]
+[ext_resource path="res://src/effect/Cursor.cs" type="Script" id=2]
[node name="Cursor" type="Node2D"]
script = ExtResource( 2 )
diff --git a/prefab/Gun.tscn b/prefab/Gun.tscn
index c04ae84..449a8b3 100644
--- a/prefab/Gun.tscn
+++ b/prefab/Gun.tscn
@@ -1,7 +1,7 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://resource/sprite/gun/gun1.png" type="Texture" id=1]
-[ext_resource path="res://src/weapon/gun/OrdinaryGun.cs" type="Script" id=2]
+[ext_resource path="res://src/gun/OrdinaryGun.cs" type="Script" id=2]
[sub_resource type="RectangleShape2D" id=1]
extents = Vector2( 9.5, 3.5 )
diff --git a/prefab/bullet/Bullet.tscn b/prefab/bullet/Bullet.tscn
index eb6d9ff..21eba41 100644
--- a/prefab/bullet/Bullet.tscn
+++ b/prefab/bullet/Bullet.tscn
@@ -1,6 +1,6 @@
[gd_scene load_steps=5 format=2]
-[ext_resource path="res://src/weapon/bullet/HighSpeedBullet.cs" type="Script" id=1]
+[ext_resource path="res://src/bullet/HighSpeedBullet.cs" type="Script" id=1]
[ext_resource path="res://prefab/effect/Hit.tscn" type="PackedScene" id=2]
[sub_resource type="Curve" id=1]
diff --git a/src/Cursor.cs b/src/Cursor.cs
deleted file mode 100644
index 4450f54..0000000
--- a/src/Cursor.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using Godot;
-
-///
-/// 鼠标指针
-///
-public class Cursor : Node2D
-{
-
- public Gun TargetGun = null;
-
- private Sprite lt;
- private Sprite lb;
- private Sprite rt;
- private Sprite rb;
-
- public override void _Ready()
- {
- lt = GetNode("LT");
- lb = GetNode("LB");
- rt = GetNode("RT");
- rb = GetNode("RB");
- }
-
- public override void _Process(float delta)
- {
- if (TargetGun != null)
- {
- SetScope(TargetGun.CurrScatteringRange);
- }
- else
- {
- SetScope(0);
- }
- SetCursorPos();
- }
-
- ///
- /// 设置光标半径范围
- ///
- private void SetScope(float scope)
- {
- if (TargetGun != null)
- {
- var len = GlobalPosition.DistanceTo(TargetGun.GlobalPosition);
- if (TargetGun.Attribute != null)
- {
- len = Mathf.Max(0, len - TargetGun.Attribute.FirePosition.x);
- }
- scope = len / GameConfig.ScatteringDistance * scope;
- }
- lt.Position = new Vector2(-scope, -scope);
- lb.Position = new Vector2(-scope, scope);
- rt.Position = new Vector2(scope, -scope);
- rb.Position = new Vector2(scope, scope);
- }
-
- private void SetCursorPos()
- {
- Position = GetGlobalMousePosition();
- }
-}
\ No newline at end of file
diff --git a/src/bullet/Bullet.cs b/src/bullet/Bullet.cs
new file mode 100644
index 0000000..a56e98d
--- /dev/null
+++ b/src/bullet/Bullet.cs
@@ -0,0 +1,27 @@
+using Godot;
+
+///
+/// 子弹
+///
+public abstract class Bullet : Node2D
+{
+ ///
+ /// 攻击目标阵营
+ ///
+ public CampEnum TargetCamp { get; private set; }
+ ///
+ /// 发射该子弹的武器
+ ///
+ public Gun Gun { get; private set; }
+ ///
+ /// 发射该子弹的物体对象
+ ///
+ public Node2D Master { get; private set; }
+
+ public void Init(CampEnum target, Gun gun, Node2D master)
+ {
+ TargetCamp = target;
+ Gun = gun;
+ Master = master;
+ }
+}
\ No newline at end of file
diff --git a/src/bullet/HighSpeedBullet.cs b/src/bullet/HighSpeedBullet.cs
new file mode 100644
index 0000000..e71eeba
--- /dev/null
+++ b/src/bullet/HighSpeedBullet.cs
@@ -0,0 +1,56 @@
+using Godot;
+
+///
+/// 高速子弹
+///
+public class HighSpeedBullet : Bullet
+{
+ [Export] public PackedScene Hit;
+ //射线检测节点
+ private RayCast2D RayCast2D;
+ //最大飞行距离
+ private float Distance;
+ private Line2D Line;
+ private float ca = 1;
+
+ public void InitData(float distance, Color color)
+ {
+ RayCast2D = GetNode("RayCast2D");
+ Line = GetNode("Line");
+ Distance = distance;
+ Modulate = color;
+
+ Vector2 targetPos = new Vector2(distance, 0);
+
+ //
+ RayCast2D.CastTo = targetPos;
+ RayCast2D.ForceRaycastUpdate();
+ if (RayCast2D.IsColliding()) { //碰到物体
+ Vector2 collPosition = RayCast2D.GetCollisionPoint();
+ Node2D hit = Hit.Instance();
+ hit.RotationDegrees = MathUtils.RandRangeInt(0, 360);
+ hit.GlobalPosition = collPosition;
+ GetTree().CurrentScene.AddChild(hit);
+ //划线的点坐标
+ Line.SetPointPosition(1, new Vector2(Line.GlobalPosition.DistanceTo(collPosition), 0));
+ }
+ else
+ {
+ //划线的点坐标
+ Line.SetPointPosition(1, targetPos);
+ }
+ RayCast2D.Enabled = false;
+ }
+
+ public override void _Process(float delta)
+ {
+ ca -= 12 * delta;
+ if (ca <= 0) {
+ QueueFree();
+ return;
+ }
+ Color c = Modulate;
+ c.a = ca;
+ Modulate = c;
+ }
+}
\ No newline at end of file
diff --git a/src/effect/Cursor.cs b/src/effect/Cursor.cs
new file mode 100644
index 0000000..4450f54
--- /dev/null
+++ b/src/effect/Cursor.cs
@@ -0,0 +1,61 @@
+using Godot;
+
+///
+/// 鼠标指针
+///
+public class Cursor : Node2D
+{
+
+ public Gun TargetGun = null;
+
+ private Sprite lt;
+ private Sprite lb;
+ private Sprite rt;
+ private Sprite rb;
+
+ public override void _Ready()
+ {
+ lt = GetNode("LT");
+ lb = GetNode("LB");
+ rt = GetNode("RT");
+ rb = GetNode("RB");
+ }
+
+ public override void _Process(float delta)
+ {
+ if (TargetGun != null)
+ {
+ SetScope(TargetGun.CurrScatteringRange);
+ }
+ else
+ {
+ SetScope(0);
+ }
+ SetCursorPos();
+ }
+
+ ///
+ /// 设置光标半径范围
+ ///
+ private void SetScope(float scope)
+ {
+ if (TargetGun != null)
+ {
+ var len = GlobalPosition.DistanceTo(TargetGun.GlobalPosition);
+ if (TargetGun.Attribute != null)
+ {
+ len = Mathf.Max(0, len - TargetGun.Attribute.FirePosition.x);
+ }
+ scope = len / GameConfig.ScatteringDistance * scope;
+ }
+ lt.Position = new Vector2(-scope, -scope);
+ lb.Position = new Vector2(-scope, scope);
+ rt.Position = new Vector2(scope, -scope);
+ rb.Position = new Vector2(scope, scope);
+ }
+
+ private void SetCursorPos()
+ {
+ Position = GetGlobalMousePosition();
+ }
+}
\ No newline at end of file
diff --git a/src/gun/Gun.cs b/src/gun/Gun.cs
new file mode 100644
index 0000000..f32823c
--- /dev/null
+++ b/src/gun/Gun.cs
@@ -0,0 +1,304 @@
+using Godot;
+using System;
+
+///
+/// 枪的基类
+///
+public abstract class Gun : Node2D
+{
+ ///
+ /// 开火回调事件
+ ///
+ 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 CampEnum TargetCamp { get; set; }
+ ///
+ /// 枪管的开火点
+ ///
+ public Position2D FirePoint { get; private set; }
+ ///
+ /// 枪管的原点
+ ///
+ public Position2D OriginPoint { get; private set; }
+ ///
+ /// 枪的当前散射半径
+ ///
+ public float CurrScatteringRange { get; private set; } = 0;
+
+ //是否按下
+ 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;
+
+ public override void _EnterTree()
+ {
+ GunSprite = GetNode("GunSprite");
+ FirePoint = GetNode("FirePoint");
+ OriginPoint = GetNode("OriginPoint");
+ }
+
+ public override void _Process(float delta)
+ {
+ 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("当前武器已经初始化过了!");
+ }
+
+ Attribute = attribute;
+ //更新图片
+ var texture = ResourceLoader.Load(attribute.Sprite);
+ GunSprite.Texture = texture;
+ //开火位置
+ FirePoint.Position = new Vector2(attribute.FirePosition.x, -attribute.FirePosition.y);
+ OriginPoint.Position = new Vector2(0, -attribute.FirePosition.y);
+ //握把位置
+ GunSprite.Position = attribute.HoldPosition;
+
+ 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 (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;
+ fireInterval = 60 / Attribute.StartFiringSpeed;
+ attackTimer += fireInterval;
+
+ //触发开火函数
+ Fire();
+
+ //开火发射的子弹数量
+ 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);
+ //发射子弹
+ ShootBullet();
+ }
+
+ //当前的散射半径
+ 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);
+ }
+ }
+
+ ///
+ /// 初始化时调用
+ ///
+ protected abstract void Init();
+
+ ///
+ /// 单次开火时调用的函数
+ ///
+ protected abstract void Fire();
+
+ ///
+ /// 发射子弹时调用的函数, 每发射一枚子弹调用一次,
+ /// 如果做霰弹枪效果, 一次开火发射5枚子弹, 则该函数调用5次
+ ///
+ protected abstract void ShootBullet();
+}
\ No newline at end of file
diff --git a/src/gun/GunAttribute.cs b/src/gun/GunAttribute.cs
new file mode 100644
index 0000000..aaeab64
--- /dev/null
+++ b/src/gun/GunAttribute.cs
@@ -0,0 +1,117 @@
+using Godot;
+
+///
+/// 枪上的属性
+///
+public class GunAttribute
+{
+ ///
+ /// 枪的图片
+ ///
+ public string Sprite = "res://resource/sprite/gun/gun1.png";
+ ///
+ /// 是否连续发射, 如果为false, 则每次发射都需要扣动扳机
+ ///
+ public bool ContinuousShoot = true;
+ ///
+ /// 是否为松发开火, 也就是松开扳机才开火, 若要启用该属性, 必须将 '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 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/src/gun/OrdinaryGun.cs b/src/gun/OrdinaryGun.cs
new file mode 100644
index 0000000..047da0c
--- /dev/null
+++ b/src/gun/OrdinaryGun.cs
@@ -0,0 +1,44 @@
+using Godot;
+
+///
+/// 普通的枪
+///
+public class OrdinaryGun : Gun
+{
+ //子弹
+ private PackedScene bulletPacked;
+
+
+ protected override void Init()
+ {
+ //子弹
+ bulletPacked = ResourceLoader.Load("res://prefab/bullet/Bullet.tscn");
+ }
+
+ protected override void Fire()
+ {
+
+ }
+
+ protected override void ShootBullet()
+ {
+ //创建子弹
+ var bullet = CreateBullet(bulletPacked);
+ //位置
+ bullet.GlobalPosition = FirePoint.GlobalPosition;
+ //角度
+ bullet.Rotation = (FirePoint.GlobalPosition - OriginPoint.GlobalPosition).Angle();
+ GetTree().CurrentScene.AddChild(bullet);
+ //飞行距离
+ var distance = MathUtils.RandRange(Attribute.MinDistance, Attribute.MaxDistance);
+ //初始化子弹数据
+ bullet.InitData(distance, Colors.White);
+ }
+
+ protected T CreateBullet(PackedScene bulletPack) where T : Bullet
+ {
+ T bullet = bulletPack.Instance();
+ bullet.Init(TargetCamp, this, null);
+ return bullet;
+ }
+}
\ No newline at end of file
diff --git a/src/weapon/bullet/Bullet.cs b/src/weapon/bullet/Bullet.cs
deleted file mode 100644
index a56e98d..0000000
--- a/src/weapon/bullet/Bullet.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using Godot;
-
-///
-/// 子弹
-///
-public abstract class Bullet : Node2D
-{
- ///
- /// 攻击目标阵营
- ///
- public CampEnum TargetCamp { get; private set; }
- ///
- /// 发射该子弹的武器
- ///
- public Gun Gun { get; private set; }
- ///
- /// 发射该子弹的物体对象
- ///
- public Node2D Master { get; private set; }
-
- public void Init(CampEnum target, Gun gun, Node2D master)
- {
- TargetCamp = target;
- Gun = gun;
- Master = master;
- }
-}
\ No newline at end of file
diff --git a/src/weapon/bullet/HighSpeedBullet.cs b/src/weapon/bullet/HighSpeedBullet.cs
deleted file mode 100644
index e71eeba..0000000
--- a/src/weapon/bullet/HighSpeedBullet.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using Godot;
-
-///
-/// 高速子弹
-///
-public class HighSpeedBullet : Bullet
-{
- [Export] public PackedScene Hit;
- //射线检测节点
- private RayCast2D RayCast2D;
- //最大飞行距离
- private float Distance;
- private Line2D Line;
- private float ca = 1;
-
- public void InitData(float distance, Color color)
- {
- RayCast2D = GetNode("RayCast2D");
- Line = GetNode("Line");
- Distance = distance;
- Modulate = color;
-
- Vector2 targetPos = new Vector2(distance, 0);
-
- //
- RayCast2D.CastTo = targetPos;
- RayCast2D.ForceRaycastUpdate();
- if (RayCast2D.IsColliding()) { //碰到物体
- Vector2 collPosition = RayCast2D.GetCollisionPoint();
- Node2D hit = Hit.Instance();
- hit.RotationDegrees = MathUtils.RandRangeInt(0, 360);
- hit.GlobalPosition = collPosition;
- GetTree().CurrentScene.AddChild(hit);
- //划线的点坐标
- Line.SetPointPosition(1, new Vector2(Line.GlobalPosition.DistanceTo(collPosition), 0));
- }
- else
- {
- //划线的点坐标
- Line.SetPointPosition(1, targetPos);
- }
- RayCast2D.Enabled = false;
- }
-
- public override void _Process(float delta)
- {
- ca -= 12 * delta;
- if (ca <= 0) {
- QueueFree();
- return;
- }
- Color c = Modulate;
- c.a = ca;
- Modulate = c;
- }
-}
\ No newline at end of file
diff --git a/src/weapon/gun/Gun.cs b/src/weapon/gun/Gun.cs
deleted file mode 100644
index f32823c..0000000
--- a/src/weapon/gun/Gun.cs
+++ /dev/null
@@ -1,304 +0,0 @@
-using Godot;
-using System;
-
-///
-/// 枪的基类
-///
-public abstract class Gun : Node2D
-{
- ///
- /// 开火回调事件
- ///
- 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 CampEnum TargetCamp { get; set; }
- ///
- /// 枪管的开火点
- ///
- public Position2D FirePoint { get; private set; }
- ///
- /// 枪管的原点
- ///
- public Position2D OriginPoint { get; private set; }
- ///
- /// 枪的当前散射半径
- ///
- public float CurrScatteringRange { get; private set; } = 0;
-
- //是否按下
- 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;
-
- public override void _EnterTree()
- {
- GunSprite = GetNode("GunSprite");
- FirePoint = GetNode("FirePoint");
- OriginPoint = GetNode("OriginPoint");
- }
-
- public override void _Process(float delta)
- {
- 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("当前武器已经初始化过了!");
- }
-
- Attribute = attribute;
- //更新图片
- var texture = ResourceLoader.Load(attribute.Sprite);
- GunSprite.Texture = texture;
- //开火位置
- FirePoint.Position = new Vector2(attribute.FirePosition.x, -attribute.FirePosition.y);
- OriginPoint.Position = new Vector2(0, -attribute.FirePosition.y);
- //握把位置
- GunSprite.Position = attribute.HoldPosition;
-
- 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 (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;
- fireInterval = 60 / Attribute.StartFiringSpeed;
- attackTimer += fireInterval;
-
- //触发开火函数
- Fire();
-
- //开火发射的子弹数量
- 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);
- //发射子弹
- ShootBullet();
- }
-
- //当前的散射半径
- 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);
- }
- }
-
- ///
- /// 初始化时调用
- ///
- protected abstract void Init();
-
- ///
- /// 单次开火时调用的函数
- ///
- protected abstract void Fire();
-
- ///
- /// 发射子弹时调用的函数, 每发射一枚子弹调用一次,
- /// 如果做霰弹枪效果, 一次开火发射5枚子弹, 则该函数调用5次
- ///
- protected abstract void ShootBullet();
-}
\ No newline at end of file
diff --git a/src/weapon/gun/GunAttribute.cs b/src/weapon/gun/GunAttribute.cs
deleted file mode 100644
index aaeab64..0000000
--- a/src/weapon/gun/GunAttribute.cs
+++ /dev/null
@@ -1,117 +0,0 @@
-using Godot;
-
-///
-/// 枪上的属性
-///
-public class GunAttribute
-{
- ///
- /// 枪的图片
- ///
- public string Sprite = "res://resource/sprite/gun/gun1.png";
- ///
- /// 是否连续发射, 如果为false, 则每次发射都需要扣动扳机
- ///
- public bool ContinuousShoot = true;
- ///
- /// 是否为松发开火, 也就是松开扳机才开火, 若要启用该属性, 必须将 '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 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/src/weapon/gun/OrdinaryGun.cs b/src/weapon/gun/OrdinaryGun.cs
deleted file mode 100644
index 047da0c..0000000
--- a/src/weapon/gun/OrdinaryGun.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-using Godot;
-
-///
-/// 普通的枪
-///
-public class OrdinaryGun : Gun
-{
- //子弹
- private PackedScene bulletPacked;
-
-
- protected override void Init()
- {
- //子弹
- bulletPacked = ResourceLoader.Load("res://prefab/bullet/Bullet.tscn");
- }
-
- protected override void Fire()
- {
-
- }
-
- protected override void ShootBullet()
- {
- //创建子弹
- var bullet = CreateBullet(bulletPacked);
- //位置
- bullet.GlobalPosition = FirePoint.GlobalPosition;
- //角度
- bullet.Rotation = (FirePoint.GlobalPosition - OriginPoint.GlobalPosition).Angle();
- GetTree().CurrentScene.AddChild(bullet);
- //飞行距离
- var distance = MathUtils.RandRange(Attribute.MinDistance, Attribute.MaxDistance);
- //初始化子弹数据
- bullet.InitData(distance, Colors.White);
- }
-
- protected T CreateBullet(PackedScene bulletPack) where T : Bullet
- {
- T bullet = bulletPack.Instance();
- bullet.Init(TargetCamp, this, null);
- return bullet;
- }
-}
\ No newline at end of file