Esempio n. 1
0
 /// <summary>
 /// Handle moving the current selection to the foundation pile.
 /// </summary>
 private void HandleMoveToFoundationPile()
 {
     // If we double click on a card, try to put it on the foundation pile.
     if (DoubleClickHelper.HasDoubleClicked(MouseButton.Left) && foundationPiles.Any(pile => TryMoveCard(pile, true)))
     {
         CurrentSelection = null;
     }
 }
Esempio n. 2
0
        /// <summary>
        /// Attempts to move a card onto the <paramref name="pile"/>.
        /// </summary>
        /// <param name="pile">The <see cref="CardPile"/> to move the current selection to.</param>
        /// <param name="ignoreMousePosition">Ignores whether the mouse is over the <paramref name="pile"/>.</param>
        private bool TryMoveCard(CardPile pile, bool ignoreMousePosition)
        {
            if (CurrentSelection == null || !pile.Contains(Input.MousePosition) && !ignoreMousePosition)
            {
                return(false);
            }

            // If we are trying to move a card from the tableau pile to
            // another pile, we need to make sure that it is the top card
            // that we are trying to move.
            if (CurrentSelection.CardPile is TableauPile &&
                CurrentSelection.Card != CurrentSelection.CardPile.Peek())
            {
                return(false);
            }

            if (!pile.CanPush(CurrentSelection.Card))
            {
                return(false);
            }

            // If we can move the card onto the pile, move it and clear the selection
            Card card = CurrentSelection.CardPile.Pop();
            LerpInformation <Vector2> animationLerp = new LerpInformation <Vector2>(card.Rectangle.GetValueOrDefault().Position,
                                                                                    pile.GetCardRectangle(card).Position, 0.15f, Vector2.Lerp);

            CardMovementAnimation cardMovementAnimation = new CardMovementAnimation(card, animationLerp, pile);

            cardMovementAnimations.Add(cardMovementAnimation);
            CurrentSelection = null;

            if (pile is FoundationPile)
            {
                foundationPileAddSoundEffect.Play();
            }

            return(true);
        }
Esempio n. 3
0
        /// <summary>
        /// Handle card movement among tableau piles.
        /// </summary>
        private bool HandleTableuPileCardMovement()
        {
            // If we are moving from tableau pile to tableau pile, treat all movements as
            // moving a portion onto another tableau pile; otherwise, move the top card of the
            // selected pile to the tableau pile.
            if (CurrentSelection?.CardPile is TableauPile selectedTableauPile)
            {
                if (selectedTableauPile.SelectedPortion == null)
                {
                    // If our selection portion is null despite the fact that
                    // this tableau pile is selected, something has gone terribly
                    // wrong so we should log this occurence.

                    Logger.LogFunctionEntry(string.Empty, "NULL portion in selected tableau pile!",
                                            LoggerVerbosity.Warning);
                    return(false);
                }

                int maximumPortionLength = freeCells.Count(freeCell => freeCell.Empty) + 1;
                foreach (TableauPile tableauPile in tableauPiles)
                {
                    if (!tableauPile.Contains(Input.MousePosition) || tableauPile == selectedTableauPile)
                    {
                        continue;
                    }

                    // If we have more cards than we can move, take the most that we can.
                    int  transferAmount = Math.Min(selectedTableauPile.SelectedPortion.Count, maximumPortionLength);
                    bool canTransfer    = false;

                    // Check whether a part of the portion pile can be moved
                    // For example, suppose that the portion consisted of 4 and 3 and
                    // the user tried to move the pile onto a pile with a top card of 4.
                    // The intended result is that only the 3 is moved.
                    for (int i = selectedTableauPile.Count - transferAmount; i < selectedTableauPile.Count; i++)
                    {
                        if (!tableauPile.CanPush(selectedTableauPile[i]))
                        {
                            continue;
                        }

                        // Recalculate the transfer amount (subtract by the amount of times we traversed down the pile).
                        transferAmount = selectedTableauPile.Count - i;
                        canTransfer    = true;

                        break;
                    }

                    if (!canTransfer)
                    {
                        return(false);
                    }

                    // A temporary "stack" buffer to store the cards as we pop them from the tableau pile
                    Card[] buffer = new Card[transferAmount];
                    for (int i = 0; i < transferAmount; i++)
                    {
                        buffer[i] = selectedTableauPile.Pop();
                    }

                    // Push the cards onto the new tableau pile.
                    for (int i = transferAmount - 1; i >= 0; i--)
                    {
                        tableauPile.Push(buffer[i]);
                    }

                    CurrentSelection = null;
                    return(true);
                }
            }
            else
            {
                return(tableauPiles.Any(TryMoveCard));
            }

            return(false);
        }
