예제 #1
0
        /**
         * Take all cards from talon and put them back in the stock
         */
        public void ReplinishStock(MoveTypes moveType = MoveTypes.NORMAL)
        {
            SnapManager talonSnapManager = talon.GetComponentInChildren <SnapManager>();

            Card[] talonCards = talonSnapManager.GetCardSet();
            if (DEBUG_MODE)
            {
                Debug.Log("Cards in talon:");
            }

            // Need to iterate in reverse order so that the cards are drawn from the stock in the same order as before
            for (int i = talonCards.Length - 1; i >= 0; i--)
            {
                Card card = talonCards[i];

                // Remove from talon
                card.transform.parent = null;

                // Move the card position from the talon to the stock
                card.transform.position = new Vector3(
                    m_stockPile.position.x,
                    m_stockPile.position.y,
                    card.transform.position.z
                    );

                // Rotate the card to be face down again
                card.Flip(false);

                // Add the card to the stock
                card.transform.parent = m_stockPile;

                // Flip the first card from the stock pile over to the talon automatically
                if (i == 0)
                {
                    // Don't track this move
                    card.MoveTo(m_talonPile, null, MoveTypes.INCOGNITO);

                    // Need to manually flip card because of not tracking
                    if (card.IsFaceDown())
                    {
                        card.Flip();
                    }
                }
            }

            // Track replinish event
            if (moveType.Equals(MoveTypes.NORMAL))
            {
                Move move = new Move();
                move.SetSpecial(true);
                Event ev = new Event();
                ev.SetType(Event.EventType.REPLINISH);
                move.AddEvent(ev);
                AddMove(move, MoveTypes.NORMAL);
            }
        }
예제 #2
0
파일: Card.cs 프로젝트: BrettFX/Solitaire
        /**
         * Event invoked by animation event in animation editor.
         * This function will be called on the last frame of the events that call it.
         */
        public void CardAnimationCompleteEvent()
        {
            if (GameManager.DEBUG_MODE)
            {
                Debug.Log("Card animation complete.");
            }

            if (!m_translating)
            {
                // Handle corner cases with flipping cards between stock and talon
                SnapManager originalSnap;
                if (m_originalParent != null)
                {
                    originalSnap = m_originalParent.GetComponent <SnapManager>();
                }
                else if (m_startParent != null)
                {
                    originalSnap = m_startParent.GetComponent <SnapManager>();
                }
                else
                {
                    // Need to determine which snap the card is closest to
                    originalSnap = Utils.GetNearestSnapManager(this);
                }

                // Set new original parent to ensure non-null value (which may be itself)
                m_originalParent = originalSnap.transform;

                // Handle corner cases
                if (m_moveType.Equals(Move.MoveTypes.UNDO) && originalSnap.BelongsTo(GameManager.Sections.TALON))
                {
                    m_originalParent = GameManager.Instance.GetStockPile();
                }

                if (m_moveType.Equals(Move.MoveTypes.REDO) && originalSnap.BelongsTo(GameManager.Sections.STOCK))
                {
                    m_originalParent = GameManager.Instance.GetTalonPile();
                }

                // Re-attach to parent now that the animation event has completed
                transform.SetParent(m_originalParent);

                // Tell the snap manager parent to stop waiting now
                if (m_originalParent != null)
                {
                    SnapManager snapManager = m_originalParent.GetComponent <SnapManager>();
                    if (snapManager != null)
                    {
                        snapManager.SetWaiting(false);
                    }
                }
            }

            m_flipping = false;
        }
예제 #3
0
파일: Utils.cs 프로젝트: BrettFX/Solitaire
        /**
         * Get the nearest snap manager to a given card. This function assumes that
         * the given card is not translating and not flipping (e.g., not performing any
         * animations). This function uses a collision vector that works like a
         * laser pointer from the origin of the card snap about the y-axis and z-axis to determine
         * if there are any snap managers nearby vertically. This
         * function is intended to be used only if the card has been double clicked.
         *
         * @param card the card to use as reference in determining the nearest snap manager.
         * @return the nearest snap manager. Returns null if no nearest snap manager exists.
         */
        public static SnapManager GetNearestSnapManager(Card card)
        {
            SnapManager nearestSnap = null;

            if (card != null)
            {
                Vector3    collisionVector = new Vector3(10.0f, 10.0f, 1000.0f);
                Collider[] hitColliders    = Physics.OverlapBox(card.transform.position, collisionVector);

                // First pass will be to find the snap manager
                // Iterate backwards to start with the nearest collisions relative to the card
                for (int i = hitColliders.Length - 1; i >= 0; i--)
                {
                    Collider hitCollider = hitColliders[i];
                    if (hitCollider.transform.CompareTag("Snap"))
                    {
                        // No need to continue once the snap has been found
                        nearestSnap = hitCollider.transform.GetComponent <SnapManager>();
                        break;
                    }
                }

                // If a snap couldn't be found then attempt to get the parent snap off of a collided card
                if (nearestSnap == null)
                {
                    // Iterate backwards to start with the nearest collisions relative to the card
                    for (int i = hitColliders.Length - 1; i >= 0; i--)
                    {
                        Collider hitCollider = hitColliders[i];
                        if (hitCollider.transform.CompareTag("Card"))
                        {
                            // Attempt to get snap from collided card
                            Card collidedCard = hitCollider.transform.GetComponent <Card>();
                            nearestSnap = collidedCard.GetComponentInParent <SnapManager>();

                            // No need to continue once the snap has been found
                            if (nearestSnap != null)
                            {
                                break;
                            }
                        }
                    }
                }
            }

            return(nearestSnap);
        }
