diff --git a/prefab/weapon/Gun.tscn b/prefab/weapon/Gun.tscn index 380fbda..0a3f551 100644 --- a/prefab/weapon/Gun.tscn +++ b/prefab/weapon/Gun.tscn @@ -1,9 +1,7 @@ -[gd_scene load_steps=6 format=2] +[gd_scene load_steps=4 format=2] [ext_resource path="res://src/weapon/gun/OrdinaryGun.cs" type="Script" id=1] -[ext_resource path="res://prefab/weapon/bullet/OrdinaryBullets.tscn" type="PackedScene" id=2] [ext_resource path="res://resource/sprite/gun/gun1.png" type="Texture" id=3] -[ext_resource path="res://prefab/weapon/shell/ShellCase.tscn" type="PackedScene" id=4] [sub_resource type="RectangleShape2D" id=1] extents = Vector2( 9.5, 3.5 ) @@ -11,8 +9,6 @@ [node name="Gun" type="Node2D"] z_index = 5 script = ExtResource( 1 ) -bulletPacked = ExtResource( 2 ) -shell = ExtResource( 4 ) [node name="GunSprite" type="Sprite" parent="."] position = Vector2( 4, -3 ) diff --git a/src/common/MathUtils.cs b/src/common/MathUtils.cs deleted file mode 100644 index 9c6033a..0000000 --- a/src/common/MathUtils.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Godot; - -public static class MathUtils -{ - /// - /// 返回一个区间内的随机小数 - /// - public static float RandRange(float min, float max) - { - if (min == max) return min; - if (min > max) - return GD.Randf() * (min - max) + max; - return GD.Randf() * (max - min) + min; - } - - /// - /// 返回一个区间内的随机整数 - /// - public static int RandRangeInt(int min, int max) - { - if (min == max) return min; - if (min > max) - return Mathf.FloorToInt(GD.Randf() * (min - max + 1) + max); - return Mathf.FloorToInt(GD.Randf() * (max - min + 1) + min); - } -} \ No newline at end of file diff --git a/src/common/ResourceManager.cs b/src/common/ResourceManager.cs deleted file mode 100644 index eb7eb3d..0000000 --- a/src/common/ResourceManager.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Godot; - -public static class ResourceManager -{ - - /// - /// 2D阴影的材质 - /// - public static ShaderMaterial ShadowMaterial - { - get - { - if (_shadowMaterial == null) - { - _shadowMaterial = ResourceLoader.Load("res://resource/materlal/Shadow.tres"); - } - return _shadowMaterial; - } - } - private static ShaderMaterial _shadowMaterial; - -} \ No newline at end of file diff --git a/src/common/ThrowNode.cs b/src/common/ThrowNode.cs deleted file mode 100644 index 2d22955..0000000 --- a/src/common/ThrowNode.cs +++ /dev/null @@ -1,183 +0,0 @@ -using System; -using Godot; - -/// -/// 模拟抛出的物体, 使用时将对象挂载到该节点上即可 -/// -public class ThrowNode : KinematicBody2D -{ - /// - /// 是否已经结束 - /// - /// - public bool IsOver { get; protected set; } = true; - /// - /// 物体大小 - /// - public Vector2 Size { get; protected set; } - /// - /// 起始坐标 - /// - public Vector2 StartPosition { get; protected set; } - /// - /// 移动方向, 0 - 360 - /// - /// - public float Direction { get; protected set; } - /// - /// x速度, 也就是水平速度 - /// - public float XSpeed { get; protected set; } - /// - /// y轴速度, 也就是竖直速度 - /// - /// - public float YSpeed { get; protected set; } - /// - /// 初始x轴组队 - /// - /// - public float StartXSpeed { get; protected set; } - /// - /// 初始y轴速度 - /// - public float StartYSpeed { get; protected set; } - /// - /// 旋转速度 - /// - public float RotateSpeed { get; protected set; } - /// - /// 挂载的对象 - /// - public Node2D Mount { get; protected set; } - /// - /// 碰撞组件 - /// - /// - public CollisionShape2D CollisionShape { get; protected set; } - /// - /// 绘制阴影的精灵 - /// - public Sprite ShadowSprite { get; protected set; } - - public override void _Ready() - { - //只与墙壁碰撞 - CollisionMask = 1; - CollisionLayer = 0; - //创建碰撞器 - CollisionShape = new CollisionShape2D(); - var shape = new RectangleShape2D(); - shape.Extents = Size * 0.5f; - CollisionShape.Shape = shape; - AddChild(CollisionShape); - - - } - - /// - /// 初始化该抛物线对象的基础数据 - /// - /// 抛射的物体所占大小, 用于碰撞检测 - /// 起始点 - /// 起始高度 - /// 角度, 0 - 360 - /// 横轴速度 - /// 纵轴速度 - /// 旋转速度 - /// 需要挂载的节点 - /// 抛射的节点显示的纹理, 用于渲染阴影用 - public void InitThrow(Vector2 size, Vector2 start, float startHeight, float direction, float xSpeed, float ySpeed, float rotate, Node2D mount) - { - IsOver = false; - Size = size; - GlobalPosition = StartPosition = start; - Direction = direction; - XSpeed = xSpeed; - YSpeed = ySpeed; - StartXSpeed = xSpeed; - StartYSpeed = ySpeed; - RotateSpeed = rotate; - - if (mount != null) - { - Mount = mount; - AddChild(mount); - mount.Position = new Vector2(0, -startHeight); - } - } - - /// - /// 初始化该抛物线对象的基础数据, 并且渲染阴影 - /// - /// 抛射的物体所占大小, 用于碰撞检测 - /// 起始点 - /// 起始高度 - /// 角度, 0 - 360 - /// 横轴速度 - /// 纵轴速度 - /// 旋转速度 - /// 需要挂载的节点 - /// 抛射的节点显示的纹理, 用于渲染阴影用 - public void InitThrow(Vector2 size, Vector2 start, float startHeight, float direction, float xSpeed, float ySpeed, float rotate, Node2D mount, Texture texutre) - { - InitThrow(size, start, startHeight, direction, xSpeed, ySpeed, rotate, mount); - if (texutre != null) - { - if (ShadowSprite == null) - { - //阴影 - ShadowSprite = new Sprite(); - ShadowSprite.ZIndex = -1; - ShadowSprite.Material = ResourceManager.ShadowMaterial; - ShadowSprite.Position = new Vector2(0, 1); - AddChild(ShadowSprite); - } - ShadowSprite.Texture = texutre; - } - else if (ShadowSprite != null) - { - ShadowSprite.Texture = null; - } - } - - /// - /// 初始化时调用 - /// - protected virtual void OnInit() - { - - } - - /// - /// 结束的调用 - /// - protected virtual void OnOver() - { - - } - - public override void _Process(float delta) - { - if (!IsOver) - { - MoveAndSlide(new Vector2(XSpeed, 0).Rotated(Direction * Mathf.Pi / 180)); - Mount.Position = new Vector2(0, Mount.Position.y - YSpeed * delta); - var rotate = Mount.GlobalRotationDegrees + RotateSpeed * delta; - Mount.GlobalRotationDegrees = rotate; - if (ShadowSprite != null) - { - ShadowSprite.GlobalRotationDegrees = rotate; - } - YSpeed -= GameConfig.G * delta; - - if (Mount.Position.y >= 0) - { - Mount.Position = new Vector2(0, 0); - IsOver = true; - OnOver(); - } - } - } - -} \ No newline at end of file diff --git a/src/effect/ThrowNode.cs b/src/effect/ThrowNode.cs new file mode 100644 index 0000000..2d22955 --- /dev/null +++ b/src/effect/ThrowNode.cs @@ -0,0 +1,183 @@ +using System; +using Godot; + +/// +/// 模拟抛出的物体, 使用时将对象挂载到该节点上即可 +/// +public class ThrowNode : KinematicBody2D +{ + /// + /// 是否已经结束 + /// + /// + public bool IsOver { get; protected set; } = true; + /// + /// 物体大小 + /// + public Vector2 Size { get; protected set; } + /// + /// 起始坐标 + /// + public Vector2 StartPosition { get; protected set; } + /// + /// 移动方向, 0 - 360 + /// + /// + public float Direction { get; protected set; } + /// + /// x速度, 也就是水平速度 + /// + public float XSpeed { get; protected set; } + /// + /// y轴速度, 也就是竖直速度 + /// + /// + public float YSpeed { get; protected set; } + /// + /// 初始x轴组队 + /// + /// + public float StartXSpeed { get; protected set; } + /// + /// 初始y轴速度 + /// + public float StartYSpeed { get; protected set; } + /// + /// 旋转速度 + /// + public float RotateSpeed { get; protected set; } + /// + /// 挂载的对象 + /// + public Node2D Mount { get; protected set; } + /// + /// 碰撞组件 + /// + /// + public CollisionShape2D CollisionShape { get; protected set; } + /// + /// 绘制阴影的精灵 + /// + public Sprite ShadowSprite { get; protected set; } + + public override void _Ready() + { + //只与墙壁碰撞 + CollisionMask = 1; + CollisionLayer = 0; + //创建碰撞器 + CollisionShape = new CollisionShape2D(); + var shape = new RectangleShape2D(); + shape.Extents = Size * 0.5f; + CollisionShape.Shape = shape; + AddChild(CollisionShape); + + + } + + /// + /// 初始化该抛物线对象的基础数据 + /// + /// 抛射的物体所占大小, 用于碰撞检测 + /// 起始点 + /// 起始高度 + /// 角度, 0 - 360 + /// 横轴速度 + /// 纵轴速度 + /// 旋转速度 + /// 需要挂载的节点 + /// 抛射的节点显示的纹理, 用于渲染阴影用 + public void InitThrow(Vector2 size, Vector2 start, float startHeight, float direction, float xSpeed, float ySpeed, float rotate, Node2D mount) + { + IsOver = false; + Size = size; + GlobalPosition = StartPosition = start; + Direction = direction; + XSpeed = xSpeed; + YSpeed = ySpeed; + StartXSpeed = xSpeed; + StartYSpeed = ySpeed; + RotateSpeed = rotate; + + if (mount != null) + { + Mount = mount; + AddChild(mount); + mount.Position = new Vector2(0, -startHeight); + } + } + + /// + /// 初始化该抛物线对象的基础数据, 并且渲染阴影 + /// + /// 抛射的物体所占大小, 用于碰撞检测 + /// 起始点 + /// 起始高度 + /// 角度, 0 - 360 + /// 横轴速度 + /// 纵轴速度 + /// 旋转速度 + /// 需要挂载的节点 + /// 抛射的节点显示的纹理, 用于渲染阴影用 + public void InitThrow(Vector2 size, Vector2 start, float startHeight, float direction, float xSpeed, float ySpeed, float rotate, Node2D mount, Texture texutre) + { + InitThrow(size, start, startHeight, direction, xSpeed, ySpeed, rotate, mount); + if (texutre != null) + { + if (ShadowSprite == null) + { + //阴影 + ShadowSprite = new Sprite(); + ShadowSprite.ZIndex = -1; + ShadowSprite.Material = ResourceManager.ShadowMaterial; + ShadowSprite.Position = new Vector2(0, 1); + AddChild(ShadowSprite); + } + ShadowSprite.Texture = texutre; + } + else if (ShadowSprite != null) + { + ShadowSprite.Texture = null; + } + } + + /// + /// 初始化时调用 + /// + protected virtual void OnInit() + { + + } + + /// + /// 结束的调用 + /// + protected virtual void OnOver() + { + + } + + public override void _Process(float delta) + { + if (!IsOver) + { + MoveAndSlide(new Vector2(XSpeed, 0).Rotated(Direction * Mathf.Pi / 180)); + Mount.Position = new Vector2(0, Mount.Position.y - YSpeed * delta); + var rotate = Mount.GlobalRotationDegrees + RotateSpeed * delta; + Mount.GlobalRotationDegrees = rotate; + if (ShadowSprite != null) + { + ShadowSprite.GlobalRotationDegrees = rotate; + } + YSpeed -= GameConfig.G * delta; + + if (Mount.Position.y >= 0) + { + Mount.Position = new Vector2(0, 0); + IsOver = true; + OnOver(); + } + } + } + +} \ No newline at end of file diff --git a/src/manager/ResourceManager.cs b/src/manager/ResourceManager.cs new file mode 100644 index 0000000..ef98c0a --- /dev/null +++ b/src/manager/ResourceManager.cs @@ -0,0 +1,60 @@ +using System.Collections.Generic; +using Godot; + +public static class ResourceManager +{ + + /// + /// 2D阴影的材质 + /// + public static ShaderMaterial ShadowMaterial + { + get + { + if (_shadowMaterial == null) + { + _shadowMaterial = ResourceLoader.Load("res://resource/materlal/Shadow.tres"); + } + return _shadowMaterial; + } + } + private static ShaderMaterial _shadowMaterial; + + private static readonly Dictionary CachePack = new Dictionary(); + + /// + /// 加载资源对象, 并且缓存当前资源对象, 可频繁获取 + /// + /// 资源路径 + public static T Load(string path) where T : class + { + if (CachePack.TryGetValue(path, out var pack)) + { + return (T)pack; + } + else + { + pack = ResourceLoader.Load(path); + if (pack != null) + { + CachePack.Add(path, pack); + return (T)pack; + } + } + return default(T); + } + + /// + /// 加载并实例化一个武器对象 + /// + /// 资源路径 + public static Gun LoadGunAndInstance(string path) + { + var pack = Load(path); + if (pack != null) { + return pack.Instance(); + } + return null; + } + +} \ No newline at end of file diff --git a/src/package/Holster.cs b/src/package/Holster.cs index acd5ef6..e9b517b 100644 --- a/src/package/Holster.cs +++ b/src/package/Holster.cs @@ -57,10 +57,10 @@ } /// - /// 拾起武器, 存入枪套中, 如果容不下这把武器, 则会返回 false + /// 拾起武器, 存入枪套中, 返回存放在枪套的位置, 如果容不下这把武器, 则会返回 -1 /// /// 武器对象 - public bool PickupGun(Gun gun) + public int PickupGun(Gun gun) { for (int i = 0; i < SlotList.Length; i++) { @@ -70,11 +70,11 @@ item.Gun = gun; ActiveGun = gun; ActiveIndex = i; - return true; + return i; } } GD.PrintErr("存入武器失败!"); - return false; + return -1; } /// @@ -92,4 +92,18 @@ { } + + /// + /// 切换到指定索引的武器 + /// + public bool ExchangeByIndex(int index) + { + if (index > SlotList.Length) return false; + var slot = SlotList[index]; + if (slot == null || slot.Gun == null) return false; + Master.MountPoint.AddChild(slot.Gun); + ActiveGun = slot.Gun; + ActiveIndex = index; + return true; + } } diff --git a/src/role/Player.cs b/src/role/Player.cs index 367502e..547227a 100644 --- a/src/role/Player.cs +++ b/src/role/Player.cs @@ -28,11 +28,8 @@ { base._Ready(); - - var gun = GunManager.GetGun1(); - MountPoint.AddChild(gun); - gun.FireEvent += FireEvent_Func; - Holster.PickupGun(gun); + PickUpGun(GunManager.GetGun1()); + PickUpGun(GunManager.GetGun2()); } public override void _Process(float delta) @@ -109,10 +106,4 @@ AnimatedSprite.Animation = AnimatorNames.Idle; } } - - //开火后 - private void FireEvent_Func(Gun gun) - { - - } } \ No newline at end of file diff --git a/src/role/Role.cs b/src/role/Role.cs index 335b3df..567a06c 100644 --- a/src/role/Role.cs +++ b/src/role/Role.cs @@ -40,9 +40,9 @@ /// public Holster Holster { get; private set; } - /// - /// 动画播放器 - /// + /// + /// 动画播放器 + /// public AnimatedSprite AnimatedSprite { get; private set; } /// /// 武器挂载点 @@ -66,11 +66,36 @@ ChangeFrameTexture(AnimatorNames.Idle, AnimatedSprite, Texture); ChangeFrameTexture(AnimatorNames.Run, AnimatedSprite, Texture); ChangeFrameTexture(AnimatorNames.ReverseRun, AnimatedSprite, Texture); - + Holster = new Holster(this); Face = FaceDirection.Right; } + /// + /// 拾起一个武器, 并且切换到这个武器 + /// + /// 武器对象 + public void PickUpGun(Gun gun) + { + var index = Holster.PickupGun(gun); + SetActiveGun(index); + } + + public void ExchangeNext() + { + Holster.ExchangeNext(); + } + + private void SetActiveGun(int index) + { + if (Holster.ActiveGun != null) + { + Holster.ActiveGun.Visible = false; + } + Holster.ExchangeByIndex(index); + Holster.ActiveGun.Visible = true; + } + private void SetFace(FaceDirection face) { if (_face != face) diff --git a/src/utils/MathUtils.cs b/src/utils/MathUtils.cs new file mode 100644 index 0000000..9c6033a --- /dev/null +++ b/src/utils/MathUtils.cs @@ -0,0 +1,26 @@ +using Godot; + +public static class MathUtils +{ + /// + /// 返回一个区间内的随机小数 + /// + public static float RandRange(float min, float max) + { + if (min == max) return min; + if (min > max) + return GD.Randf() * (min - max) + max; + return GD.Randf() * (max - min) + min; + } + + /// + /// 返回一个区间内的随机整数 + /// + public static int RandRangeInt(int min, int max) + { + if (min == max) return min; + if (min > max) + return Mathf.FloorToInt(GD.Randf() * (min - max + 1) + max); + return Mathf.FloorToInt(GD.Randf() * (max - min + 1) + min); + } +} \ No newline at end of file diff --git a/src/weapon/gun/Gun.cs b/src/weapon/gun/Gun.cs index 8cb5429..15e154e 100644 --- a/src/weapon/gun/Gun.cs +++ b/src/weapon/gun/Gun.cs @@ -163,8 +163,7 @@ Attribute = attribute; //更新图片 - var texture = ResourceLoader.Load(attribute.Sprite); - GunSprite.Texture = texture; + GunSprite.Texture = attribute.Sprite; //开火位置 FirePoint.Position = new Vector2(attribute.FirePosition.x, -attribute.FirePosition.y); OriginPoint.Position = new Vector2(0, -attribute.FirePosition.y); @@ -312,6 +311,17 @@ protected abstract void ShootBullet(); /// + /// 当武器被拾起时调用 + /// + /// 拾起该武器的角色 + protected abstract void OnPickUp(Role master); + + /// + /// 当武器被扔掉时调用 + /// + protected abstract void OnThrowOut(); + + /// /// 实例化并返回子弹对象 /// /// 子弹的预制体 diff --git a/src/weapon/gun/GunAttribute.cs b/src/weapon/gun/GunAttribute.cs index 38a338d..b69c394 100644 --- a/src/weapon/gun/GunAttribute.cs +++ b/src/weapon/gun/GunAttribute.cs @@ -12,7 +12,15 @@ /// /// 枪的图片 /// - public string Sprite = "res://resource/sprite/gun/gun1.png"; + public Texture Sprite; + /// + /// 子弹预制体 + /// + public PackedScene BulletPack; + /// + /// 弹壳预制体 + /// + public PackedScene ShellPack; /// /// 是否连续发射, 如果为false, 则每次发射都需要扣动扳机 /// diff --git a/src/weapon/gun/GunManager.cs b/src/weapon/gun/GunManager.cs index 1000652..ff7784d 100644 --- a/src/weapon/gun/GunManager.cs +++ b/src/weapon/gun/GunManager.cs @@ -4,36 +4,10 @@ public static class GunManager { - private static readonly Dictionary CacheGunPack = new Dictionary(); - - /// - /// 加载武器预制体, - /// 路径位于res://prefab/weapon/下 - /// - /// 资源路径 - public static Gun LoadGun(string path) - { - path = "res://prefab/weapon/" + path; - if (CacheGunPack.TryGetValue(path, out var pack)) - { - return pack.Instance(); - } - else - { - pack = ResourceLoader.Load(path); - if (pack != null) - { - CacheGunPack.Add(path, pack); - return pack.Instance(); - } - } - return null; - } - public static Gun GetGun1() { //加载枪的 prefab - var gun = LoadGun("Gun.tscn"); + var gun = ResourceManager.LoadGunAndInstance("res://prefab/weapon/Gun.tscn"); //设置基础属性 var attr = new GunAttribute(); attr.StartFiringSpeed = 480; @@ -60,7 +34,47 @@ attr.UpliftAngle = 10; //枪身长度 attr.FirePosition = new Vector2(16, 1.5f); - attr.Sprite = "res://resource/sprite/gun/gun4.png"; + 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.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; } diff --git a/src/weapon/gun/OrdinaryGun.cs b/src/weapon/gun/OrdinaryGun.cs index fa39413..3ced390 100644 --- a/src/weapon/gun/OrdinaryGun.cs +++ b/src/weapon/gun/OrdinaryGun.cs @@ -1,3 +1,4 @@ +using System; using Godot; @@ -6,11 +7,6 @@ /// public class OrdinaryGun : Gun { - - [Export] public PackedScene bulletPacked; - - [Export] public PackedScene shell; - protected override void Init() { @@ -26,7 +22,7 @@ var xf = MathUtils.RandRangeInt(20, 60); var yf = MathUtils.RandRangeInt(60, 120); var rotate = MathUtils.RandRangeInt(-720, 720); - var sprite = shell.Instance(); + var sprite = Attribute.ShellPack.Instance(); temp.InitThrow(new Vector2(5, 10), startPos, startHeight, direction, xf, yf, rotate, sprite, sprite.Texture); RoomManager.Current.ItemRoot.AddChild(temp); } @@ -34,6 +30,17 @@ protected override void ShootBullet() { //创建子弹 - CreateBullet(bulletPacked, FirePoint.GlobalPosition, (FirePoint.GlobalPosition - OriginPoint.GlobalPosition).Angle()); + CreateBullet(Attribute.BulletPack, FirePoint.GlobalPosition, (FirePoint.GlobalPosition - OriginPoint.GlobalPosition).Angle()); } + + protected override void OnPickUp(Role master) + { + + } + + protected override void OnThrowOut() + { + + } + } \ No newline at end of file