diff --git a/prefab/Bullet.tscn b/prefab/Bullet.tscn index 604ebb0..19d9c8e 100644 --- a/prefab/Bullet.tscn +++ b/prefab/Bullet.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=4 format=2] -[ext_resource path="res://src/gun/bullet/Bullet.cs" type="Script" id=1] +[ext_resource path="res://src/weapon/bullet/HighSpeedBullet.cs" type="Script" id=1] [sub_resource type="Curve" id=1] _data = [ Vector2( 0, 0.781588 ), 0.0, 0.0, 0, 0, Vector2( 1, 1 ), 0.0, 0.0, 0, 0 ] @@ -8,17 +8,17 @@ [sub_resource type="Gradient" id=2] colors = PoolColorArray( 1, 1, 1, 0.313726, 1, 1, 1, 0.784314 ) -[node name="Line2D" type="Line2D"] -points = PoolVector2Array( 0, 0, 100, 0 ) +[node name="Bullet" type="Node2D"] +script = ExtResource( 1 ) + +[node name="Line" type="Line2D" parent="."] +points = PoolVector2Array( 0, 0, 0, 10 ) width = 1.0 width_curve = SubResource( 1 ) default_color = Color( 1, 1, 1, 1 ) gradient = SubResource( 2 ) begin_cap_mode = 2 end_cap_mode = 2 -script = ExtResource( 1 ) [node name="RayCast2D" type="RayCast2D" parent="."] visible = false -rotation = 4.71239 -enabled = true diff --git a/prefab/Cursor.tscn b/prefab/Cursor.tscn index 593f9e1..3c2fb6e 100644 --- a/prefab/Cursor.tscn +++ b/prefab/Cursor.tscn @@ -13,24 +13,24 @@ [node name="LT" type="Sprite" parent="."] texture = ExtResource( 1 ) -offset = Vector2( -1.5, -1.5 ) +offset = Vector2( -0.5, -0.5 ) region_enabled = true region_rect = Rect2( 0, 0, 3, 3 ) [node name="LB" type="Sprite" parent="."] texture = ExtResource( 1 ) -offset = Vector2( -1.5, 1.5 ) +offset = Vector2( -0.5, 0.5 ) region_enabled = true region_rect = Rect2( 0, 5, 3, 3 ) [node name="RT" type="Sprite" parent="."] texture = ExtResource( 1 ) -offset = Vector2( 1.5, -1.5 ) +offset = Vector2( 0.5, -0.5 ) region_enabled = true region_rect = Rect2( 5, 0, 3, 3 ) [node name="RB" type="Sprite" parent="."] texture = ExtResource( 1 ) -offset = Vector2( 1.5, 1.5 ) +offset = Vector2( 0.5, 0.5 ) region_enabled = true region_rect = Rect2( 5, 5, 3, 3 ) diff --git a/prefab/Gun.tscn b/prefab/Gun.tscn index 49e675a..ef22feb 100644 --- a/prefab/Gun.tscn +++ b/prefab/Gun.tscn @@ -1,14 +1,12 @@ [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/gun/Gun.cs" type="Script" id=2] +[ext_resource path="res://src/weapon/gun/Gun.cs" type="Script" id=2] [sub_resource type="RectangleShape2D" id=1] extents = Vector2( 9.5, 3.5 ) -[node name="Gun" type="Area2D"] -collision_layer = 4 -collision_mask = 0 +[node name="Gun" type="Node2D"] script = ExtResource( 2 ) [node name="Sprite" type="Sprite" parent="."] @@ -25,7 +23,11 @@ position = Vector2( 11, -1.5 ) scale = Vector2( 0.8, 0.8 ) -[node name="Collision" type="CollisionShape2D" parent="."] +[node name="Area" type="Area2D" parent="."] +collision_layer = 4 +collision_mask = 0 + +[node name="Collision" type="CollisionShape2D" parent="Area"] position = Vector2( 4.2, -0.199999 ) shape = SubResource( 1 ) disabled = true diff --git a/prefab/Player.tscn b/prefab/Player.tscn index 8699592..dc42a64 100644 --- a/prefab/Player.tscn +++ b/prefab/Player.tscn @@ -9,4 +9,4 @@ GunPrefab = ExtResource( 4 ) [node name="AnimatedSprite" parent="." index="0"] -frame = 3 +frame = 1 diff --git a/prefab/Role.tscn b/prefab/Role.tscn index a74fa2d..2c60000 100644 --- a/prefab/Role.tscn +++ b/prefab/Role.tscn @@ -20,22 +20,6 @@ atlas = ExtResource( 1 ) region = Rect2( 48, 24, 16, 24 ) -[sub_resource type="AtlasTexture" id=21] -atlas = ExtResource( 1 ) -region = Rect2( 0, 48, 16, 24 ) - -[sub_resource type="AtlasTexture" id=22] -atlas = ExtResource( 1 ) -region = Rect2( 16, 48, 16, 24 ) - -[sub_resource type="AtlasTexture" id=23] -atlas = ExtResource( 1 ) -region = Rect2( 32, 48, 16, 24 ) - -[sub_resource type="AtlasTexture" id=24] -atlas = ExtResource( 1 ) -region = Rect2( 48, 48, 16, 24 ) - [sub_resource type="AtlasTexture" id=25] atlas = ExtResource( 1 ) region = Rect2( 48, 48, 16, 24 ) @@ -52,6 +36,22 @@ atlas = ExtResource( 1 ) region = Rect2( 0, 48, 16, 24 ) +[sub_resource type="AtlasTexture" id=21] +atlas = ExtResource( 1 ) +region = Rect2( 0, 48, 16, 24 ) + +[sub_resource type="AtlasTexture" id=22] +atlas = ExtResource( 1 ) +region = Rect2( 16, 48, 16, 24 ) + +[sub_resource type="AtlasTexture" id=23] +atlas = ExtResource( 1 ) +region = Rect2( 32, 48, 16, 24 ) + +[sub_resource type="AtlasTexture" id=24] +atlas = ExtResource( 1 ) +region = Rect2( 48, 48, 16, 24 ) + [sub_resource type="SpriteFrames" id=6] animations = [ { "frames": [ SubResource( 17 ), SubResource( 18 ), SubResource( 19 ), SubResource( 20 ) ], @@ -59,22 +59,22 @@ "name": "idle", "speed": 7.0 }, { -"frames": [ SubResource( 21 ), SubResource( 22 ), SubResource( 23 ), SubResource( 24 ) ], -"loop": true, -"name": "run", -"speed": 10.0 -}, { "frames": [ SubResource( 25 ), SubResource( 26 ), SubResource( 27 ), SubResource( 28 ) ], "loop": true, "name": "reverseRun", "speed": 10.0 +}, { +"frames": [ SubResource( 21 ), SubResource( 22 ), SubResource( 23 ), SubResource( 24 ) ], +"loop": true, +"name": "run", +"speed": 10.0 } ] [sub_resource type="RectangleShape2D" id=29] extents = Vector2( 5, 7.5 ) [sub_resource type="RectangleShape2D" id=16] -extents = Vector2( 5, 1.5 ) +extents = Vector2( 5, 4.5 ) [node name="Role" type="KinematicBody2D"] collision_layer = 0 @@ -92,11 +92,12 @@ [node name="HitArea" type="Area2D" parent="."] [node name="CollisionShape2D" type="CollisionShape2D" parent="HitArea"] +visible = false position = Vector2( 0, -7.5 ) shape = SubResource( 29 ) [node name="Collision" type="CollisionShape2D" parent="."] -position = Vector2( 0, -1.5 ) +position = Vector2( 0, -4.5 ) shape = SubResource( 16 ) [node name="MountPoint" type="Position2D" parent="."] diff --git a/resource/tile/itch-io-DungeonTileset4.tres b/resource/tile/itch-io-DungeonTileset4.tres index cebaeb7..b2eceaa 100644 --- a/resource/tile/itch-io-DungeonTileset4.tres +++ b/resource/tile/itch-io-DungeonTileset4.tres @@ -147,16 +147,16 @@ points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 ) [sub_resource type="ConvexPolygonShape2D" id=51] -points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 ) +points = PoolVector2Array( 0, 0, 16, 0, 16, 12, 0, 12 ) [sub_resource type="ConvexPolygonShape2D" id=52] -points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 ) +points = PoolVector2Array( 0, 0, 16, 0, 16, 12, 0, 12 ) [sub_resource type="ConvexPolygonShape2D" id=53] -points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 ) +points = PoolVector2Array( 0, 0, 16, 0, 16, 12, 0, 12 ) [sub_resource type="ConvexPolygonShape2D" id=54] -points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 ) +points = PoolVector2Array( 0, 0, 16, 0, 16, 12, 0, 12 ) [resource] 0/name = "16x16 dungeon ii wall reconfig v04 spritesheet.png 0" diff --git a/scene/Room.tscn b/scene/Room.tscn index e93a913..1ce667c 100644 --- a/scene/Room.tscn +++ b/scene/Room.tscn @@ -19,6 +19,15 @@ [node name="Camera2D" type="Camera2D" parent="."] position = Vector2( 196, 128 ) current = true +limit_left = -40 +limit_top = -25 +limit_right = 470 +limit_bottom = 300 +drag_margin_h_enabled = true +drag_margin_v_enabled = true +smoothing_enabled = true +editor_draw_limits = true +editor_draw_drag_margin = true [node name="Player" parent="." instance=ExtResource( 1 )] position = Vector2( 196, 128 ) diff --git a/src/gun/Gun.cs b/src/gun/Gun.cs deleted file mode 100644 index 85adb8f..0000000 --- a/src/gun/Gun.cs +++ /dev/null @@ -1,170 +0,0 @@ -using Godot; -using System; - -public class Gun : Area2D -{ - /// - /// 开火回调事件 - /// - 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 Sprite { 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 fireInterval = 0; - private float fireAngle = 0; - private float attackTimer = 0; - private bool attackFlag = false; - private int downFrame = 0; - //子弹 - private PackedScene bulletPacked; - - public override void _EnterTree() - { - Sprite = GetNode("Sprite"); - FirePoint = GetNode("FirePoint"); - OriginPoint = GetNode("OriginPoint"); - } - - public override void _Process(float delta) - { - downFrame = triggerFlag ? downFrame : 0; - // 攻击的计时器 - if (attackTimer > 0) - { - attackTimer -= delta; - } - else if (!attackFlag && attackTimer < 0) - { - attackTimer = 0; - } - - if (!attackFlag && attackTimer <= 0) - { - CurrScatteringRange = Mathf.Max(CurrScatteringRange - Attribute.ScatteringRangeBackSpeed * delta, Attribute.StartScatteringRange); - } - 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) - { - Attribute = attribute; - //更新图片 - var texture = ResourceLoader.Load(attribute.Sprite); - Sprite.Texture = texture; - //子弹 - bulletPacked = ResourceLoader.Load(attribute.Bullet); - //开火位置 - FirePoint.Position = new Vector2(attribute.BarrelLength, FirePoint.Position.y); - } - - /// - /// 扳机函数, 调用即视为扣动扳机 - /// - public void Trigger() - { - //是否第一帧按下 - var justDown = downFrame++ == 0; - - if (Attribute.ContinuousShoot || justDown) - { - if (attackTimer <= 0) - { - fireInterval = 60 / Attribute.FiringSpeed; - attackTimer += fireInterval; - Fire(); - //当前的散射半径 - 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); - } - } - attackFlag = true; - } - triggerFlag = true; - } - - protected virtual void 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); - - //创建子弹 - var bullet = bulletPacked.Instance(); - bullet.GlobalPosition = FirePoint.GlobalPosition; - bullet.Rotation = (FirePoint.GlobalPosition - OriginPoint.GlobalPosition).Angle(); - GetTree().CurrentScene.AddChild(bullet); - - //飞行距离 - var distance = MathUtils.RandRange(Attribute.MinDistance, Attribute.MaxDistance); - //初始化子弹数据 - bullet.Init(TargetCamp, distance, Colors.White); - } - } -} \ No newline at end of file diff --git a/src/gun/GunAttribute.cs b/src/gun/GunAttribute.cs deleted file mode 100644 index 2437344..0000000 --- a/src/gun/GunAttribute.cs +++ /dev/null @@ -1,97 +0,0 @@ -using Godot; - -/// -/// 枪上的属性 -/// -public class GunAttribute -{ - /// - /// 子弹对象 - /// - public string Bullet = "res://prefab/Bullet.tscn"; - /// - /// 枪的图片 - /// - public string Sprite = "res://resource/sprite/gun/gun1.png"; - /// - /// 是否连续发射, 如果为false, 则每次发射都需要扣动扳机 - /// - public bool ContinuousShoot = true; - /// - /// 连续发射最小次数, 仅当ContinuousShoot为false时生效 - /// - public int MinContinuousCount = 3; - /// - /// 连续发射最大次数, 仅当ContinuousShoot为false时生效 - /// - public int MaxContinuousCount = 3; - /// - /// 放开扳机后需要多少时间才能再次按下扳机 - /// - public float TriggerInterval = 0; - /// - /// 射速, 每秒分钟能发射多少发子弹 - /// - public float FiringSpeed = 300; - /// - /// 单次开火发射子弹最小数量 - /// - 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 float BarrelLength = 11; - /// - /// 重量 - /// - public float Weight = 11; - /// - /// 最大后坐力 (仅用于开火后枪身抖动) - /// - public float MaxBacklash = 4; - /// - /// 最小后坐力 (仅用于开火后枪身抖动) - /// - public float MinBacklash = 2; - /// - /// 开火后枪口上抬角度 - /// - public float UpliftAngle = 30; - - public GunAttribute() - { - - } -} \ No newline at end of file diff --git a/src/gun/bullet/Bullet.cs b/src/gun/bullet/Bullet.cs deleted file mode 100644 index 582e0db..0000000 --- a/src/gun/bullet/Bullet.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Godot; - -/// -/// 子弹 -/// -public class Bullet : Line2D -{ - /// - /// 存在弹道特效存在时间 - /// - [Export] public float LifeTime = 1f; - - /// - /// 攻击目标 - /// - public CampEnum Target; - - /// - /// 最大飞行距离 - /// - public float Distance; - - private float a = 1; - - public void Init(CampEnum target, float distance, Color color) - { - Target = target; - Distance = distance; - Modulate = color; - SetPointPosition(1, new Vector2(distance, 0)); - } - - public override void _Process(float delta) - { - a -= 12 * delta; - if (a <= 0) { - QueueFree(); - return; - } - Color c = Modulate; - c.a = a; - Modulate = c; - } - -} \ No newline at end of file diff --git a/src/role/Player.cs b/src/role/Player.cs index b95a3af..11cfb09 100644 --- a/src/role/Player.cs +++ b/src/role/Player.cs @@ -30,23 +30,29 @@ var attr = new GunAttribute(); attr.FiringSpeed = 420; - attr.StartScatteringRange = 3; - attr.FinalScatteringRange = 30; - attr.ScatteringRangeAddValue = 15; + attr.StartScatteringRange = 0; + attr.FinalScatteringRange = 10; + attr.ScatteringRangeAddValue = 5; attr.ScatteringRangeBackSpeed = 20; //连发 attr.ContinuousShoot = true; + //扳机检测间隔 + attr.TriggerInterval = 1f; + //连发数量 + attr.MinContinuousCount = 3; + //开火前延时 + attr.DelayedTime = 0f; //攻击距离 attr.MinDistance = 500; attr.MaxDistance = 600; //发射子弹数量 attr.MinFireBulletCount = 1; attr.MaxFireBulletCount = 1; - // + //抬起角度 attr.UpliftAngle = 10; - - attr.BarrelLength = 10; - attr.Sprite = "res://resource/sprite/gun/gun3.png"; + //枪身长度 + attr.BarrelLength = 15; + attr.Sprite = "res://resource/sprite/gun/gun4.png"; gun.Init(attr); gun.FireEvent += FireEvent_Func; diff --git a/src/weapon/Weapon.cs b/src/weapon/Weapon.cs new file mode 100644 index 0000000..e7816d4 --- /dev/null +++ b/src/weapon/Weapon.cs @@ -0,0 +1,8 @@ + +/// +/// 武器基类 +/// +public class Weapon +{ + +} \ No newline at end of file diff --git a/src/weapon/bullet/Bullet.cs b/src/weapon/bullet/Bullet.cs new file mode 100644 index 0000000..a56e98d --- /dev/null +++ b/src/weapon/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/weapon/bullet/HighSpeedBullet.cs b/src/weapon/bullet/HighSpeedBullet.cs new file mode 100644 index 0000000..dcd7173 --- /dev/null +++ b/src/weapon/bullet/HighSpeedBullet.cs @@ -0,0 +1,50 @@ +using Godot; + +/// +/// 高速子弹 +/// +public class HighSpeedBullet : Bullet +{ + //射线检测节点 + 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()) { + //划线的点坐标 + Line.SetPointPosition(1, new Vector2(Line.GlobalPosition.DistanceTo(RayCast2D.GetCollisionPoint()), 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 new file mode 100644 index 0000000..8f224e8 --- /dev/null +++ b/src/weapon/gun/Gun.cs @@ -0,0 +1,265 @@ +using Godot; +using System; + +/// +/// 枪的基类 +/// +public 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 Sprite { 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 PackedScene bulletPacked; + + public override void _EnterTree() + { + Sprite = GetNode("Sprite"); + 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) + { + Attribute = attribute; + //更新图片 + var texture = ResourceLoader.Load(attribute.Sprite); + Sprite.Texture = texture; + //子弹 + bulletPacked = ResourceLoader.Load(attribute.Bullet); + //开火位置 + FirePoint.Position = new Vector2(attribute.BarrelLength, FirePoint.Position.y); + } + + /// + /// 扳机函数, 调用即视为扣动扳机 + /// + public void Trigger() + { + //是否第一帧按下 + var justDown = downTimer == 0; + + if ((Attribute.ContinuousShoot || (justDown && triggerTimer <= 0)) && continuousCount <= 0) + { + if (justDown) + { + //开火前延时 + delayedTime = Attribute.DelayedTime; + //扳机按下间隔 + triggerTimer += Attribute.TriggerInterval; + //连发数量 + if (!Attribute.ContinuousShoot) + { + continuousCount = Attribute.MinContinuousCount; + } + } + if (delayedTime <= 0 && attackTimer <= 0) + { + TriggernFire(); + } + attackFlag = true; + } + triggerFlag = true; + } + + /// + /// 刚按下扳机 + /// + private void DownTrigger() + { + + } + + /// + /// 刚松开扳机 + /// + private void UpTriggern() + { + + } + + private void TriggernFire() + { + continuousCount = continuousCount > 0 ? continuousCount - 1 : 0; + fireInterval = 60 / Attribute.FiringSpeed; + attackTimer += fireInterval; + Fire(); + //当前的散射半径 + 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 virtual void 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); + + //创建子弹 + 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); + } + } + + public 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/gun/GunAttribute.cs b/src/weapon/gun/GunAttribute.cs new file mode 100644 index 0000000..df608a5 --- /dev/null +++ b/src/weapon/gun/GunAttribute.cs @@ -0,0 +1,97 @@ +using Godot; + +/// +/// 枪上的属性 +/// +public class GunAttribute +{ + /// + /// 子弹对象 + /// + public string Bullet = "res://prefab/Bullet.tscn"; + /// + /// 枪的图片 + /// + public string Sprite = "res://resource/sprite/gun/gun1.png"; + /// + /// 是否连续发射, 如果为false, 则每次发射都需要扣动扳机 + /// + public bool ContinuousShoot = true; + /// + /// 连续发射最小次数, 仅当ContinuousShoot为false时生效 + /// + public int MinContinuousCount = 3; + /// + /// 连续发射最大次数, 仅当ContinuousShoot为false时生效 + /// + public int MaxContinuousCount = 3; + /// + /// 按下一次扳机后需要多长时间才能再次按下 + /// + public float TriggerInterval = 0; + /// + /// 射速, 每秒分钟能发射多少发子弹 + /// + public float FiringSpeed = 300; + /// + /// 单次开火发射子弹最小数量 + /// + 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 float BarrelLength = 11; + /// + /// 重量 + /// + public float Weight = 11; + /// + /// 最大后坐力 (仅用于开火后枪身抖动) + /// + public float MaxBacklash = 4; + /// + /// 最小后坐力 (仅用于开火后枪身抖动) + /// + public float MinBacklash = 2; + /// + /// 开火后枪口上抬角度 + /// + public float UpliftAngle = 30; + + public GunAttribute() + { + + } +} \ No newline at end of file