Files
aibis-dream/Assets/Scripts/FixSystemNew/CoolingMachine/CoolingBottle.cs
T
2024-12-24 18:23:42 +00:00

150 lines
4.3 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using AibisDream.Framework;
using DG.Tweening;
using UnityEngine;
namespace AibisDream.FixSystem
{
[RequireComponent(typeof(Collider2D), typeof(Rigidbody2D))]
public class CoolingBottle : MonoBehaviour, IMoveable
{
private const float RotateTime = 0.3f;
private const float SnapMoveTime = 0.3f;
private static readonly Vector3 ClockwiseAngle = new(0, 0, 0);
private static readonly Vector3 ClockWiseScale = new(1, 1, 1);
private static readonly Vector3 AnticlockwiseAngle = new(0, 0, 90);
private static readonly Vector3 AnticlockwiseScale = new(1.45f, 1.45f, 1);
public CoolingBottleData data;
#region 引用
private Sprite _verticalSprite;
private Sprite _horizontalSprite;
public BottleSlot curSnapSlot;
public readonly HashSet<BottleSlot> targetSnapSlotSet = new();
private Rigidbody2D _rb;
private SpriteRenderer _renderer;
#endregion
private void Awake()
{
InitRefs();
}
private void InitRefs()
{
_rb = GetComponent<Rigidbody2D>();
_renderer = GetComponent<SpriteRenderer>();
}
#region 移动逻辑
public bool IsBlock { get; set; }
public void StartMove()
{
_rb.isKinematic = false;
curSnapSlot.RemoveBottle();
// 开始移动时就切换成横版
Rotate(false);
}
public void Rotate(bool isVertical)
{
StartCoroutine(RotateAsync(isVertical));
}
/// <summary>
/// 旋转瓶子
/// </summary>
/// <param name="isVertical">是否竖直</param>
/// <returns></returns>
private IEnumerator RotateAsync(bool isVertical)
{
var angle = isVertical ? ClockwiseAngle : AnticlockwiseAngle;
var scale = isVertical ? ClockWiseScale : AnticlockwiseScale;
// 动画序列
var sq = DOTween.Sequence();
Tween rotate = transform.DORotate(angle, RotateTime, RotateMode.FastBeyond360);
sq.Join(rotate);
Tween scaleTw = transform.DOScale(scale, RotateTime);
sq.Join(scaleTw);
while (sq.active && !sq.IsComplete())
{
yield return null;
}
}
public void Move(Vector2 mousePos)
{
_rb.MovePosition(mousePos);
}
public void StopMove()
{
if (TryFindClosestSlot(out var targetSlot))
{
curSnapSlot = targetSlot;
}
targetSnapSlotSet.Clear();
// 吸附到目标位置
_rb.isKinematic = true;
transform.DOMove(curSnapSlot.transform.position, SnapMoveTime);
curSnapSlot.InsertSlot(this);
// TODO 停止描边
}
public bool TryFindClosestSlot(out BottleSlot targetSlot)
{
// 没有目标Slot,返回
if (targetSnapSlotSet.Count == 0)
{
targetSlot = null;
return false;
}
// 寻找最近的Slot
var shortestDistance = float.MaxValue;
BottleSlot closestSlot = null;
foreach (var slot in targetSnapSlotSet)
{
var distance = Vector3.Distance(slot.transform.position, transform.position);
if (distance < shortestDistance)
{
shortestDistance = distance;
closestSlot = slot;
}
}
targetSlot = closestSlot;
return true;
}
#endregion
public void Load(CoolingBottleData targetData)
{
data = targetData;
_verticalSprite = ResourceKit.LoadSpriteFromPsd($"Art/Fix/Cooling/冷却系统/{data.verticalSprite}");
_renderer.sprite = _verticalSprite;
}
}
[Serializable]
public struct CoolingBottleData
{
public string name;
public string description;
public string verticalSprite;
public string horizontalSprite;
}
}