mirror of
http://47.107.252.169:3000/Roguelite-Game-Developing-Team/Gen_Hack-and-Slash-Roguelite.git
synced 2025-11-19 23:37:13 +08:00
Co-authored-by: m0_75251201 <m0_75251201@noreply.gitcode.com> Reviewed-on: http://47.107.252.169:3000/Roguelite-Game-Developing-Team/Gen_Hack-and-Slash-Roguelite/pulls/60
278 lines
9.6 KiB
C#
278 lines
9.6 KiB
C#
using System;
|
||
using System.Xml.Linq;
|
||
|
||
namespace Data
|
||
{
|
||
public enum Orientation
|
||
{
|
||
Down,
|
||
Left,
|
||
Right,
|
||
Up
|
||
}
|
||
|
||
public enum EntityState
|
||
{
|
||
Idle,
|
||
Walking,
|
||
MeleeAttack,
|
||
RangedAttack,
|
||
Death
|
||
}
|
||
|
||
public class DrawingOrderDef : Define
|
||
{
|
||
public DrawNodeDef death_down;
|
||
public DrawNodeDef death_left;
|
||
public DrawNodeDef death_right;
|
||
public DrawNodeDef death_up;
|
||
public DrawNodeDef idle_down;
|
||
public DrawNodeDef idle_left;
|
||
public DrawNodeDef idle_right;
|
||
public DrawNodeDef idle_up;
|
||
|
||
public DrawNodeDef meleeAttack_down;
|
||
public DrawNodeDef meleeAttack_left;
|
||
public DrawNodeDef meleeAttack_right;
|
||
public DrawNodeDef meleeAttack_up;
|
||
|
||
public DrawNodeDef rangedAttack_down;
|
||
public DrawNodeDef rangedAttack_left;
|
||
public DrawNodeDef rangedAttack_right;
|
||
public DrawNodeDef rangedAttack_up;
|
||
|
||
public DrawNodeDef walk_down;
|
||
public DrawNodeDef walk_left;
|
||
public DrawNodeDef walk_right;
|
||
public DrawNodeDef walk_up;
|
||
|
||
public DrawNodeDef GetDrawNodeDef(EntityState state, Orientation orientation,
|
||
out Orientation? fallbackOrientation)
|
||
{
|
||
fallbackOrientation = null;
|
||
|
||
// 根据状态和方向获取对应的DrawNodeDef
|
||
var result = GetDrawNodeDefInternal(state, orientation);
|
||
|
||
if (result != null) return result;
|
||
|
||
// 如果找不到,按照规则查找替补
|
||
switch (orientation)
|
||
{
|
||
case Orientation.Up:
|
||
// 上方向优先找下方向
|
||
result = GetDrawNodeDefInternal(state, Orientation.Down);
|
||
if (result != null)
|
||
{
|
||
fallbackOrientation = Orientation.Down;
|
||
return result;
|
||
}
|
||
|
||
// 其次找左右方向
|
||
result = GetDrawNodeDefInternal(state, Orientation.Left);
|
||
if (result != null)
|
||
{
|
||
fallbackOrientation = Orientation.Left;
|
||
return result;
|
||
}
|
||
|
||
result = GetDrawNodeDefInternal(state, Orientation.Right);
|
||
if (result != null)
|
||
{
|
||
fallbackOrientation = Orientation.Right;
|
||
return result;
|
||
}
|
||
|
||
break;
|
||
|
||
case Orientation.Down:
|
||
// 下方向优先找上方向
|
||
result = GetDrawNodeDefInternal(state, Orientation.Up);
|
||
if (result != null)
|
||
{
|
||
fallbackOrientation = Orientation.Up;
|
||
return result;
|
||
}
|
||
|
||
// 其次找左右方向
|
||
result = GetDrawNodeDefInternal(state, Orientation.Left);
|
||
if (result != null)
|
||
{
|
||
fallbackOrientation = Orientation.Left;
|
||
return result;
|
||
}
|
||
|
||
result = GetDrawNodeDefInternal(state, Orientation.Right);
|
||
if (result != null)
|
||
{
|
||
fallbackOrientation = Orientation.Right;
|
||
return result;
|
||
}
|
||
|
||
break;
|
||
|
||
case Orientation.Left:
|
||
// 左方向优先找右方向
|
||
result = GetDrawNodeDefInternal(state, Orientation.Right);
|
||
if (result != null)
|
||
{
|
||
fallbackOrientation = Orientation.Right;
|
||
return result;
|
||
}
|
||
|
||
// 其次找上下方向
|
||
result = GetDrawNodeDefInternal(state, Orientation.Up);
|
||
if (result != null)
|
||
{
|
||
fallbackOrientation = Orientation.Up;
|
||
return result;
|
||
}
|
||
|
||
result = GetDrawNodeDefInternal(state, Orientation.Down);
|
||
if (result != null)
|
||
{
|
||
fallbackOrientation = Orientation.Down;
|
||
return result;
|
||
}
|
||
|
||
break;
|
||
|
||
case Orientation.Right:
|
||
// 右方向优先找左方向
|
||
result = GetDrawNodeDefInternal(state, Orientation.Left);
|
||
if (result != null)
|
||
{
|
||
fallbackOrientation = Orientation.Left;
|
||
return result;
|
||
}
|
||
|
||
// 其次找上下方向
|
||
result = GetDrawNodeDefInternal(state, Orientation.Up);
|
||
if (result != null)
|
||
{
|
||
fallbackOrientation = Orientation.Up;
|
||
return result;
|
||
}
|
||
|
||
result = GetDrawNodeDefInternal(state, Orientation.Down);
|
||
if (result != null)
|
||
{
|
||
fallbackOrientation = Orientation.Down;
|
||
return result;
|
||
}
|
||
|
||
break;
|
||
default:
|
||
throw new ArgumentOutOfRangeException(nameof(orientation), orientation, null);
|
||
}
|
||
|
||
// 如果所有替补都找不到,返回null
|
||
return null;
|
||
}
|
||
|
||
private DrawNodeDef GetDrawNodeDefInternal(EntityState state, Orientation orientation)
|
||
{
|
||
// 根据状态和方向获取对应的DrawNodeDef
|
||
switch (state)
|
||
{
|
||
case EntityState.Idle:
|
||
switch (orientation)
|
||
{
|
||
case Orientation.Down: return idle_down;
|
||
case Orientation.Up: return idle_up;
|
||
case Orientation.Left: return idle_left;
|
||
case Orientation.Right: return idle_right;
|
||
}
|
||
|
||
break;
|
||
|
||
case EntityState.Walking:
|
||
switch (orientation)
|
||
{
|
||
case Orientation.Down: return walk_down;
|
||
case Orientation.Up: return walk_up;
|
||
case Orientation.Left: return walk_left;
|
||
case Orientation.Right: return walk_right;
|
||
}
|
||
|
||
break;
|
||
|
||
case EntityState.MeleeAttack:
|
||
switch (orientation)
|
||
{
|
||
case Orientation.Down: return meleeAttack_down;
|
||
case Orientation.Up: return meleeAttack_up;
|
||
case Orientation.Left: return meleeAttack_left;
|
||
case Orientation.Right: return meleeAttack_right;
|
||
}
|
||
|
||
break;
|
||
|
||
case EntityState.RangedAttack:
|
||
switch (orientation)
|
||
{
|
||
case Orientation.Down: return rangedAttack_down;
|
||
case Orientation.Up: return rangedAttack_up;
|
||
case Orientation.Left: return rangedAttack_left;
|
||
case Orientation.Right: return rangedAttack_right;
|
||
}
|
||
|
||
break;
|
||
case EntityState.Death:
|
||
switch (orientation)
|
||
{
|
||
case Orientation.Down: return death_down;
|
||
case Orientation.Up: return death_up;
|
||
case Orientation.Left: return death_left;
|
||
case Orientation.Right: return death_right;
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}
|
||
|
||
public class DrawNodeDef : Define
|
||
{
|
||
public float FPS = 5f;
|
||
public string nodeName;
|
||
public DrawNodeDef[] nodes;
|
||
public string position;
|
||
public string[] textures;
|
||
|
||
public override bool Init(XElement xmlDef)
|
||
{
|
||
base.Init(xmlDef);
|
||
|
||
nodeName = xmlDef.Attribute("name")?.Value ?? "noName";
|
||
position = xmlDef.Attribute("position")?.Value ?? "0,0";
|
||
FPS = float.TryParse(xmlDef.Attribute("FPS")?.Value, out var result) ? result : 5.0f;
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取播放一遍动画所需的最小时间(取当前节点动画与所有子集动画的最大值)。
|
||
/// </summary>
|
||
/// <returns>播放一遍动画所需的最小时间(秒),如果无动画则为0。</returns>
|
||
public float GetMinAnimationDuration()
|
||
{
|
||
var maxDuration = 0f;
|
||
// 计算当前节点自身的动画时间
|
||
if (textures != null && textures.Length > 0)
|
||
// 只有当FPS大于0时,才计算有效的动画时间。
|
||
// 如果FPS <= 0,表示该部分动画无法播放,其时长贡献为0,不参与最大值计算。
|
||
if (FPS > 0)
|
||
maxDuration = Math.Max(maxDuration, textures.Length / FPS);
|
||
|
||
// 递归计算子节点的动画时间,并更新最大值
|
||
if (nodes != null && nodes.Length > 0)
|
||
foreach (var node in nodes)
|
||
if (node != null)
|
||
maxDuration = Math.Max(maxDuration, node.GetMinAnimationDuration());
|
||
|
||
return maxDuration;
|
||
}
|
||
}
|
||
} |