예제 #4
0
파일: Card.cs 프로젝트: BrettFX/Solitaire
        public Transform GetCurrentParent()
        {
            // Handle corner case when parent is null by returning the transform of the nearest snap
            // only if the card isn't currently translating or flipping
            SnapManager currentSnapManager = GetComponentInParent <SnapManager>();
            Transform   currentParent      = null;

            //Transform currentParent = GetComponentInParent<SnapManager>().transform;
            if (currentSnapManager == null)
            {
                SnapManager nearestSnap = Utils.GetNearestSnapManager(this);
                if (nearestSnap != null)
                {
                    currentParent = nearestSnap.transform;
                }
            }

            return(currentParent);
        }
예제 #5
0
        /**
         * Used for reversing a replinishing event
         */
        public void DeplinishStock(MoveTypes moveType = MoveTypes.NORMAL)
        {
            SnapManager stockSnapManager = stock.GetComponentInChildren <SnapManager>();

            Card[] stockCards = stockSnapManager.GetCardSet();

            for (int i = stockCards.Length - 1; i >= 0; i--)
            {
                Card card = stockCards[i];

                // Remove from stock
                card.transform.parent = null;

                // Move the card position from the stock to the talon
                card.transform.position = new Vector3(
                    m_talonPile.position.x,
                    m_talonPile.position.y,
                    card.transform.position.z
                    );

                // Rotate the card to be face up
                if (card.IsFaceDown())
                {
                    card.Flip(false);
                }

                // Add the card to the talon
                card.transform.parent = m_talonPile;
            }

            // Track deplinish event
            if (moveType.Equals(MoveTypes.NORMAL))
            {
                Move move = new Move();
                move.SetSpecial(true);
                Event ev = new Event();
                ev.SetType(Event.EventType.DEPLINISH);
                move.AddEvent(ev);
                AddMove(move, MoveTypes.NORMAL);
            }
        }
