Supports throwing items out of a specific item slot.
支持扔出特定物品槽内的物品了。
This commit is contained in:
parent
95515ddab2
commit
5ca995d689
|
@ -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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Throw item</para>
|
||||
/// <para>抛出物品</para>
|
||||
/// </summary>
|
||||
/// <param name="index">
|
||||
///<para>Item slot subscript in item container</para>
|
||||
///<para>物品容器内的物品槽下标</para>
|
||||
/// </param>
|
||||
/// <param name="number">
|
||||
/// <para>How many to throw</para>
|
||||
/// <para>要扔几个</para>
|
||||
/// </param>
|
||||
/// <param name="velocity">
|
||||
///<para>The speed to be applied to the item</para>
|
||||
///<para>要施加到物品上的速度</para>
|
||||
/// </param>
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>当玩家手动抛出物品时,施加到物品上的速度值</para>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
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的目的是,使生命条刷新。
|
||||
|
|
|
@ -14,6 +14,12 @@ public partial class HotBar : HBoxContainer, IItemContainer
|
|||
|
||||
private List<ItemSlotNode>? _itemSlotNodes;
|
||||
|
||||
/// <summary>
|
||||
/// <para>UnknownIndex</para>
|
||||
/// <para>未知位置</para>
|
||||
/// </summary>
|
||||
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];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Remove items from the item slot</para>
|
||||
/// <para>从物品槽内移除物品</para>
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Gets a secure subscript index</para>
|
||||
/// <para>获取安全的下标索引</para>
|
||||
/// </summary>
|
||||
/// <param name="itemSlotIndex"></param>
|
||||
/// <returns>
|
||||
///<para>-1 is returned on failure, and the index that does not result in an out-of-bounds subscript is returned on success</para>
|
||||
///<para>失败返回-1,成功返回不会导致下标越界的索引</para>
|
||||
/// </returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -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)
|
||||
|
|
|
@ -26,6 +26,13 @@ public interface IItemContainer
|
|||
/// <returns></returns>
|
||||
bool AddItem(IItem item);
|
||||
|
||||
/// <summary>
|
||||
/// <para>Gets the selected location</para>
|
||||
/// <para>获取选中的位置</para>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
int GetSelectIndex();
|
||||
|
||||
/// <summary>
|
||||
/// <para>Gets the currently selected node</para>
|
||||
/// <para>获取当前选中的节点</para>
|
||||
|
@ -33,6 +40,38 @@ public interface IItemContainer
|
|||
/// <returns></returns>
|
||||
ItemSlotNode? GetSelectItemSlotNode();
|
||||
|
||||
/// <summary>
|
||||
/// <para>Removes an item from the inventory at the currently selected location</para>
|
||||
/// <para>移除当前选中位置物品栏内的物品</para>
|
||||
/// </summary>
|
||||
/// <param name="number"></param>
|
||||
/// <returns></returns>
|
||||
bool RemoveItemFromItemSlotBySelectIndex(int number);
|
||||
|
||||
/// <summary>
|
||||
/// <para>Gets the number of item slots</para>
|
||||
/// <para>获取物品槽的数量</para>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
int GetItemSlotCount();
|
||||
|
||||
/// <summary>
|
||||
/// <para>Gets the item slot for the specified location</para>
|
||||
/// <para>获取指定位置的物品槽</para>
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
ItemSlotNode? GetItemSlotNode(int index);
|
||||
|
||||
/// <summary>
|
||||
/// <para>Removes an item from the item slot in the specified location</para>
|
||||
/// <para>在指定位置的物品槽内移除物品</para>
|
||||
/// </summary>
|
||||
/// <param name="itemSlotIndex"></param>
|
||||
/// <param name="number"></param>
|
||||
/// <returns></returns>
|
||||
bool RemoveItemFromItemSlot(int itemSlotIndex, int number);
|
||||
|
||||
/// <summary>
|
||||
/// <para>Based on the given item, match the item slots where it can be placed</para>
|
||||
/// <para>根据给定的物品,匹配可放置它的物品槽</para>
|
||||
|
|
Loading…
Reference in New Issue
Block a user