150 lines
4.3 KiB
C#
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;
|
|
}
|
|
} |