예제 #6
0
        /**
         *
         */
        private void HandleTouchUp(Touch touch)
        {
            // Don't process if dragging isn't currently allowed
            if (!DraggingIsAllowed())
            {
                Init();
                return;
            }

            // Don't process if target card is performing an animation
            if (m_isDoingAnimation)
            {
                Init();
                return;
            }

            if (m_isCard || (m_currentObject != null && m_currentObject.CompareTag("Snap")))
            {
                m_screenPoint = Camera.main.ScreenToWorldPoint(new Vector3(touch.position.x, touch.position.y, 10));
                //Vector3 curPosition = Camera.main.ScreenToWorldPoint(m_screenPoint) + m_offset;
                Vector3 curPosition = m_screenPoint;
                if (GameManager.DEBUG_MODE)
                {
                    Debug.Log("Stopped dragging at: " + curPosition);
                    Debug.Log("Starting point was: " + m_startPos);
                }

                // Mouse up will be determined as a click if the current position is the same as the start position
                if (IsClick(curPosition))
                {
                    if (m_currentObject.CompareTag("Snap"))
                    {
                        if (m_currentObject.transform.parent.CompareTag("Stock"))
                        {
                            // Only way to get to this point is if the stock was clicked and there are no cards on it
                            // Transfer all cards attached to talon back to stock
                            GameManager.Instance.SetBlocked(true);
                            GameManager.Instance.ReplinishStock();
                        }
                    }
                    else
                    {
                        Card cardOfInterest = m_currentObject.GetComponent <Card>();
                        if (cardOfInterest.GetStartParent() != null)
                        {
                            string cardParentSetTag = cardOfInterest.GetStartParent().parent.tag;

                            // Determine if double click
                            float timeDiff = Time.timeSinceLevelLoad - m_timeSinceLastClick;
                            if (GameManager.DEBUG_MODE)
                            {
                                Debug.Log("Time difference since last click: " + timeDiff);
                            }
                            bool doubleClick = (m_timeSinceLastClick >= 0) && timeDiff <= CLICK_DIFF_TIME_THRESHOLD;

                            Transform nextMove = null;

                            // Don't apply double-click logic to stock
                            // Also don't permit click spamming for drawing cards (use game manager action/event block)
                            if (cardParentSetTag.Equals("Stock") && !GameManager.Instance.IsBlocked())
                            {
                                // Move the card to the talon pile once it has been clicked on the stock (draw card)
                                GameManager.Instance.SetBlocked(true); // Place temporary lock to prevent concurrent actions/events
                                cardOfInterest.MoveTo(GameManager.Instance.GetTalonPile());
                            }
                            else if (doubleClick || SettingsManager.Instance.IsSingleTapAutoCompleteTrigger())
                            {
                                // Determine the next valid move. Supply the dragged cards count so prevent the scenario in which
                                // more than one card is dragged to a foundation in one event.
                                nextMove = GameManager.Instance.GetNextAvailableMove(cardOfInterest, m_draggedCards.Length);
                                if (GameManager.DEBUG_MODE)
                                {
                                    Debug.Log("Next Move: " + nextMove);
                                }

                                // If double click and there is a valid next move
                                // Then, automatically move the double clicked card to the most appropriate location.
                                if (nextMove)
                                {
                                    // Move all cards in set of dragged cards (can be 1)
                                    GameManager.Instance.SetBlocked(true); // Place temporary lock to prevent concurrent actions/events
                                    cardOfInterest.MoveTo(nextMove, m_draggedCards);
                                }
                            }

                            // Handle cleanup case
                            if (!cardParentSetTag.Equals("Stock") && !nextMove)
                            {
                                // Need to set the parent back to the original parent for card(s) in the set of dragged cards.
                                foreach (Card card in m_draggedCards)
                                {
                                    card.transform.parent = card.GetStartParent();

                                    // Ensure all mesh colliders are re-enabled (corner case when double clicking a face down card)
                                    card.GetComponent <MeshCollider>().enabled = true;
                                }

                                // Unblock actions/events since invalid click
                                GameManager.Instance.SetBlocked(false);
                            }
                        }
                    }

                    // Keep track of the time of last click
                    m_timeSinceLastClick = Time.timeSinceLevelLoad;
                    return;
                }

                // Don't allow dropping stock cards or face-down cards
                Card cardCheck = m_currentObject.GetComponent <Card>();
                bool valid     = !m_isStockCard && cardCheck != null && !cardCheck.IsFaceDown();

                // Validate the dragged location to determine if the card should be snapped back to original location
                // or snapped to the respective target (e.g., attempted drag location)
                Vector3 collisionVector = new Vector3(10.0f, 10.0f, 1000.0f);
                bool    collides        = Physics.CheckBox(curPosition, collisionVector);

                if (collides && valid)
                {
                    Collider[] hitColliders = Physics.OverlapBox(curPosition, collisionVector);
                    int        i            = 0;
                    while (i < hitColliders.Length)
                    {
                        Transform collidedTransform = hitColliders[i].GetComponent <Transform>();
                        if (GameManager.DEBUG_MODE)
                        {
                            Debug.Log("Would collide with object: " + collidedTransform);
                        }

                        // Snap to the snap location if there is one
                        if (collidedTransform.CompareTag("Snap"))
                        {
                            // Don't allow dropping dragged cards in prohibited locations
                            SnapManager snapManager = collidedTransform.GetComponent <SnapManager>();
                            if (GameManager.PROHIBITED_DROP_LOCATIONS.Contains(collidedTransform.parent.tag))
                            {
                                if (GameManager.DEBUG_MODE)
                                {
                                    Debug.Log("Can't manually drop card in " + collidedTransform.parent.tag);
                                }
                                valid = false;
                                break;
                            }

                            // Make sure there isn't already a card attached to the snap (otherwise need to search for card)
                            if (snapManager.HasCard())
                            {
                                if (GameManager.DEBUG_MODE)
                                {
                                    Debug.Log("Snap already has a card, skipping...");
                                }
                            }
                            else
                            {
                                if (GameManager.DEBUG_MODE)
                                {
                                    Debug.Log("Placing card(s) in: " + collidedTransform.parent.tag);
                                }

                                // Set the new position relative to the snap, adjusting the z value appropriately
                                Vector3 newPos = new Vector3(
                                    collidedTransform.position.x,
                                    collidedTransform.position.y,
                                    -1.0f                        // Set to a z value of -1 for initial card in stack
                                    );

                                // Need to iterate the set of dragged cards and adjust the position accordingly
                                bool isFoundation = collidedTransform.parent.CompareTag("Foundations");

                                // Assert that there is only one card being placed if target is foundation
                                if (isFoundation && m_draggedCards.Length > 1)
                                {
                                    if (GameManager.DEBUG_MODE)
                                    {
                                        Debug.Log("Cannot move more than one card at once to a foundation.");
                                    }
                                    valid = false;
                                    break;
                                }

                                // General validation step to take card value and suit into consideration
                                valid = snapManager.IsValidMove(m_draggedCards[0]);
                                if (valid)
                                {
                                    float yOffset = isFoundation ? 0.0f : GameManager.FOUNDATION_Y_OFFSET;
                                    int   j       = 0;
                                    foreach (Card card in m_draggedCards)
                                    {
                                        Vector3 cardPosition = card.transform.position;
                                        Vector3 newCardPos   = new Vector3(newPos.x, newPos.y - (yOffset * j), newPos.z - j);
                                        card.transform.position = newCardPos;

                                        // Add the card to the stack
                                        card.transform.parent = collidedTransform;

                                        // Re-enable the mesh colliders on the cards
                                        card.GetComponent <MeshCollider>().enabled = true;

                                        j++;
                                    }
                                }

                                break;
                            }
                        }
                        else if (collidedTransform.CompareTag("Card"))
                        {
                            // Determine if the card was the same one that is being dragged/dropped
                            if (collidedTransform.Equals(m_currentObject.transform))
                            {
                                if (GameManager.DEBUG_MODE)
                                {
                                    Debug.Log("Collided object is self, skipping...");
                                }
                            }
                            else
                            {
                                // Get the card object to determine if the respective card is stackable
                                Card targetCard = collidedTransform.GetComponent <Card>();
                                if (!targetCard.IsStackable())
                                {
                                    if (GameManager.DEBUG_MODE)
                                    {
                                        Debug.Log("Card is not stackable, skipping...");
                                    }
                                }
                                else
                                {
                                    // Reference the snap manager the card is attached to
                                    SnapManager snapManager = targetCard.GetComponentInParent <SnapManager>();

                                    if (GameManager.DEBUG_MODE)
                                    {
                                        Debug.Log("Placing card(s) in: " + collidedTransform.parent.parent.tag);
                                    }
                                    bool isFoundation = collidedTransform.parent.parent.CompareTag("Foundations");

                                    // Assert that there is only one card being placed if target is foundation
                                    if (isFoundation && m_draggedCards.Length > 1)
                                    {
                                        if (GameManager.DEBUG_MODE)
                                        {
                                            Debug.Log("Cannot move more than one card at once to a foundation.");
                                        }
                                        valid = false;
                                        break;
                                    }

                                    // General validation step to take card value and suit into consideration
                                    valid = snapManager.IsValidMove(m_draggedCards[0]);
                                    if (valid)
                                    {
                                        float yOffset = isFoundation ? 0.0f : GameManager.FOUNDATION_Y_OFFSET;

                                        // Offset y position by specified foundation y-offset
                                        // so that the card that is below is still shown
                                        Vector3 newPos = new Vector3(
                                            collidedTransform.position.x,
                                            collidedTransform.position.y - yOffset,
                                            collidedTransform.position.z - 1.0f
                                            );

                                        // Need to iterate the set of dragged cards and adjust the position accordingly
                                        int j = 0;
                                        foreach (Card card in m_draggedCards)
                                        {
                                            Vector3 cardPosition = card.transform.position;
                                            Vector3 newCardPos   = new Vector3(newPos.x, newPos.y - (yOffset * j), newPos.z - j);
                                            card.transform.position = newCardPos;

                                            // Add the card to the stack (note that the parent is not the collided transform)
                                            card.transform.parent = collidedTransform.parent;

                                            // Re-enable the mesh colliders on the cards
                                            card.GetComponent <MeshCollider>().enabled = true;

                                            j++;
                                        }
                                    }

                                    break;
                                }
                            }
                        }
                        else
                        {
                            // If collided with anything else other than a card or a snap then deemed as invalid
                            valid = false;
                        }

                        i++;
                    }
                }

                // Need to do one last check to determine if the cards were moved to the same location
                if (valid)
                {
                    Card    topCard         = m_draggedCards[0];
                    Vector3 topCardStartPos = topCard.GetStartPos();
                    valid = !(topCard.transform.position.x == topCardStartPos.x &&
                              topCard.transform.position.y == topCardStartPos.y);
                }

                if (!valid)
                {
                    if (GameManager.DEBUG_MODE)
                    {
                        Debug.Log("Invalid Move.");
                    }

                    // If the drag location is deemed invalid then we should snap back to starting position
                    // Need to iterate the list of dragged cards and set each card back to their respective
                    // starting position and starting parent
                    if (m_draggedCards != null)
                    {
                        foreach (Card card in m_draggedCards)
                        {
                            // Hanle corner case for when origin was the stock pile
                            if (m_originSnapManager.BelongsTo(GameManager.Sections.STOCK))
                            {
                                Vector3 startPos = card.GetStartPos();
                                bool    samePos  = card.transform.position.x == startPos.x &&
                                                   card.transform.position.y == startPos.y;
                                // Only handle this corner case if the card's curren position isn't the same
                                // as it's starting position.
                                if (!samePos)
                                {
                                    Transform talonTransform = GameManager.Instance.GetTalonPile();
                                    card.transform.position = talonTransform.position;
                                    card.transform.parent   = talonTransform;
                                }
                            }
                            else
                            {
                                card.transform.position = card.GetStartPos();
                                card.transform.parent   = card.GetStartParent();
                            }

                            // Re-enable the mesh colliders on the cards
                            card.GetComponent <MeshCollider>().enabled = true;
                        }
                    }
                }
                else
                {
                    // Register the manual move if it was valid
                    Move move = new Move();
                    move.SetCards(m_draggedCards);
                    move.SetPreviousParent(m_originSnapManager.transform);
                    move.SetNextParent(m_draggedCards[0].transform.parent);
                    GameManager.Instance.AddMove(move, Move.MoveTypes.NORMAL);

                    // Play the card set sound one shot so that other clips can play at the same time
                    AudioSource cardSetSound = SettingsManager.Instance.cardSetSound;
                    cardSetSound.PlayOneShot(SettingsManager.Instance.cardSetSoundClip);

                    // Track the total number of moves with stats manager
                    StatsManager.Instance.TallyMove();
                }

                // Remove temporary locks set during dragging
                if (m_dragged)
                {
                    // Can stop waiting now that the move is complete
                    // Evaluate only if origin snap manager isn't null
                    if (m_originSnapManager != null)
                    {
                        m_originSnapManager.SetWaiting(false);
                    }

                    GameManager.Instance.SetBlocked(false);
                    m_dragged = false;
                }
            }

            // Always initialize as a last step
            Init();
        }
