Files
Gen_Hack-and-Slash-Roguelite/Client/Assets/Scripts/Data/DrawingOrderDef.cs

278 lines
9.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}
}