diff --git a/DungeonShooting_Godot/src/framework/ActivityObject.cs b/DungeonShooting_Godot/src/framework/ActivityObject.cs index 98a79b6..30022c1 100644 --- a/DungeonShooting_Godot/src/framework/ActivityObject.cs +++ b/DungeonShooting_Godot/src/framework/ActivityObject.cs @@ -147,28 +147,66 @@ /// /// 投抛该物体达到最高点时调用 /// - public virtual void OnMaxHeight(float height) + public virtual void OnThrowMaxHeight(float height) { } - public virtual void PickUp() + /// + /// 投抛状态下第一次接触地面时调用, 之后的回弹落地将不会调用该函数 + /// + public virtual void OnFirstFallToGround() { } - public virtual void PickDown() + /// + /// 投抛状态下每次接触地面时调用 + /// + public virtual void OnFallToGround() { } + /// + /// 投抛结束时调用 + /// + public virtual void OnThrowOver() + { + + } + + public void PickUp() + { + + } + + public void PickDown() + { + + } + + /// + /// 将该节点投抛出去 + /// + /// 碰撞器大小 + /// 起始坐标 (全局) + /// 起始高度 + /// 投抛角度 (0-360) + /// 移动速度 + /// 下坠速度 + /// 旋转速度 + /// 落地时是否回弹 + /// 落地回弹力度, 1为不消耗能量, 值越小回弹力度越小 + /// 落地回弹后的速度, 1为不消速度, 值越小回弹速度消耗越大 public void Throw(Vector2 size, Vector2 start, float startHeight, float direction, float xSpeed, - float ySpeed, float rotate) + float ySpeed, float rotate, bool bounce = false, float bounceStrength = 0.5f, float bounceSpeed = 0.8f) { if (_throwData == null) { _throwData = new ObjectThrowData(); } + SetThrowCollision(); _throwData.IsOver = false; @@ -182,31 +220,15 @@ _throwData.RotateSpeed = rotate; _throwData.LinearVelocity = new Vector2(_throwData.XSpeed, 0).Rotated(_throwData.Direction * Mathf.Pi / 180); _throwData.Y = startHeight; + _throwData.Bounce = bounce; + _throwData.BounceStrength = bounceStrength; + _throwData.BounceSpeed = bounceSpeed; _throwData.RectangleShape.Extents = _throwData.Size * 0.5f; Throw(); } - private void Throw() - { - var parent = GetParent(); - if (parent == null) - { - RoomManager.Current.SortRoot.AddChild(this); - } - else if (parent == RoomManager.Current.ObjectRoot) - { - parent.RemoveChild(this); - RoomManager.Current.SortRoot.AddChild(this); - } - GlobalPosition = _throwData.StartPosition + new Vector2(0, -_throwData.Y); - - //显示阴影 - ShowShadowSprite(); - ShadowSprite.Scale = AnimatedSprite.Scale; - } - /// /// 强制停止投抛运动 /// @@ -216,39 +238,6 @@ RestoreCollision(); } - /// - /// 结束的调用 - /// - public void OnOver() - { - if (_throwData.FirstOver) - { - _throwData.FirstOver = false; - if (this is Weapon gun) - { - gun._FallToGround(); - } - } - //如果落地高度不够低, 再抛一次 - if (_throwData.StartYSpeed > 1) - { - _throwData.StartPosition = Position; - _throwData.Y = 0; - _throwData.XSpeed = _throwData.StartXSpeed = _throwData.StartXSpeed * 0.8f; - _throwData.YSpeed = _throwData.StartYSpeed = _throwData.StartYSpeed * 0.5f; - _throwData.RotateSpeed = _throwData.RotateSpeed * 0.5f; - _throwData.LinearVelocity = new Vector2(_throwData.XSpeed, 0).Rotated(_throwData.Direction * Mathf.Pi / 180); - _throwData.FirstOver = true; - _throwData.IsOver = false; - } - else //结束 - { - GetParent().RemoveChild(this); - RoomManager.Current.ObjectRoot.AddChild(this); - RestoreCollision(); - } - } - public void AddComponent(Component component) { if (!ContainsComponent(component)) @@ -314,14 +303,18 @@ //投抛计算 if (_throwData != null && !_throwData.IsOver) { - MoveAndSlide(_throwData.LinearVelocity); + _throwData.LinearVelocity = MoveAndSlide(_throwData.LinearVelocity); Position = new Vector2(Position.x, Position.y - _throwData.YSpeed * delta); var rotate = GlobalRotationDegrees + _throwData.RotateSpeed * delta; GlobalRotationDegrees = rotate; //计算阴影位置 + var pos = AnimatedSprite.GlobalPosition + new Vector2(0, 2 + _throwData.Y); ShadowSprite.GlobalRotationDegrees = rotate; - ShadowSprite.GlobalPosition = AnimatedSprite.GlobalPosition + new Vector2(0, 2 + _throwData.Y); + ShadowSprite.GlobalPosition = pos; + //碰撞器位置 + Collision.GlobalPosition = pos; + var ysp = _throwData.YSpeed; _throwData.Y += _throwData.YSpeed * delta; @@ -330,15 +323,44 @@ //达到最高点 if (ysp * _throwData.YSpeed < 0) { - OnMaxHeight(_throwData.Y); + ZIndex = 0; + OnThrowMaxHeight(_throwData.Y); } - + //落地判断 if (_throwData.Y <= 0) { ShadowSprite.GlobalPosition = AnimatedSprite.GlobalPosition + new Vector2(0, 2); _throwData.IsOver = true; - OnOver(); + + //第一次接触地面 + if (_throwData.FirstOver) + { + _throwData.FirstOver = false; + OnFirstFallToGround(); + } + + //如果落地高度不够低, 再抛一次 + if (_throwData.StartYSpeed > 1 && _throwData.Bounce) + { + _throwData.StartPosition = Position; + _throwData.Y = 0; + _throwData.XSpeed = _throwData.StartXSpeed = _throwData.StartXSpeed * _throwData.BounceSpeed; + _throwData.YSpeed = _throwData.StartYSpeed = _throwData.StartYSpeed * _throwData.BounceStrength; + _throwData.RotateSpeed = _throwData.RotateSpeed * _throwData.BounceStrength; + _throwData.LinearVelocity *= _throwData.BounceSpeed; + // _throwData.LinearVelocity = + // new Vector2(_throwData.XSpeed, 0).Rotated(_throwData.Direction * Mathf.Pi / 180); + _throwData.FirstOver = false; + _throwData.IsOver = false; + + OnFallToGround(); + } + else //结束 + { + OnFallToGround(); + ThrowOver(); + } } } @@ -408,6 +430,32 @@ return false; } + /// + /// 触发投抛动作 + /// + private void Throw() + { + var parent = GetParent(); + if (parent == null) + { + RoomManager.Current.SortRoot.AddChild(this); + } + else if (parent == RoomManager.Current.ObjectRoot) + { + parent.RemoveChild(this); + RoomManager.Current.SortRoot.AddChild(this); + } + + GlobalPosition = _throwData.StartPosition + new Vector2(0, -_throwData.Y); + + //显示阴影 + ShowShadowSprite(); + ShadowSprite.Scale = AnimatedSprite.Scale; + } + + /// + /// 设置投抛状态下的碰撞器 + /// private void SetThrowCollision() { if (_throwData != null && _throwData.UseOrigin) @@ -416,8 +464,13 @@ _throwData.OriginPosition = Collision.Position; _throwData.OriginRotation = Collision.Rotation; _throwData.OriginScale = Collision.Scale; - _throwData.OriginCollisionEnable = Collision.Disabled; _throwData.OriginZIndex = ZIndex; + _throwData.OriginCollisionEnable = Collision.Disabled; + _throwData.OriginCollisionPosition = Collision.Position; + _throwData.OriginCollisionRotation = Collision.Rotation; + _throwData.OriginCollisionScale = Collision.Scale; + _throwData.OriginCollisionMask = CollisionMask; + _throwData.OriginCollisionLayer = CollisionLayer; if (_throwData.RectangleShape == null) { @@ -428,12 +481,20 @@ //Collision.Position = Vector2.Zero; Collision.Rotation = 0; Collision.Scale = Vector2.One; - Collision.Disabled = false; - _throwData.UseOrigin = false; ZIndex = 2; + Collision.Disabled = false; + Collision.Position = Vector2.Zero; + Collision.Rotation = 0; + Collision.Scale = Vector2.One; + CollisionMask = 1; + CollisionLayer = 0; + _throwData.UseOrigin = false; } } + /// + /// 重置碰撞器 + /// private void RestoreCollision() { if (_throwData != null && !_throwData.UseOrigin) @@ -442,10 +503,27 @@ Collision.Position = _throwData.OriginPosition; Collision.Rotation = _throwData.OriginRotation; Collision.Scale = _throwData.OriginScale; - Collision.Disabled = _throwData.OriginCollisionEnable; ZIndex = _throwData.OriginZIndex; - + Collision.Disabled = _throwData.OriginCollisionEnable; + Collision.Position = _throwData.OriginCollisionPosition; + Collision.Rotation = _throwData.OriginCollisionRotation; + Collision.Scale = _throwData.OriginCollisionScale; + CollisionMask = _throwData.OriginCollisionMask; + CollisionLayer = _throwData.OriginCollisionLayer; + _throwData.UseOrigin = true; } } + + /// + /// 投抛结束 + /// + private void ThrowOver() + { + GetParent().RemoveChild(this); + RoomManager.Current.ObjectRoot.AddChild(this); + RestoreCollision(); + + OnThrowOver(); + } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/ObjectThrowData.cs b/DungeonShooting_Godot/src/framework/ObjectThrowData.cs index 7590dbd..21d31f3 100644 --- a/DungeonShooting_Godot/src/framework/ObjectThrowData.cs +++ b/DungeonShooting_Godot/src/framework/ObjectThrowData.cs @@ -5,7 +5,7 @@ /// /// 是否是第一次结束 /// - public bool FirstOver = false; + public bool FirstOver = true; /// /// 是否已经结束 @@ -57,6 +57,21 @@ /// public RectangleShape2D RectangleShape; + /// + /// 落地之后是否弹跳 + /// + public bool Bounce; + + /// + /// 回弹的强度 + /// + public float BounceStrength = 0.5f; + + /// + /// 回弹后的速度 + /// + public float BounceSpeed = 0.8f; + public Vector2 CurrPosition; public float Y; public Vector2 LinearVelocity; @@ -67,6 +82,11 @@ public Vector2 OriginPosition; public float OriginRotation; public Vector2 OriginScale; - public bool OriginCollisionEnable; public int OriginZIndex; + public bool OriginCollisionEnable; + public Vector2 OriginCollisionPosition; + public float OriginCollisionRotation; + public Vector2 OriginCollisionScale; + public uint OriginCollisionMask; + public uint OriginCollisionLayer; } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/common/NodeExtend.cs b/DungeonShooting_Godot/src/game/common/NodeExtend.cs index f3d9d2e..2d84709 100644 --- a/DungeonShooting_Godot/src/game/common/NodeExtend.cs +++ b/DungeonShooting_Godot/src/game/common/NodeExtend.cs @@ -68,27 +68,6 @@ } /// - /// 触发扔掉武器操作 - /// - /// 触发扔掉该武器的的角色 - public static void StartThrowWeapon(this Weapon weapon, Role master) - { - if (master.Face == FaceDirection.Left) - { - weapon.Scale *= new Vector2(1, -1); - weapon.RotationDegrees = 180; - } - var startHeight = 6; - var direction = master.GlobalRotationDegrees + MathUtils.RandRangeInt(-20, 20); - var xf = 30; - var yf = MathUtils.RandRangeInt(60, 120); - var rotate = MathUtils.RandRangeInt(-180, 180); - //weapon.Position = Vector2.Zero; - weapon.Throw(new Vector2(20, 20), master.MountPoint.GlobalPosition, startHeight, direction, xf, yf, rotate); - } - - - /// /// 尝试将一个node2d节点转换成一个 ActivityObject 类 /// public static ActivityObject AsActivityObject(this Node2D node2d) diff --git a/DungeonShooting_Godot/src/game/item/weapon/ThrowWeapon.cs b/DungeonShooting_Godot/src/game/item/weapon/ThrowWeapon.cs index 5286173..49ae0f7 100644 --- a/DungeonShooting_Godot/src/game/item/weapon/ThrowWeapon.cs +++ b/DungeonShooting_Godot/src/game/item/weapon/ThrowWeapon.cs @@ -20,7 +20,7 @@ fristOver = false; if (ActivityObject is Weapon gun) { - gun._FallToGround(); + } } //如果落地高度不够低, 再抛一次 diff --git a/DungeonShooting_Godot/src/game/item/weapon/Weapon.cs b/DungeonShooting_Godot/src/game/item/weapon/Weapon.cs index 2ded6cf..5d011d4 100644 --- a/DungeonShooting_Godot/src/game/item/weapon/Weapon.cs +++ b/DungeonShooting_Godot/src/game/item/weapon/Weapon.cs @@ -6,7 +6,6 @@ /// public abstract class Weapon : ActivityObject { - /// /// 武器的唯一id /// @@ -21,12 +20,7 @@ /// 属性数据 /// public WeaponAttribute Attribute { get; private set; } - - // /// - // /// 武器的图片 - // /// - //public Sprite WeaponSprite { get; private set; } - + /// /// 动画播放器 /// @@ -131,7 +125,6 @@ Id = id; Attribute = attribute; - //WeaponSprite = GetNode("WeaponBody/WeaponSprite"); FirePoint = GetNode("WeaponBody/FirePoint"); OriginPoint = GetNode("WeaponBody/OriginPoint"); ShellPoint = GetNode("WeaponBody/ShellPoint"); @@ -622,8 +615,9 @@ { if (master is Role roleMaster) //与role碰撞 { + var holster = roleMaster.Holster; //查找是否有同类型武器 - var index = roleMaster.Holster.FindWeapon(Id); + var index = holster.FindWeapon(Id); if (index != -1) //如果有这个武器 { if (CurrAmmo + ResidueAmmo == 0) //没有子弹了 @@ -631,7 +625,7 @@ return; } - var weapon = roleMaster.Holster.GetWeapon(index); + var weapon = holster.GetWeapon(index); //子弹上限 var maxCount = Attribute.MaxAmmoCapacity; //是否捡到子弹 @@ -666,13 +660,13 @@ } else //没有武器 { - if (roleMaster.Holster.PickupWeapon(this) == -1) + if (holster.PickupWeapon(this) == -1) { - var slot = roleMaster.Holster.SlotList[roleMaster.Holster.ActiveIndex]; + var slot = holster.SlotList[holster.ActiveIndex]; if (slot.Type == Attribute.WeightType) { - var weapon = roleMaster.Holster.RemoveWeapon(roleMaster.Holster.ActiveIndex); - weapon.StartThrowWeapon(roleMaster); + var weapon = holster.RemoveWeapon(holster.ActiveIndex); + weapon.TriggerThrowWeapon(roleMaster); roleMaster.PickUpWeapon(this); } } @@ -680,15 +674,26 @@ } } - public Vector2 GetItemPosition() - { - return GlobalPosition; - } - /// - /// 触发落到地面 + /// 触发扔掉武器操作 /// - public void _FallToGround() + /// 触发扔掉该武器的的角色 + public void TriggerThrowWeapon(Role master) + { + if (master.Face == FaceDirection.Left) + { + Scale *= new Vector2(1, -1); + RotationDegrees = 180; + } + var startHeight = 6; + var direction = master.GlobalRotationDegrees + MathUtils.RandRangeInt(-20, 20); + var xf = 30; + var yf = MathUtils.RandRangeInt(60, 120); + var rotate = MathUtils.RandRangeInt(-180, 180); + Throw(new Vector2(30, 15), master.MountPoint.GlobalPosition, startHeight, direction, xf, yf, rotate, true); + } + + public override void OnThrowOver() { //启用碰撞 CollisionShape2D.Disabled = false; diff --git a/DungeonShooting_Godot/src/game/role/Role.cs b/DungeonShooting_Godot/src/game/role/Role.cs index a19b0ec..85d5073 100644 --- a/DungeonShooting_Godot/src/game/role/Role.cs +++ b/DungeonShooting_Godot/src/game/role/Role.cs @@ -231,7 +231,7 @@ //播放抛出效果 if (weapon != null) { - weapon.StartThrowWeapon(this); + weapon.TriggerThrowWeapon(this); } }