예제 #7
0
        /**
         *
         */
        private void HandleTouchDown(Touch touch)
        {
            // Don't process if dragging isn't currently allowed
            if (!DraggingIsAllowed())
            {
                return;
            }

            Ray raycast = Camera.main.ScreenPointToRay(touch.position);

            if (Physics.Raycast(raycast, out RaycastHit raycastHit))
            {
                m_screenPoint   = Camera.main.ScreenToWorldPoint(new Vector3(touch.position.x, touch.position.y, 10));
                m_startPos      = m_screenPoint;
                m_currentObject = raycastHit.collider.gameObject;
                m_isCard        = raycastHit.collider.CompareTag("Card");
                if (m_isCard)
                {
                    // Assert that the card isn't face down (permit if card is in stock pile)
                    Card        targetCard = m_currentObject.GetComponent <Card>();
                    SnapManager parentSnap = targetCard.GetComponentInParent <SnapManager>();

                    // Don't deem as card if the target card is face down and doesn't belong to the stock
                    m_isCard = !(targetCard.IsFaceDown() && !parentSnap.BelongsTo(GameManager.Sections.STOCK));
                }
            }

            // If card, we need to get a list of the cards that are to be dragged (through the use of the Snap Manager)
            if (m_isCard && m_currentObject.transform.parent != null)
            {
                Card targetCard = m_currentObject.GetComponent <Card>();
                m_isDoingAnimation = targetCard.IsTranslating() || targetCard.IsFlipping();
                if (m_isDoingAnimation)
                {
                    if (GameManager.DEBUG_MODE)
                    {
                        Debug.Log("Card is doing an animation and cannot be dragged!");
                    }
                    return;
                }

                // Initialize the dragged cards list by referencing the set of cards that are attached to the
                // respective snap that one or many cards are to be dragged from.
                m_draggedCards = m_currentObject.GetComponentInParent <SnapManager>().GetCardSet(targetCard);
                if (m_draggedCards != null && m_draggedCards.Length > 0)
                {
                    // Check the first card to see if it's a stock card
                    if (GameManager.DEBUG_MODE)
                    {
                        Debug.Log("Tag Clicked: " + m_draggedCards[0].transform.parent.parent.tag);
                    }
                    m_isStockCard = m_draggedCards[0].transform.parent.parent.CompareTag("Stock");
                    if (GameManager.DEBUG_MODE)
                    {
                        Debug.Log("Is Stock Card: " + m_isStockCard);
                    }

                    // Set each dragged card's start position and parent
                    int i = 0;
                    m_originSnapManager = m_draggedCards[0].GetComponentInParent <SnapManager>();
                    m_originSnapManager.SetWaiting(true); // Wait until cards are dropped and validated before flipping any cards in tableau

                    foreach (Card card in m_draggedCards)
                    {
                        card.SetStartPos(card.transform.position);
                        card.SetStartParent(card.transform.parent);

                        // Temporarily disable the mesh collider for all cards except the first one in the set of dragged cards.
                        if (i != 0)
                        {
                            card.GetComponent <MeshCollider>().enabled = false;
                        }
                        i++;
                    }
                }
            }
            else
            {
                // Only initialize if not a snap
                if (!m_currentObject.CompareTag("Snap"))
                {
                    Init();
                }
            }
        }
