/// <summary> /// Initialize the <see cref="TableauPile"/>s. /// </summary> private void InitializeTableauPiles() { tableauPiles = new TableauPile[TableauPileCount]; float tableauPilePositionY = GetTableauPileStartPositionY(); float cardTextureWidth = Card.GetTexture(CardSuit.Clubs, CardRank.Ace).Width; // The width of all the tableau piles (including spacing). float fullWidth = cardTextureWidth * tableauPiles.Length + TableauPileHorizontalSpacing * (tableauPiles.Length - 1); // The amount of pixels to offset each tableau pile such that they are horizontally centered. float centreOffsetX = 0.5f * (MainGame.GameScreenWidth - fullWidth); for (int i = 0; i < tableauPiles.Length; i++) { float positionX = centreOffsetX + i * (cardTextureWidth + TableauPileHorizontalSpacing); // The height of the tableau card area, in pixels. float height = MainGame.GameScreenHeight - tableauPilePositionY - TableauPileBottomPadding; tableauPiles[i] = new TableauPile(new RectangleF(positionX, tableauPilePositionY, cardTextureWidth, height), height); } }
/// <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); }