209 lines
6.9 KiB
C#
209 lines
6.9 KiB
C#
using Code.DI;
|
|
using Code.Input;
|
|
using Code.Records;
|
|
using DG.Tweening;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.SceneManagement;
|
|
using UnityEngine.UI;
|
|
|
|
namespace Code.UI
|
|
{
|
|
public class MainMenuController : MonoBehaviour
|
|
{
|
|
[SerializeField] private TMP_Text logotype;
|
|
[SerializeField] private Button startGameButton;
|
|
[SerializeField] private Button showResultsButton;
|
|
[SerializeField] private Button exitButton;
|
|
[SerializeField] private Transform parallaxRoot;
|
|
|
|
[SerializeField] private Image fader;
|
|
[SerializeField] private Image backgroundImage;
|
|
|
|
[SerializeField] private Transform resultsWrapper;
|
|
[SerializeField] private TMP_Text resultsText;
|
|
[SerializeField] private Button closeResultsButton;
|
|
|
|
[SerializeField] private float parallaxStrength = 15f;
|
|
[SerializeField] private float parallaxSmoothTime = 0.1f;
|
|
|
|
private Vector3 _targetParallaxOffset;
|
|
private Vector3 _currentParallaxOffset;
|
|
private IInputService _inputService;
|
|
private AudioSource _audioSource;
|
|
|
|
private void Start()
|
|
{
|
|
var container = FindFirstObjectByType<DIContainer>();
|
|
_inputService = container.Resolve<IInputService>();
|
|
_inputService.EnableMap(ActionMapping.MainMenu);
|
|
_audioSource = FindFirstObjectByType<AudioSource>();
|
|
|
|
resultsWrapper.gameObject.SetActive(false);
|
|
|
|
SetupButtons();
|
|
AnimateLogo();
|
|
AnimateBackground();
|
|
FadeIn();
|
|
}
|
|
|
|
private void SetupButtons()
|
|
{
|
|
startGameButton.onClick.AddListener(OnStartGameClicked);
|
|
showResultsButton.onClick.AddListener(OnShowResultsClicked);
|
|
exitButton.onClick.AddListener(OnExitButtonClicked);
|
|
}
|
|
|
|
private void AnimateLogo()
|
|
{
|
|
var rect = logotype.rectTransform;
|
|
var originalColor = logotype.color;
|
|
|
|
rect.localScale = Vector3.zero;
|
|
rect.rotation = Quaternion.Euler(0, 0, -20f);
|
|
logotype.color = new Color(originalColor.r, originalColor.g, originalColor.b, 0f);
|
|
|
|
var logoSequence = DOTween.Sequence();
|
|
logoSequence.Append(rect.DOScale(Vector3.one * 1.2f, 0.6f).SetEase(Ease.OutBack))
|
|
.Join(rect.DORotate(Vector3.zero, 0.6f).SetEase(Ease.OutSine))
|
|
.Join(logotype.DOColor(originalColor, 0.6f));
|
|
|
|
logoSequence.OnComplete(() =>
|
|
{
|
|
rect.DOScale(new Vector3(1.08f, 1.08f, 1f), 2.4f)
|
|
.SetLoops(-1, LoopType.Yoyo)
|
|
.SetEase(Ease.InOutSine);
|
|
|
|
logotype.DOColor(new Color(originalColor.r, originalColor.g, originalColor.b, 0.9f), 3f)
|
|
.SetLoops(-1, LoopType.Yoyo)
|
|
.SetEase(Ease.InOutSine);
|
|
});
|
|
}
|
|
|
|
private void AnimateBackground()
|
|
{
|
|
if (backgroundImage == null) return;
|
|
|
|
var rect = backgroundImage.rectTransform;
|
|
|
|
rect.DOScale(1.2f, 25f)
|
|
.SetLoops(-1, LoopType.Yoyo)
|
|
.SetEase(Ease.InOutSine);
|
|
}
|
|
|
|
private void FadeIn()
|
|
{
|
|
_audioSource.volume = 0f;
|
|
_audioSource.DOFade(1f, 1f).SetEase(Ease.Linear);
|
|
fader.color = new Color(0, 0, 0, 1f);
|
|
fader.DOFade(0f, 1f).SetEase(Ease.Linear);
|
|
fader.raycastTarget = false;
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
HandleParallax();
|
|
}
|
|
|
|
private void HandleParallax()
|
|
{
|
|
if (!parallaxRoot) return;
|
|
|
|
var mousePos = _inputService.MainMenuParalax;
|
|
var center = new Vector2(Screen.width / 2f, Screen.height / 2f);
|
|
|
|
if (center.x == 0 || center.y == 0) return;
|
|
|
|
var offset = (mousePos - center) / center;
|
|
_targetParallaxOffset = new Vector3(
|
|
-offset.x * parallaxStrength,
|
|
-offset.y * parallaxStrength,
|
|
0f
|
|
);
|
|
|
|
_currentParallaxOffset = Vector3.Lerp(
|
|
_currentParallaxOffset,
|
|
_targetParallaxOffset,
|
|
Time.deltaTime / parallaxSmoothTime
|
|
);
|
|
|
|
parallaxRoot.localPosition = _currentParallaxOffset;
|
|
}
|
|
|
|
private void OnStartGameClicked() => FadeOutAndLoad("Gameplay");
|
|
|
|
private void OnShowResultsClicked()
|
|
{
|
|
resultsWrapper.gameObject.SetActive(true);
|
|
var rect = resultsWrapper.GetComponent<RectTransform>();
|
|
rect.localScale = Vector3.zero;
|
|
rect.DOScale(Vector3.one, 0.3f).SetEase(Ease.OutBack);
|
|
closeResultsButton.onClick.AddListener(HideResults);
|
|
UpdateResultsDisplay();
|
|
}
|
|
|
|
private void HideResults()
|
|
{
|
|
var rect = resultsWrapper.GetComponent<RectTransform>();
|
|
rect.DOScale(Vector3.zero, 0.2f).SetEase(Ease.InBack).OnComplete(() =>
|
|
{
|
|
resultsWrapper.gameObject.SetActive(false);
|
|
});
|
|
closeResultsButton.onClick.RemoveAllListeners();
|
|
}
|
|
|
|
private void OnExitButtonClicked() => FadeOutAndQuit();
|
|
|
|
private void FadeOutAndLoad(string sceneName)
|
|
{
|
|
fader.raycastTarget = true;
|
|
_audioSource.DOFade(0, 0.8f).SetEase(Ease.Linear);
|
|
fader.DOFade(1f, 0.8f).OnComplete(() =>
|
|
{
|
|
SceneManager.LoadScene(sceneName);
|
|
});
|
|
}
|
|
|
|
private void FadeOutAndQuit()
|
|
{
|
|
fader.raycastTarget = true;
|
|
_audioSource.DOFade(0, 0.8f).SetEase(Ease.Linear);
|
|
fader.DOFade(1f, 0.8f).OnComplete(() =>
|
|
{
|
|
#if UNITY_EDITOR
|
|
UnityEditor.EditorApplication.isPlaying = false;
|
|
#else
|
|
Application.Quit();
|
|
#endif
|
|
});
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
_inputService?.DisableMap(ActionMapping.MainMenu);
|
|
_inputService?.DisableMap(ActionMapping.Gameplay);
|
|
startGameButton?.onClick.RemoveListener(OnStartGameClicked);
|
|
showResultsButton?.onClick.RemoveListener(OnShowResultsClicked);
|
|
exitButton?.onClick.RemoveListener(OnExitButtonClicked);
|
|
}
|
|
|
|
private void UpdateResultsDisplay()
|
|
{
|
|
var records = RecordsService.Load();
|
|
if (records.Count == 0)
|
|
{
|
|
resultsText.text = "RESULTS\n\nNo records yet.";
|
|
return;
|
|
}
|
|
|
|
var lines = new System.Text.StringBuilder();
|
|
lines.AppendLine("RESULTS");
|
|
for (var i = 0; i < records.Count; i++)
|
|
{
|
|
var r = records[i];
|
|
lines.AppendLine($"{i + 1}. {r.name} - {r.formattedTime}");
|
|
}
|
|
resultsText.text = lines.ToString();
|
|
}
|
|
}
|
|
} |