예제 #8
0
        /**
         * Perform the core function for running the auto complete process.
         * This coroutine will rapidly move cards from the tableau to the foundation
         * and automatically complete the game once a valid winning state has been
         * determined by the system.
         */
        private IEnumerator AutoWinCoroutine()
        {
            SetDoingAutoWin(true);

            int attempts    = 0;
            int maxAttempts = 5000;

            // Build min priority queue based on all cards in tableau (prioritize lower value cards)
            PriorityQueue <Card> cardQueue = new PriorityQueue <Card>(true);

            // Add max attempts in case there is some corner case that occurs and causes a fail
            while (attempts < maxAttempts)
            {
                yield return(new WaitForEndOfFrame());

                // Break out of the loop if the win state has been met
                if (HasWon())
                {
                    break;
                }

                SnapManager[] tableauSnaps = tableau.GetComponentsInChildren <SnapManager>();
                foreach (SnapManager tableauSnap in tableauSnaps)
                {
                    // Get only the top card for now
                    Card topCard = tableauSnap.GetTopCard();
                    if (topCard != null)
                    {
                        cardQueue.Enqueue(topCard.value, topCard);
                    }
                }

                // Dequeue cards from priority queue and move each one to the foundation
                while (cardQueue.Count > 0)
                {
                    Card      priorityCard = cardQueue.Dequeue();
                    Transform nextMove     = GetNextAvailableMove(priorityCard);

                    // Only process move if one existed and if it is to a foundation
                    if (nextMove)
                    {
                        SnapManager currentSnapManager = priorityCard.GetComponentInParent <SnapManager>();
                        SnapManager nextSnapManager    = nextMove.GetComponent <SnapManager>();
                        bool        validMove          = nextSnapManager.belongingSection.Equals(Sections.FOUNDATIONS);
                        if (validMove)
                        {
                            // Make note of the current amount of attached cards
                            int currentCardCount = nextSnapManager.GetCardCount();

                            priorityCard.MoveTo(nextMove);

                            // Wait until the card is finished translating, is attached to the snap, and the current
                            // card count has incremented by one
                            yield return(new WaitUntil(() => {
                                return priorityCard.transform.parent != null &&
                                !priorityCard.IsTranslating() &&
                                nextSnapManager.GetCardCount() >= (currentCardCount + 1);
                            }));

                            // Add the current snap manager's top card to the priority queue
                            Card nextTopCard = currentSnapManager.GetTopCard();
                            if (nextTopCard != null)
                            {
                                cardQueue.Enqueue(nextTopCard.value, nextTopCard);
                            }
                        }
                    }
                }

                attempts++;
            }

            SetDoingAutoWin(false);
            m_autoWinComplete = true;
        }
