Danro/Assets/Scripts/UI/TextSplash.cs
Danil Iarosh 6a4c23c154
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
feat: Add prize status API, fix TextSplash rotation, and update game fonts
- Добавлены публичные методы в PrizeSystem для проверки статуса выдачи приза (WasLastPrizeSuccessful, IsPrizing)
- Сохранение результата последней выдачи приза для внешнего контроля
- Исправлено вращение в TextSplash: теперь оно применяется относительно начального поворота вместо сброса до 0
- Начальное вращение сохраняется в Awake и используется как базовое для анимации покачивания
- Начата глобальная замена шрифтов в игре: добавлены BerlinSansFBCyrillic, Flatiron Casual, Flatiron Regular, RifficFree-Bold
- Заменена часть шрифтов в главном меню на новые
- Добавлены новые тайловые спрайты для фона (Forest, Hills, Sky)
- Удален лишний пробел в PlayerController.cs
- Исправлена BOM-метка в UICreditsTextController.cs
2026-02-17 13:29:26 +03:00

190 lines
6.7 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 TMPro;
using UnityEngine;
namespace RR.Common.UI
{
/// <summary>
/// Компонент для создания анимированного сплеша текста.
/// Поддерживает изменение размера, покачивание и изменение цвета.
/// </summary>
[RequireComponent(typeof(TextMeshProUGUI))]
public class TextSplash : MonoBehaviour
{
[Header("Настройки масштаба")]
[SerializeField] private bool animateScale = true;
[SerializeField] private AnimationCurve scaleCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);
[SerializeField] private float startScale = 0.5f;
[SerializeField] private float endScale = 1.5f;
[Header("Настройки покачивания")]
[SerializeField] private bool animateSwing = true;
[SerializeField] private float swingAmplitude = 20f;
[SerializeField] private float swingFrequency = 2f;
[SerializeField] private AnimationCurve swingCurve = AnimationCurve.EaseInOut(0, 0, 0.5f, 1);
[Header("Настройки цвета")]
[SerializeField] private bool animateColor = true;
[SerializeField] private Gradient colorGradient = new Gradient();
[Header("Настройки движения")]
[SerializeField] private bool animateMovement = true;
[SerializeField] private Vector2 movementDirection = Vector2.up;
[SerializeField] private float movementDistance = 100f;
[SerializeField] private AnimationCurve movementCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);
[Header("Общие настройки")]
[SerializeField] private float animationDuration = 1f;
[SerializeField] private bool loopAnimation = false;
[SerializeField] private bool destroyOnComplete = true;
private TextMeshProUGUI _textComponent;
private RectTransform _rectTransform;
private Vector2 _startPosition;
private Quaternion _startRotation;
private float _elapsed;
private bool _isAnimating;
private void Awake()
{
_textComponent = GetComponent<TextMeshProUGUI>();
_rectTransform = GetComponent<RectTransform>();
_startPosition = _rectTransform.anchoredPosition;
_startRotation = _rectTransform.localRotation;
}
private void OnEnable()
{
StartAnimation();
}
/// <summary>
/// Запускает анимацию сплеша
/// </summary>
public void StartAnimation()
{
_elapsed = 0f;
_isAnimating = true;
// Сохраняем только позицию, вращение сохраняется один раз в Awake
if (animateMovement)
{
_startPosition = _rectTransform.anchoredPosition;
}
}
/// <summary>
/// Устанавливает текст сплеша
/// </summary>
public void SetText(string text)
{
if (_textComponent != null)
{
_textComponent.text = text;
}
}
/// <summary>
/// Устанавливает начальный цвет
/// </summary>
public void SetColor(Color color)
{
if (_textComponent != null)
{
_textComponent.color = color;
}
}
private void Update()
{
if (!_isAnimating) return;
_elapsed += Time.unscaledDeltaTime;
float t = Mathf.Clamp01(_elapsed / animationDuration);
// Анимация масштаба
if (animateScale)
{
float scaleValue = Mathf.Lerp(startScale, endScale, scaleCurve.Evaluate(t));
_rectTransform.localScale = Vector3.one * scaleValue;
}
// Анимация покачивания (rotation)
if (animateSwing)
{
float swingValue = swingCurve.Evaluate(t) * swingAmplitude;
// Используем частоту для создания непрерывного покачивания
float swingAngle = Mathf.Sin(t * Mathf.PI * 2 * swingFrequency) * swingValue;
// Применяем вращение относительно начального
_rectTransform.localRotation = _startRotation * Quaternion.Euler(0, 0, swingAngle);
}
// Анимация движения
if (animateMovement)
{
float moveValue = movementCurve.Evaluate(t) * movementDistance;
Vector2 offset = movementDirection.normalized * moveValue;
_rectTransform.anchoredPosition = _startPosition + offset;
}
// Анимация цвета
if (animateColor && _textComponent != null)
{
_textComponent.color = colorGradient.Evaluate(t);
}
// Завершение анимации
if (t >= 1f)
{
if (loopAnimation)
{
// Перезапускаем анимацию с начала
_elapsed = 0f;
}
else
{
_isAnimating = false;
if (destroyOnComplete)
{
Destroy(gameObject);
}
}
}
}
/// <summary>
/// Устанавливает длительность анимации
/// </summary>
public void SetDuration(float duration)
{
animationDuration = duration;
}
/// <summary>
/// Останавливает анимацию
/// </summary>
public void StopAnimation()
{
_isAnimating = false;
}
#if UNITY_EDITOR
/// <summary>
/// Предварительный просмотр в редакторе
/// </summary>
private void OnValidate()
{
if (colorGradient == null || colorGradient.colorKeys.Length == 0)
{
// Устанавливаем градиент по умолчанию (белый -> прозрачный)
colorGradient = new Gradient();
colorGradient.SetKeys(
new[] { new GradientColorKey(Color.white, 0f), new GradientColorKey(Color.white, 1f) },
new[] { new GradientAlphaKey(1f, 0f), new GradientAlphaKey(0f, 1f) }
);
}
}
#endif
}
}