diff --git a/scripts/character/CharacterTemplate.cs b/scripts/character/CharacterTemplate.cs index 019b65a..f7d2830 100644 --- a/scripts/character/CharacterTemplate.cs +++ b/scripts/character/CharacterTemplate.cs @@ -29,6 +29,9 @@ public partial class CharacterTemplate : CharacterBody2D protected const float JumpVelocity = -240; + //物品被扔出后多长时间恢复与地面和平台的碰撞(单位:秒) + private readonly double _itemCollisionRecoveryTime = 0.045f; + public string? ReadOnlyCharacterName => CharacterName; protected string? CharacterName; @@ -264,12 +267,12 @@ public partial class CharacterTemplate : CharacterBody2D { return false; } - + if (_itemContainer == null) { return false; } - + //Get the currently selected node //拿到当前选择的节点 var itemSlotNode = _itemContainer.GetSelectItemSlotNode(); @@ -525,6 +528,86 @@ public partial class CharacterTemplate : CharacterBody2D _animatedSprite2D.FlipH = FacingLeft; } + /// + /// Throw item + /// 抛出物品 + /// + /// + ///Item slot subscript in item container + ///物品容器内的物品槽下标 + /// + /// + /// How many to throw + /// 要扔几个 + /// + /// + ///The speed to be applied to the item + ///要施加到物品上的速度 + /// + protected void ThrowItem(int index, int number, Vector2 velocity) + { + if (_itemContainer == null) + { + return; + } + + var itemSlotNode = _itemContainer.GetItemSlotNode(index); + if (itemSlotNode == null) + { + return; + } + + var item = itemSlotNode.GetItem(); + if (item == null) + { + return; + } + + switch (item) + { + case WeaponTemplate weaponTemplate: + if (GameSceneNodeHolder.WeaponContainer == null) + { + return; + } + + weaponTemplate.Reparent(GameSceneNodeHolder.WeaponContainer); + var timer = new Timer(); + weaponTemplate.AddChild(timer); + timer.WaitTime = _itemCollisionRecoveryTime; + timer.OneShot = true; + timer.Timeout += () => + { + //We cannot immediately resume the physical collision when the weapon is discharged, which will cause the weapon to collide with the ground and platform earlier, preventing the weapon from flying. + //仍出武器时,我们不能立即恢复物理碰撞,立即恢复会导致武器更早的与地面和平台碰撞,阻止武器的飞行。 + weaponTemplate.EnableContactInjury = true; + weaponTemplate.SetCollisionMaskValue(Config.LayerNumber.Ground, true); + weaponTemplate.SetCollisionMaskValue(Config.LayerNumber.Platform, true); + timer.QueueFree(); + }; + timer.Start(); + weaponTemplate.Sleeping = false; + // weaponTemplate.LinearVelocity = Vector2.Zero; + break; + } + + //We apply force to objects. + //我们给物品施加力。 + switch (CurrentItem) + { + case CharacterBody2D characterBody2D: + characterBody2D.Velocity = velocity; + break; + case RigidBody2D rigidBody2D: + rigidBody2D.LinearVelocity = velocity; + break; + } + + //Remove items from the item container + //在物品容器内移除物品 + itemSlotNode.RemoveItem(number); + } + public sealed override void _PhysicsProcess(double delta) { diff --git a/scripts/character/Player.cs b/scripts/character/Player.cs index a6c57fd..7070d94 100644 --- a/scripts/character/Player.cs +++ b/scripts/character/Player.cs @@ -43,9 +43,6 @@ public partial class Player : CharacterTemplate //角色从平台上跳下后,多少时间后恢复与平台的碰撞(单位:秒) private double _platformCollisionRecoveryTime = 0.2f; - //物品被扔出后多长时间恢复与地面和平台的碰撞(单位:秒) - private readonly double _itemCollisionRecoveryTime = 0.045f; - public override void _Ready() { @@ -255,7 +252,7 @@ public partial class Player : CharacterTemplate //抬起手时,抛出物品 if (Input.IsActionJustReleased("throw")) { - if (CurrentItem == null) + if (ItemContainer == null) { return; } @@ -265,46 +262,8 @@ public partial class Player : CharacterTemplate _parabola.Points = new[] { Vector2.Zero }; } - CurrentItem.Reparent(GameSceneNodeHolder.WeaponContainer); - switch (CurrentItem) - { - case WeaponTemplate weaponTemplate: - { - var timer = new Timer(); - weaponTemplate.AddChild(timer); - timer.WaitTime = _itemCollisionRecoveryTime; - timer.OneShot = true; - timer.Timeout += () => - { - //We cannot immediately resume the physical collision when the weapon is discharged, which will cause the weapon to collide with the ground and platform earlier, preventing the weapon from flying. - //仍出武器时,我们不能立即恢复物理碰撞,立即恢复会导致武器更早的与地面和平台碰撞,阻止武器的飞行。 - weaponTemplate.EnableContactInjury = true; - weaponTemplate.SetCollisionMaskValue(Config.LayerNumber.Ground, true); - weaponTemplate.SetCollisionMaskValue(Config.LayerNumber.Platform, true); - timer.QueueFree(); - }; - timer.Start(); - weaponTemplate.Sleeping = false; - weaponTemplate.LinearVelocity = Vector2.Zero; - break; - } - } - - //We apply force to objects. - //我们给物品施加力。 - switch (CurrentItem) - { - case CharacterBody2D characterBody2D: - characterBody2D.Velocity = GetThrowVelocity(); - break; - case RigidBody2D rigidBody2D: - rigidBody2D.LinearVelocity = GetThrowVelocity(); - break; - } - + ThrowItem(ItemContainer.GetSelectIndex(), 1, GetThrowVelocity()); CurrentItem = null; - var hotBar = GameSceneNodeHolder.HotBar; - hotBar?.RemoveItemFromItemSlotBySelectIndex(1); } } @@ -313,6 +272,10 @@ public partial class Player : CharacterTemplate UpdateOperationTip(); } + /// + /// 当玩家手动抛出物品时,施加到物品上的速度值 + /// + /// private Vector2 GetThrowVelocity() { //We take the mouse position, normalize it, and then multiply it by the distance the player can throw @@ -382,7 +345,7 @@ public partial class Player : CharacterTemplate { base.Revive(newHp); var healthBarUi = GameSceneNodeHolder.HealthBarUi; - if (healthBarUi!=null) + if (healthBarUi != null) { //The purpose of setting Hp to the current Hp is to cause the life bar to refresh. //将Hp设置为当前Hp的目的是,使生命条刷新。 diff --git a/scripts/inventory/HotBar.cs b/scripts/inventory/HotBar.cs index 6dff720..cc2fa91 100644 --- a/scripts/inventory/HotBar.cs +++ b/scripts/inventory/HotBar.cs @@ -14,6 +14,12 @@ public partial class HotBar : HBoxContainer, IItemContainer private List? _itemSlotNodes; + /// + /// UnknownIndex + /// 未知位置 + /// + private const int UnknownIndex = -1; + //_selectIndex默认为0. private int _selectIndex; @@ -160,17 +166,14 @@ public partial class HotBar : HBoxContainer, IItemContainer return; } - var count = _itemSlotNodes.Count; - if (count == 0) + var safeIndex = GetSafeIndex(shortcutKeyIndex); + if (safeIndex == UnknownIndex) { - //Prevents the dividend from being 0 - //防止被除数为0 return; } - var newIndex = shortcutKeyIndex % count; - SelectItemSlot(_selectIndex, newIndex); - _selectIndex = newIndex; + SelectItemSlot(_selectIndex, safeIndex); + _selectIndex = safeIndex; } @@ -185,6 +188,27 @@ public partial class HotBar : HBoxContainer, IItemContainer return RemoveItemFromItemSlot(_selectIndex, number); } + public int GetItemSlotCount() + { + if (_itemSlotNodes == null) + { + return 0; + } + + return _itemSlotNodes.Count; + } + + public ItemSlotNode? GetItemSlotNode(int index) + { + if (_itemSlotNodes == null) + { + return null; + } + + var safeIndex = GetSafeIndex(index); + return _itemSlotNodes[safeIndex]; + } + /// /// Remove items from the item slot /// 从物品槽内移除物品 @@ -204,17 +228,41 @@ public partial class HotBar : HBoxContainer, IItemContainer return false; } + var safeIndex = GetSafeIndex(itemSlotIndex); + if (safeIndex == UnknownIndex) + { + return false; + } + + var itemSlot = _itemSlotNodes[safeIndex]; + return itemSlot.RemoveItem(number); + } + + /// + /// Gets a secure subscript index + /// 获取安全的下标索引 + /// + /// + /// + ///-1 is returned on failure, and the index that does not result in an out-of-bounds subscript is returned on success + ///失败返回-1,成功返回不会导致下标越界的索引 + /// + private int GetSafeIndex(int itemSlotIndex) + { + if (_itemSlotNodes == null) + { + return UnknownIndex; + } + var count = _itemSlotNodes.Count; if (count == 0) { //Prevents the dividend from being 0 //防止被除数为0 - return false; + return UnknownIndex; } - var newIndex = itemSlotIndex % count; - var itemSlot = _itemSlotNodes[newIndex]; - return itemSlot.RemoveItem(number); + return itemSlotIndex % count; } /// @@ -294,6 +342,11 @@ public partial class HotBar : HBoxContainer, IItemContainer return itemSlotNode.SetItem(item); } + public int GetSelectIndex() + { + return _selectIndex; + } + public ItemSlotNode? GetSelectItemSlotNode() { if (_itemSlotNodes == null || _itemSlotNodes.Count == 0) diff --git a/scripts/inventory/IItemContainer.cs b/scripts/inventory/IItemContainer.cs index 01d2bff..c275c7d 100644 --- a/scripts/inventory/IItemContainer.cs +++ b/scripts/inventory/IItemContainer.cs @@ -26,6 +26,13 @@ public interface IItemContainer /// bool AddItem(IItem item); + /// + /// Gets the selected location + /// 获取选中的位置 + /// + /// + int GetSelectIndex(); + /// /// Gets the currently selected node /// 获取当前选中的节点 @@ -33,6 +40,38 @@ public interface IItemContainer /// ItemSlotNode? GetSelectItemSlotNode(); + /// + /// Removes an item from the inventory at the currently selected location + /// 移除当前选中位置物品栏内的物品 + /// + /// + /// + bool RemoveItemFromItemSlotBySelectIndex(int number); + + /// + /// Gets the number of item slots + /// 获取物品槽的数量 + /// + /// + int GetItemSlotCount(); + + /// + /// Gets the item slot for the specified location + /// 获取指定位置的物品槽 + /// + /// + /// + ItemSlotNode? GetItemSlotNode(int index); + + /// + /// Removes an item from the item slot in the specified location + /// 在指定位置的物品槽内移除物品 + /// + /// + /// + /// + bool RemoveItemFromItemSlot(int itemSlotIndex, int number); + /// /// Based on the given item, match the item slots where it can be placed /// 根据给定的物品,匹配可放置它的物品槽