예제 #9
0
파일: Card.cs 프로젝트: BrettFX/Solitaire
        private void HandleTranslation()
        {
            if (m_translating)
            {
                float zOffset = m_flipping ? GameManager.Z_OFFSET_DRAGGING / 2.0f : GameManager.Z_OFFSET_DRAGGING;
                if (m_draggedCards != null && m_draggedCards.Length > 1)
                {
                    foreach (Card card in m_draggedCards)
                    {
                        // Ensure that the z-offset is applied to the target translation position to avoid clipping
                        Vector3 modTargetPos = card.GetTargetTranslatePosition();
                        modTargetPos = new Vector3(
                            modTargetPos.x,
                            modTargetPos.y,
                            -(Mathf.Abs(modTargetPos.z) + zOffset)
                            );

                        // Use linear interpolation (lerp) to move from point a to point b within a specific amount of time
                        card.transform.position = Vector3.Lerp(
                            card.GetStartPos(),
                            modTargetPos,
                            m_totalTime
                            );

                        // Stop translating once the total time has elapsed for linear interpolation
                        m_translating = m_totalTime < 1.0f;
                    }
                }
                else
                {
                    // Ensure that the z-offset is applied to the target translation position to avoid clipping
                    Vector3 modTargetPos = new Vector3(
                        m_targetTranslatePos.x,
                        m_targetTranslatePos.y,
                        -(Mathf.Abs(m_targetTranslatePos.z) + zOffset)
                        );

                    // Use linear interpolation (lerp) to move from point a to point b within a specific amount of time
                    transform.position = Vector3.Lerp(
                        GetStartPos(),
                        modTargetPos,
                        m_totalTime
                        );

                    // Stop translating once the total time has elapsed for linear interpolation
                    m_translating = m_totalTime < 1.0f;

                    // Only flip card if it's face down and processing normal move
                    if (currentState.Equals(CardState.FACE_DOWN) && m_moveType.Equals(Move.MoveTypes.NORMAL))
                    {
                        SnapManager targetSnapManager = m_targetTranslateSnap.GetComponent <SnapManager>();

                        // Flip the card with an animation
                        Flip();

                        // Stage the event
                        Event evt = new Event();
                        evt.SetType(Event.EventType.FLIP);
                        evt.SetCard(this);
                        // Setting relative snap manager to this instance for locking when reversing event
                        evt.SetRelativeSnapManager(targetSnapManager);
                        GameManager.Instance.AddEventToLastMove(evt);
                    }
                }

                // Accumulate total time with respect to the card translation speed
                m_totalTime += Time.deltaTime / GameManager.Instance.GetCardTranslationSpeed();

                // Perform final steps after translation is complete
                if (!m_translating)
                {
                    // Play the card set sound one shot so more than one clip can play at a time
                    SettingsManager.Instance.cardSetSound.PlayOneShot(SettingsManager.Instance.cardSetSoundClip);

                    SnapManager targetSnapManager = m_targetTranslateSnap.GetComponent <SnapManager>();

                    if (m_draggedCards != null && m_draggedCards.Length > 1)
                    {
                        // Don't need to check current state when dragging more than one card
                        // since the only case when the card is face down is if it came from the
                        // stock pile.
                        foreach (Card card in m_draggedCards)
                        {
                            // Place the card in the respective snap parent (this ensures proper card order)
                            card.transform.parent = m_targetTranslateSnap;

                            // Re-enable the mesh colliders on the cards
                            card.GetComponent <MeshCollider>().enabled = true;
                        }
                    }
                    else
                    {
                        // Only reattach to parent here if this card is not presently flipping
                        if (!m_flipping)
                        {
                            transform.parent = m_targetTranslateSnap;

                            // Re-enable the mesh colliders on this card
                            GetComponent <MeshCollider>().enabled = true;
                        }
                    }

                    // Need to remove any locks and blocks on parent snap manager and game manager instance caused by events
                    targetSnapManager.SetWaiting(false);
                    GameManager.Instance.SetBlocked(false);

                    // Also tell the original snap manager to stop waiting if it is
                    if (m_startParent != null)
                    {
                        m_startParent.GetComponent <SnapManager>().SetWaiting(false);
                    }

                    // Reset the total time for correct linear interpolation (lerp)
                    m_totalTime = 0.0f;
                }
            }
        }
