Files
aibis-dream/Assets/Scripts/MiniGame/Gear/Shaft.cs
T
2024-12-01 21:50:27 +08:00

307 lines
8.8 KiB
C#

using System;
using AibisDream.Framework;
using AibisDream.Utility;
using DG.Tweening;
using Newtonsoft.Json;
using UnityEngine;
namespace AibisDream
{
public class Shaft : MonoBehaviour
{
[SerializeField] private int id;
[SerializeField] public ShaftType shaftType;
// 初始齿轮
[SerializeField] private float initRadius;
[SerializeField] private Sprite initSprite;
[SerializeField] private bool hasGear;
[SerializeField] private GameObject childGear;
// 初始角速度
[SerializeField] private float initialSpeed;
// 目标角速度
[SerializeField] private float targetSpeed;
// 当前角速度
public float speed;
public bool IsPluggable => shaftType is ShaftType.Pluggable or ShaftType.Driver or ShaftType.Target;
/// <summary>
/// 当前齿轮半径
/// </summary>
public float GearRadius
{
get
{
if (!childGear)
{
return 0;
}
if (IsPluggable)
{
Gear gear = childGear.GetComponent<Gear>();
return gear.radius;
}
return initRadius;
}
}
private GearSystem _gearSystem;
private void Awake()
{
_gearSystem = transform.parent.parent.GetComponent<GearSystem>();
}
/// <summary>
/// 初始化当前轴位置
/// </summary>
public void InitShaft()
{
// 如果不带齿轮
if (!hasGear) return;
// 如果带齿轮,要根据齿轮类型生成
childGear = IsPluggable ? InitPluggableGear() : InitStaticGear();
speed = initialSpeed;
UpdateSpeed();
}
private GameObject InitStaticGear()
{
GameObject staticGear = transform.GetChild(0).gameObject;
// 添加齿轮图片
staticGear.SetActive(true);
var staticGearRenderer = staticGear.GetComponent<SpriteRenderer>();
staticGearRenderer.sprite = initSprite;
staticGearRenderer.size = new Vector2(initRadius * 2, initRadius * 2);
// 如果有初速,就要开始转动了
if (!CommonUtil.IsZero(initialSpeed))
{
staticGear.transform.DORotate(new Vector3(0, 0, 360), 1 / initialSpeed, RotateMode.LocalAxisAdd)
.SetEase(Ease.Linear).SetLoops(-1, LoopType.Incremental);
}
return staticGear;
}
private GameObject InitPluggableGear()
{
var gear = _gearSystem.InitGear(transform.position, initRadius, initSprite);
gear.GetComponent<Gear>().targetShaft = this;
return gear;
}
public void PlugInGear(Gear gear)
{
childGear = gear.gameObject;
_gearSystem.ChangeGraphVertex(GetInstanceID());
}
public void PlugOutGear()
{
childGear = null;
_gearSystem.ChangeGraphVertex(GetInstanceID());
}
public void UpdateSpeed()
{
UpdateSpeedAnima();
CheckGameState();
}
/// <summary>
/// 速度修改后改变动画
/// </summary>
private void UpdateSpeedAnima()
{
// 没有齿轮的不需要旋转
if (!HasChildGear())
{
return;
}
if (CommonUtil.IsZero(speed))
{
childGear.transform.DOPause();
return;
}
// 更新动画
childGear.transform.DOKill();
if (speed > 0)
{
childGear.transform.DORotate(new Vector3(0, 0, 360), 1 / speed, RotateMode.LocalAxisAdd)
.SetEase(Ease.Linear).SetLoops(-1, LoopType.Incremental);
}
else
{
childGear.transform.DORotate(new Vector3(0, 0, -360), 1 / -speed, RotateMode.LocalAxisAdd)
.SetEase(Ease.Linear).SetLoops(-1, LoopType.Incremental);
}
}
private void CheckGameState()
{
if (shaftType == ShaftType.Target)
{
if (targetSpeed <= Mathf.Abs(speed))
{
_gearSystem.Succeed();
}
}
}
/// <summary>
/// 判断是否带齿轮
/// </summary>
/// <returns>是否带齿轮</returns>
public bool HasChildGear()
{
return childGear;
}
/// <summary>
/// 判断两个轴是否齿轮相接
/// </summary>
/// <param name="shaft1">轴1</param>
/// <param name="shaft2">轴2</param>
/// <returns>是否相接</returns>
public static bool IsShaftConnected(Shaft shaft1, Shaft shaft2)
{
// 如果轴上无齿轮就不计算
if (!shaft1 || !shaft2)
{
return false;
}
if (!shaft1.HasChildGear() || !shaft2.HasChildGear())
{
return false;
}
// 如果两个都有齿轮,就判断是否相邻
float distance = (shaft1.transform.position - shaft2.transform.position).magnitude;
float radiusSum = shaft1.GearRadius + shaft2.GearRadius;
return distance < radiusSum;
}
/// <summary>
/// 获取可以安装齿轮的最大尺寸
/// </summary>
/// <param name="sourcePos">源位置</param>
/// <param name="shaft">目标轴</param>
/// <returns>可用距离</returns>
public static float CalcShaftAvailableDis(Vector3 sourcePos, Shaft shaft)
{
if (!shaft.HasChildGear())
{
return (sourcePos - shaft.transform.position).magnitude;
}
else
{
return (sourcePos - shaft.transform.position).magnitude - shaft.GearRadius;
}
}
/// <summary>
/// 求两个轴角速度之比
/// </summary>
/// <param name="shaft1">轴1</param>
/// <param name="shaft2">轴2</param>
/// <returns>角速度之比</returns>
public static float CalcAngularVelocityRatio(Shaft shaft1, Shaft shaft2)
{
return shaft1.GearRadius / shaft2.GearRadius;
}
public void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, initRadius);
}
#region 保存与加载
public void Load(ShaftLevelData levelData)
{
// 加载数据
gameObject.name = levelData.shaftName;
transform.localPosition = levelData.ShaftPos;
initSprite = levelData.GearPic;
shaftType = levelData.shaftType;
hasGear = levelData.hasChildGear;
initialSpeed = levelData.initialSpeed;
targetSpeed = levelData.targetSpeed;
initRadius = levelData.radius;
}
public ShaftLevelData Save()
{
return new ShaftLevelData
{
shaftName = gameObject.name,
ShaftPos = transform.localPosition,
GearPic = initSprite,
shaftType = shaftType,
hasChildGear = hasGear,
initialSpeed = initialSpeed,
targetSpeed = targetSpeed,
radius = initRadius
};
}
#endregion
}
public enum ShaftType
{
Driver, // 拥有初始速度,没有目标速度,全局仅有一个
Target, // 没有初始速度,有目标速度,全局有多个
Constant, // 没有初始速度,没有目标速度,不可拖动
Pluggable // 没有初始速度,没有目标速度,可拔插
}
[Serializable]
public struct ShaftLevelData
{
public string shaftName;
// 关卡数据
public ShaftType shaftType;
public float initialSpeed;
public float targetSpeed;
public bool hasChildGear;
public float radius;
// 外形数据
public SerializableVector3 shaftPos;
public string gearPicPath;
// 类型转换
[JsonIgnore]
public Sprite GearPic
{
get => !string.IsNullOrEmpty(gearPicPath) ? ResourceKit.LoadSpriteFromPsd(gearPicPath) : null;
set => gearPicPath = ResourceKit.SaveSprite(value);
}
[JsonIgnore]
public Vector3 ShaftPos
{
get => shaftPos.ToVector3();
set => shaftPos = new SerializableVector3(value);
}
}
}