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
/// 根据给定的物品,匹配可放置它的物品槽