예제 #10
0
파일: Card.cs 프로젝트: BrettFX/Solitaire
        public CardState Flip(bool animate = true)
        {
            m_flipping = true;

            m_flipped    = !m_flipped;
            currentState = m_flipped ? CardState.FACE_UP : CardState.FACE_DOWN;

            // Keep track of original parent so that it can be restored after flipping
            m_originalParent = transform.parent;

            // Need to detatch from parent to avoid odd clipping behavior
            // Will re-attach once any animations complete
            transform.SetParent(null);

            // Need to temporarily disable mesh collider and remove from parent when doing rotation
            MeshCollider meshCollider = gameObject.GetComponent <MeshCollider>();

            meshCollider.enabled = false;

            if (animate)
            {
                // Need to tell the snap manager parent to wait until animation is done
                if (m_originalParent != null)
                {
                    SnapManager snapManager = m_originalParent.GetComponent <SnapManager>();
                    if (snapManager != null)
                    {
                        snapManager.SetWaiting(true);
                    }
                }
                // Handle corner case when original parent is null and when card came from stock
                else
                {
                    if (m_startParent != null)
                    {
                        SnapManager startSnapManager = m_startParent.GetComponent <SnapManager>();
                        // Need to set original parent to talon pile so the card doesn't snap back to stock
                        if (startSnapManager.BelongsTo(GameManager.Sections.STOCK))
                        {
                            m_originalParent = GameManager.Instance.GetTalonPile();
                        }
                    }
                }

                transform.position = new Vector3(
                    transform.position.x,
                    transform.position.y,
                    -(Mathf.Abs(transform.position.z) + Mathf.Abs(GameManager.Z_OFFSET_DRAGGING))
                    );

                // Implement flip animation
                string trigger = m_flipped ? "FlipFaceUp" : "FlipFaceDown";
                m_animator = GetComponent <Animator>();
                m_animator.SetTrigger(trigger);

                AudioSource cardFlipSound = SettingsManager.Instance.cardFlipSound;
                cardFlipSound.PlayOneShot(SettingsManager.Instance.cardFlipSoundClip);
            }
            else
            {
                int degrees = m_flipped ? 180 : 0;
                // Flip the card 180 degrees about the y axis
                transform.rotation = Quaternion.Euler(0, degrees, 0);
                transform.SetParent(m_originalParent);
                m_flipping = false;
            }

            // Re-enable the mesh collider
            meshCollider.enabled = true;
            return(currentState);
        }
