Files
AppleHillsProduction/Assets/Scripts/UI/CardSystem/BoosterOpeningPage.cs
2025-10-20 16:33:58 +02:00

338 lines
12 KiB
C#

using System.Collections;
using System.Collections.Generic;
using AppleHills.Data.CardSystem;
using Core;
using Data.CardSystem;
using Pixelplacement;
using UnityEngine;
using UnityEngine.UI;
namespace AppleHills.UI.CardSystem
{
/// <summary>
/// UI page for opening booster packs and displaying the cards obtained.
/// </summary>
public class BoosterOpeningPage : UIPage
{
[Header("UI Elements")]
[SerializeField] private GameObject boosterPackObject;
[SerializeField] private Transform cardRevealTransform;
[SerializeField] private GameObject cardPrefab;
[SerializeField] private Button openBoosterButton;
[SerializeField] private Button continueButton;
[SerializeField] private CanvasGroup canvasGroup;
[Header("Animation Settings")]
[SerializeField] private float cardRevealDelay = 0.5f;
[SerializeField] private float cardMoveToBackpackDelay = 1.0f;
[SerializeField] private Transform backpackTargetTransform;
[SerializeField] private AudioSource cardRevealSound;
[SerializeField] private AudioSource rareCardSound;
[SerializeField] private ParticleSystem cardRevealParticles;
[SerializeField] private ParticleSystem rareCardParticles;
// State tracking
private enum OpeningState
{
BoosterReady,
CardsRevealing,
CardsRevealed,
MovingToBackpack,
Completed
}
private OpeningState _currentState = OpeningState.BoosterReady;
private List<CardUIElement> _revealedCards = new List<CardUIElement>();
private CardSystemManager _cardManager;
private Coroutine _revealCoroutine;
private Coroutine _moveToBackpackCoroutine;
private void Awake()
{
_cardManager = CardSystemManager.Instance;
// Set up button listeners
if (openBoosterButton != null)
{
openBoosterButton.onClick.AddListener(OnOpenBoosterClicked);
}
if (continueButton != null)
{
continueButton.onClick.AddListener(OnContinueClicked);
continueButton.gameObject.SetActive(false);
}
// Make sure we have a CanvasGroup for transitions
if (canvasGroup == null)
canvasGroup = GetComponent<CanvasGroup>();
if (canvasGroup == null)
canvasGroup = gameObject.AddComponent<CanvasGroup>();
}
private void OnDestroy()
{
// Clean up button listeners
if (openBoosterButton != null)
{
openBoosterButton.onClick.RemoveListener(OnOpenBoosterClicked);
}
if (continueButton != null)
{
continueButton.onClick.RemoveListener(OnContinueClicked);
}
// Stop any running coroutines
if (_revealCoroutine != null)
StopCoroutine(_revealCoroutine);
if (_moveToBackpackCoroutine != null)
StopCoroutine(_moveToBackpackCoroutine);
}
/// <summary>
/// Resets the page to its initial state when it becomes active
/// </summary>
public override void TransitionIn()
{
base.TransitionIn();
ResetState();
}
/// <summary>
/// Resets the state of the booster opening process
/// </summary>
private void ResetState()
{
// Clear any previously revealed cards
foreach (var card in _revealedCards)
{
if (card != null && card.gameObject != null)
Destroy(card.gameObject);
}
_revealedCards.Clear();
// Reset state
_currentState = OpeningState.BoosterReady;
// Show booster pack, hide continue button
if (boosterPackObject != null)
{
boosterPackObject.SetActive(true);
}
if (openBoosterButton != null)
{
openBoosterButton.gameObject.SetActive(true);
}
if (continueButton != null)
{
continueButton.gameObject.SetActive(false);
}
}
/// <summary>
/// Handles click on the booster pack to open it
/// </summary>
private void OnOpenBoosterClicked()
{
if (_currentState != OpeningState.BoosterReady) return;
_currentState = OpeningState.CardsRevealing;
// Open the booster pack and get the cards
List<CardData> newCards = _cardManager.OpenBoosterPack();
if (newCards.Count > 0)
{
// Hide the booster pack and open button
if (boosterPackObject != null)
{
// Animate the booster pack opening
Tween.LocalScale(boosterPackObject.transform, Vector3.zero, 0.3f, 0f, Tween.EaseInBack, Tween.LoopType.None, null, () => {
boosterPackObject.SetActive(false);
});
}
if (openBoosterButton != null)
{
openBoosterButton.gameObject.SetActive(false);
}
// Start revealing cards
_revealCoroutine = StartCoroutine(RevealCards(newCards));
}
else
{
Logging.Warning("[BoosterOpeningPage] No cards were obtained from the booster pack.");
UIPageController.Instance.PopPage();
}
}
/// <summary>
/// Reveals cards one by one with animation
/// </summary>
private IEnumerator RevealCards(List<CardData> cards)
{
// Wait a short delay before revealing cards
yield return new WaitForSeconds(0.5f);
// Reveal each card
foreach (var cardData in cards)
{
// Instantiate card UI element
GameObject cardObj = Instantiate(cardPrefab, cardRevealTransform);
CardUIElement cardUI = cardObj.GetComponent<CardUIElement>();
if (cardUI != null)
{
// Set up the card data
cardUI.SetupCard(cardData);
_revealedCards.Add(cardUI);
// Set initial scale to zero for animation
cardObj.transform.localScale = Vector3.zero;
// Play reveal animation using Pixelplacement.Tween
Tween.LocalScale(cardObj.transform, Vector3.one, 0.5f, 0f, Tween.EaseOutBack);
// Call card's show animation
cardUI.OnShowAnimation();
// Play appropriate sound and particles based on rarity
if (cardData.Rarity >= CardRarity.Rare)
{
// Play rare card sound
if (rareCardSound != null)
{
rareCardSound.Play();
}
// Play rare card particles
if (rareCardParticles != null)
{
rareCardParticles.transform.position = cardObj.transform.position;
rareCardParticles.Play();
}
}
else
{
// Play regular card sound
if (cardRevealSound != null)
{
cardRevealSound.Play();
}
// Play regular particles
if (cardRevealParticles != null)
{
cardRevealParticles.transform.position = cardObj.transform.position;
cardRevealParticles.Play();
}
}
// Wait for animation delay
yield return new WaitForSeconds(cardRevealDelay);
}
}
// Update state and show continue button
_currentState = OpeningState.CardsRevealed;
if (continueButton != null)
{
continueButton.gameObject.SetActive(true);
// Animate button appearance
continueButton.transform.localScale = Vector3.zero;
Tween.LocalScale(continueButton.transform, Vector3.one, 0.3f, 0f, Tween.EaseOutBack);
}
}
/// <summary>
/// Handles click on the continue button after cards are revealed
/// </summary>
private void OnContinueClicked()
{
if (_currentState != OpeningState.CardsRevealed) return;
_currentState = OpeningState.MovingToBackpack;
if (continueButton != null)
{
continueButton.gameObject.SetActive(false);
}
// Start moving cards to backpack animation
_moveToBackpackCoroutine = StartCoroutine(MoveCardsToBackpack());
}
/// <summary>
/// Animates cards moving to the backpack
/// </summary>
private IEnumerator MoveCardsToBackpack()
{
// If no backpack target, use a default position (lower-right corner)
Vector3 targetPosition = (backpackTargetTransform != null)
? backpackTargetTransform.position
: new Vector3(Screen.width * 0.9f, Screen.height * 0.1f, 0f);
// Move each card to backpack with animation
foreach (var cardUI in _revealedCards)
{
if (cardUI != null)
{
// Call card's move to backpack animation
cardUI.OnMoveToBackpackAnimation();
// Animate movement to backpack
Tween.Position(cardUI.transform, targetPosition, 0.5f, 0f, Tween.EaseInBack);
Tween.LocalScale(cardUI.transform, Vector3.zero, 0.5f, 0f, Tween.EaseInBack);
// Wait for delay between cards
yield return new WaitForSeconds(0.2f);
}
}
// Wait for final animation
yield return new WaitForSeconds(0.5f);
// Update state to completed
_currentState = OpeningState.Completed;
// Return to previous page
UIPageController.Instance.PopPage();
}
// Override for transition animations
protected override void DoTransitionIn(System.Action onComplete)
{
// Simple fade in animation
if (canvasGroup != null)
{
canvasGroup.alpha = 0f;
Tween.Value(0f, 1f, (value) => canvasGroup.alpha = value, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete);
}
else
{
onComplete?.Invoke();
}
}
protected override void DoTransitionOut(System.Action onComplete)
{
// Simple fade out animation
if (canvasGroup != null)
{
Tween.Value(canvasGroup.alpha, 0f, (value) => canvasGroup.alpha = value, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete);
}
else
{
onComplete?.Invoke();
}
}
}
}