Esempio n. 4
0
        /// <summary>
        /// Handle the card selection input.
        /// </summary>
        private void HandleCardSelection()
        {
            if (!Input.GetMouseButtonDown(MouseButton.Left))
            {
                return;
            }

            // A card is a "middle tableau" if it is not the top card.
            bool isMiddleTableauCardSelected    = false;
            bool isMiddleTableauPortionSelected = false;

            TableauPile selectedTableauPile = null;

            if (CurrentSelection?.CardPile is TableauPile)
            {
                selectedTableauPile = (TableauPile)CurrentSelection.CardPile;

                isMiddleTableauCardSelected    = CurrentSelection.Card != CurrentSelection.CardPile.Peek();
                isMiddleTableauPortionSelected = selectedTableauPile.SelectedPortion.Contains(CurrentSelection.Card) &&
                                                 !selectedTableauPile.SelectedPortion.Contains(selectedTableauPile.Peek());
            }

            // Check if we clicked on a card in a tableau pile
            foreach (TableauPile tableauPile in tableauPiles)
            {
                Card card = tableauPile.GetCardFromPoint(Input.MousePosition);

                // If the card is null, we didn't click on this tableau pile.
                if (card == null)
                {
                    continue;
                }

                bool selectedPortionCard = false;
                if (selectedTableauPile != null)
                {
                    selectedPortionCard = selectedTableauPile.SelectedPortion.Contains(card);
                }

                // If we have a "middle tableau" card selected and we clicked on it again, let's deselect it.
                // OR if our "middle" tableau card is in a portion and we select another card in that portion
                // (i.e. we treat portions in the middle of a tableau pile as one card in terms of selection).
                if (isMiddleTableauCardSelected && card == CurrentSelection.Card || isMiddleTableauPortionSelected && selectedPortionCard)
                {
                    CurrentSelection = null;
                    return;
                }


                // If we were previously selecting a tableau pile, cache it so we can update it.
                TableauPile oldTableauPile = null;
                if (CurrentSelection?.CardPile is TableauPile pile)
                {
                    oldTableauPile = pile;
                }

                // Store our previous selection state so we can play the correct sound effect.
                CardSelectionInformation previousSelection = CurrentSelection;
                CurrentSelection = new CardSelectionInformation(card, tableauPile);

                oldTableauPile?.UpdateSelection(tableauPile == oldTableauPile);
                tableauPile.UpdateSelection(true);

                // Play the primary sound effect if we selected the top card AND if this is our first card selection
                if (tableauPile.Peek() == card && previousSelection == null)
                {
                    cardSelectPrimarySoundEffect.Play();
                }
                else
                {
                    cardSelectSecondarySoundEffect.Play();
                }

                return;
            }

            // Check if we clicked on a free cell
            foreach (FreeCell freeCell in freeCells)
            {
                if (!freeCell.Contains(Input.MousePosition))
                {
                    continue;
                }

                // Store our previous selection state so we can play the correct sound effect.
                CardSelectionInformation previousSelection = CurrentSelection;

                // If we have selected a non-top card in a tableau pile, clicking on an empty free cell shouldn't change the selection.
                if (isMiddleTableauCardSelected && freeCell.Empty)
                {
                    return;
                }
                if (freeCell.Empty)
                {
                    return;
                }

                CurrentSelection = new CardSelectionInformation(freeCell.Value, freeCell);

                // Play if this is our first card selection
                if (previousSelection == null)
                {
                    cardSelectPrimarySoundEffect.Play();
                }
                else
                {
                    cardSelectSecondarySoundEffect.Play();
                }

                return;
            }

            // If we have selected a non-top card in a tableau pile, clicking on a foundation pile shouldn't change the selection.
            bool isSelectingFoundationPile = foundationPiles.Any(foundationPile => foundationPile.Contains(Input.MousePosition));

            if (isSelectingFoundationPile && isMiddleTableauCardSelected)
            {
                return;
            }

            // At this point, we are just clicking on an empty space.
            CurrentSelection = null;
            selectedTableauPile?.UpdateSelection(false);
        }