예제 #11
0
파일: Card.cs 프로젝트: BrettFX/Solitaire
        /**
         * Move this card instance and/or other cards in it's card set to the specified target snap transform
         * @param Transform snap the target snap transform to move this card to
         * @param Card[] cardSet the set of dragged cards to handle translation all at once
         *                       with respect to this card instance. Defaults to null if a card set is not provided.
         *                       If the card set has only one card in it then it's assumed that the one card is
         *                       this card instance and will be processed as such.
         * @param MoveTypes moveType the type of move that determines how the move should be tracked in the GameManager.
         */
        public void MoveTo(Transform snap, Card[] cardSet = null, Move.MoveTypes moveType = Move.MoveTypes.NORMAL)
        {
            // Prepare the move object
            m_move     = new Move();
            m_moveType = moveType;

            // Set the target card based on value of card set
            // (if card set is null then create a new card set with this card as the only element)
            m_move.SetCards(cardSet ?? (new Card[] { this }));

            // We know that the card has/had a parent
            m_move.SetPreviousParent(m_startParent);

            // Need to get what the snap belongs to so that the card is placed in the correct location
            SnapManager snapManager    = snap.GetComponent <SnapManager>();
            bool        faceDownTarget = snapManager.HasCard() && snapManager.GetTopCard().IsFaceDown();

            GameManager.Sections targetSection = snapManager.belongingSection;

            // Set the next parent in the move
            m_move.SetNextParent(snapManager.transform);

            // Need to target the top card in the respective tableau pile and offset the y and z positions
            Transform tableauHasCardTarget = targetSection.Equals(GameManager.Sections.TABLEAU) && snapManager.HasCard() ?
                                             snapManager.GetTopCard().transform : snap;

            // Setting for reference to new parent snap
            m_targetTranslateSnap = snap;
            m_targetTranslatePos  = m_targetTranslateSnap.position; // Defaults to target snap position

            // Keep track of the starting position
            m_startPos = transform.position;

            m_draggedCards = cardSet;

            // Tell the snap manager currently associated with the card(s) to wait until animations are complete
            SnapManager currentSnap = GetComponentInParent <SnapManager>();

            if (currentSnap != null)
            {
                // Set the start parent here so that the current snap can be told to stop waiting later
                SetStartParent(currentSnap.transform);
                currentSnap.SetWaiting(true);
            }

            // Process a bit differently if a card set has been provided
            if (m_draggedCards != null && m_draggedCards.Length > 1)
            {
                // Do a first pass-through to remove parent and bring z-value of each of the dragged cards
                // to the z-offset dragging value
                for (int i = 0; i < m_draggedCards.Length; i++)
                {
                    Card draggedCard = m_draggedCards[i];
                    draggedCard.transform.parent = null;

                    // Keep track of each card's starting position
                    draggedCard.SetStartPos(draggedCard.transform.position);

                    float yOffset;
                    // Apply y-offset when dragging multiple cards (start without y-offset if there isn't a card on the snap)
                    // Handle case when action was an undo and the top card in the target snap is facedown
                    // (only the first card in the the set of dragged cards should have the face down y-offset applied in this case).
                    if (faceDownTarget && i == 0)
                    {
                        yOffset = GameManager.FACE_DOWN_Y_OFFSET;
                    }
                    else
                    {
                        if (faceDownTarget)
                        {
                            // Need to compensate for the fact that the first card applied face down y-offset
                            yOffset = (GameManager.FOUNDATION_Y_OFFSET * i) + GameManager.FACE_DOWN_Y_OFFSET;
                        }
                        else
                        {
                            // Process normally (e.g., not undoing a flip event)
                            yOffset = GameManager.FOUNDATION_Y_OFFSET * (snapManager.HasCard() ? i + 1 : i);
                        }
                    }

                    Vector3 newTargetPos = new Vector3(
                        tableauHasCardTarget.position.x,
                        tableauHasCardTarget.position.y - yOffset,
                        tableauHasCardTarget.position.z - (i + 1)
                        );

                    // Set the new translate position for the dragged card
                    draggedCard.SetTargetTranslatePosition(newTargetPos);

                    // Set the z-value of the transform to move to be high enough to hover over all other cards
                    draggedCard.transform.position = new Vector3(
                        draggedCard.transform.position.x,
                        draggedCard.transform.position.y,
                        -(GameManager.Z_OFFSET_DRAGGING + i)
                        );
                }
            }
            else // Otherwise, process on one card
            {
                // transform position is a special case for the Tableau cards due to y-offset in addition to z-offset
                if (targetSection.Equals(GameManager.Sections.TABLEAU) && snapManager.HasCard())
                {
                    Vector3 newTargetPos = new Vector3(
                        tableauHasCardTarget.position.x,
                        tableauHasCardTarget.position.y - (faceDownTarget ? GameManager.FACE_DOWN_Y_OFFSET : GameManager.FOUNDATION_Y_OFFSET),
                        tableauHasCardTarget.position.z - 1
                        );

                    m_targetTranslatePos = newTargetPos;
                }

                transform.parent = null;         // Temporarily detatch from the parent
                SetStartPos(transform.position); // Keep track of this card instance start position

                // Set the z-value of the transform to move to be high enough to hover over all other cards
                transform.position = new Vector3(
                    transform.position.x,
                    transform.position.y,
                    -GameManager.Z_OFFSET_DRAGGING
                    );
            }

            // Add the move to the game manager instance (only if normal move and not undone or redone)
            if (moveType == Move.MoveTypes.NORMAL)
            {
                GameManager.Instance.AddMove(m_move, moveType);
            }

            // Track the total number of moves with stats manager
            StatsManager.Instance.TallyMove();

            // Begin the translating animation
            m_translating = true;
        }