//-----------------------------------------------------------------------------
// ShuffleAnimationComponent.cs
//
// Game component that manages a shuffle animation, creates and coordinates
// all animated card components, and handles cleanup
//-----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace CardsFramework
{
///
/// Component that orchestrates a shuffle animation by creating animated
/// cards and managing their lifecycle
///
public class ShuffleAnimationComponent : DrawableGameComponent
{
private readonly ShuffleAnimation shuffleAnimation;
private readonly List deck;
private readonly SpriteBatch spriteBatch;
private readonly Matrix globalTransformation;
private List animatedCards;
private TimeSpan elapsedTime;
private bool animationStarted = false;
private bool animationCompleted = false;
///
/// Gets whether the shuffle animation has completed
///
public bool IsComplete => animationCompleted;
///
/// Creates a new shuffle animation component
///
/// The game instance
/// The shuffle animation to perform
/// The deck of cards to shuffle
/// Shared sprite batch for rendering
/// Transformation matrix for scaling
public ShuffleAnimationComponent(
Game game,
ShuffleAnimation shuffleAnimation,
List deck,
SpriteBatch spriteBatch,
Matrix globalTransformation)
: base(game)
{
this.shuffleAnimation = shuffleAnimation;
this.deck = deck;
this.spriteBatch = spriteBatch;
this.globalTransformation = globalTransformation;
// Component should not be visible initially
Visible = false;
}
///
/// Initialize and start the animation
///
public override void Initialize()
{
base.Initialize();
// Create all animated cards
animatedCards = shuffleAnimation.CreateAnimatedCards(deck, spriteBatch, globalTransformation);
// Add all card components to the game
foreach (var card in animatedCards)
{
Game.Components.Add(card);
}
// Make component visible and trigger start callback
Visible = true;
animationStarted = true;
shuffleAnimation.OnAnimationStart?.Invoke();
}
///
/// Update animation progress and check for completion
///
public override void Update(GameTime gameTime)
{
base.Update(gameTime);
if (!animationStarted)
return;
elapsedTime += gameTime.ElapsedGameTime;
// Check if animation duration has elapsed
if (elapsedTime >= shuffleAnimation.Duration && !animationCompleted)
{
CompleteAnimation();
}
}
///
/// Called when animation finishes
///
private void CompleteAnimation()
{
animationCompleted = true;
// CRITICAL: Hide cards immediately before doing anything else
// This prevents the "ghost deck" from appearing at shuffle position
if (animatedCards != null)
{
foreach (var card in animatedCards)
{
card.Visible = false;
}
}
// Invoke completion callback
shuffleAnimation.OnAnimationComplete?.Invoke();
// Clean up all card components
CleanupCards();
// Remove this component from the game
Game.Components.Remove(this);
}
///
/// Removes all animated card components from the game
///
private void CleanupCards()
{
if (animatedCards != null)
{
// First make all cards invisible
foreach (var card in animatedCards)
{
card.Visible = false;
}
// Then remove them from the game
foreach (var card in animatedCards)
{
if (Game.Components.Contains(card))
{
Game.Components.Remove(card);
}
}
animatedCards.Clear();
}
}
///
/// Dispose and cleanup
///
protected override void Dispose(bool disposing)
{
if (disposing)
{
CleanupCards();
}
base.Dispose(disposing);
}
}
}