// Find the match that this hexagon piece is part of (implementation)
    private void GetMatchingPiecesAt(HexagonPiece piece, HexagonMatch match)
    {
        bool isPieceAddedToMatch = false;

        // Iterate over each possible tuple that is formed with this hexagon piece and see if that tuple is a match
        for (int i = 0; i < 6; i++)
        {
            HexagonTuple tuple = GetTupleAtCorner(piece.X, piece.Y, (HexagonPiece.Corner)i);
            if (!tuple.IsEmpty && tuple.IsMatching)
            {
                if (!isPieceAddedToMatch)
                {
                    match.Add(piece);
                    isPieceAddedToMatch = true;
                }

                if (matchesOnGridSet.Add(tuple.piece1))
                {
                    GetMatchingPiecesAt(tuple.piece1, match);
                }
                if (matchesOnGridSet.Add(tuple.piece2))
                {
                    GetMatchingPiecesAt(tuple.piece2, match);
                }
                if (matchesOnGridSet.Add(tuple.piece3))
                {
                    GetMatchingPiecesAt(tuple.piece3, match);
                }
            }
        }
    }
        // Find the match that this hexagon piece is part of (implementation)
        private void TryGetMatchingPiecesAt(HexagonPiece piece, HexagonMatch match)
        {
            bool isPieceAddedToMatch = false;

            // Iterate over each possible group that is formed with this hexagon piece and see if that group is a match
            for (int i = 0; i < 6; i++)
            {
                HexagonGroup _group = GetGroupAtCorner(piece.GridPos.x, piece.GridPos.y, (HexagonPiece.Edge)i);
                if (_group.IsEmpty || !_group.IsMatching)
                {
                    continue;
                }
                if (!isPieceAddedToMatch)
                {
                    match.Add(piece);
                    isPieceAddedToMatch = true;
                }
                if (matchesOnGridSet.Add(_group.Piece1))
                {
                    TryGetMatchingPiecesAt(_group.Piece1, match);
                }
                if (matchesOnGridSet.Add(_group.Piece2))
                {
                    TryGetMatchingPiecesAt(_group.Piece2, match);
                }
                if (matchesOnGridSet.Add(_group.Piece3))
                {
                    TryGetMatchingPiecesAt(_group.Piece3, match);
                }
            }
        }
 /// <summary>
 /// Returns true if there are no possible moves that result in a match on the grid
 /// </summary>
 /// <returns>true; no more move left, false moves possible.</returns>
 public bool IsDeadlocked()
 {
     matchesOnGridSet.Clear();
     // Check only on even coloums; checking all coloums is redundant.
     for (int x = 0; x < gridInfo.x; x += 2)
     {
         for (int y = 0; y < gridInfo.y; y++)
         {
             for (int i = 0; i < 6; i++)
             {
                 HexagonGroup group = GetGroupAtCorner(x, y, (HexagonPiece.Edge)i);
                 if (!group.IsEmpty)
                 {
                     for (int j = 0; j < 2; j++)
                     {
                         group.RotateClockwise();
                         HexagonMatch match = TryGetMatchingPiecesAt(group);
                         if (match != null)
                         {
                             PoolManager.Instance.Push(match);
                             group.RotateClockwise(2 - j);
                             return(false);
                         }
                     }
                     group.RotateClockwise();
                 }
             }
         }
     }
     return(true);
 }
Exemple #4
0
        private void ProcessMatch(HexagonMatch match)
        {
            _score += _scoreMultiplier * match.Count;
            UIManager.Instance.UpdateScore(_score);
            SoundManager.Instance.PlayFx("cluster");

            for (int i = match.Count - 1; i >= 0; i--)
            {
                // Destroy the matching pieces in a fashionable way
                GridManager.Instance[match[i].GridPos.x][match[i].GridPos.y] = null; // Mark that slot as empty
                AnimationManager.Instance.BlowPieceAway(match[i]);
                // Check if a bomb was attached to the destroyed piece
                for (int j = _bombs.Count - 1; j >= 0; j--)
                {
                    if (_bombs[j].HexagonElement == match[i])
                    {
                        PoolManager.Instance.Push(_bombs[j]);
                        SoundManager.Instance.PlayFx("bomb_remove");
                        // This bomb is now defused, move the last bomb to this index
                        if (j < _bombs.Count - 1)
                        {
                            _bombs[j] = _bombs[_bombs.Count - 1];
                        }

                        _bombs.RemoveAt(_bombs.Count - 1);
                    }
                }
            }

            PoolManager.Instance.Push(match);
        }
    private void ProcessMatch(HexagonMatch match)
    {
        score += scoreMultiplier * match.Count;
        UIManager.Instance.UpdateScore(score);

        for (int i = match.Count - 1; i >= 0; i--)
        {
            // Destroy the matching pieces in a fashionable way
            GridManager.Instance[match[i].X][match[i].Y] = null;             // Mark that slot as empty
            AnimationManager.Instance.BlowPieceAway(match[i]);

            // Check if a bomb was attached to the destroyed piece
            for (int j = bombs.Count - 1; j >= 0; j--)
            {
                if (bombs[j].AttachedPiece == match[i])
                {
                    PoolManager.Instance.Push(bombs[j]);

                    // This bomb is now defused, move the last bomb to this index
                    if (j < bombs.Count - 1)
                    {
                        bombs[j] = bombs[bombs.Count - 1];
                    }

                    bombs.RemoveAt(bombs.Count - 1);
                }
            }
        }

        PoolManager.Instance.Push(match);
    }
        // Finds the match that have at least one hexagon piece from this group
        public HexagonMatch TryGetMatchingPiecesAt(HexagonGroup group)
        {
            matchesOnGridSet.Clear();
            HexagonMatch result = TryGetMatchingPiecesAt(group.Piece1);

            if (result == null)
            {
                result = TryGetMatchingPiecesAt(group.Piece2);
            }
            if (result == null)
            {
                result = TryGetMatchingPiecesAt(group.Piece3);
            }
            return(result);
        }
    // Finds the match that have at least one hexagon piece from this tuple
    public HexagonMatch GetMatchingPiecesAt(HexagonTuple tuple)
    {
        matchesOnGridSet.Clear();

        HexagonMatch result = GetMatchingPiecesAt(tuple.piece1);

        if (result == null)
        {
            result = GetMatchingPiecesAt(tuple.piece2);
            if (result == null)
            {
                result = GetMatchingPiecesAt(tuple.piece3);
            }
        }

        return(result);
    }
    // Find the match that this hexagon piece is part of
    public HexagonMatch GetMatchingPiecesAt(HexagonPiece piece)
    {
        // Don't search the piece for match if it is already searched before
        if (!matchesOnGridSet.Add(piece))
        {
            return(null);
        }

        HexagonMatch result = PoolManager.Instance.PopMatch();

        GetMatchingPiecesAt(piece, result);
        if (result.Count > 0)
        {
            return(result);
        }

        PoolManager.Instance.Push(result);
        return(null);
    }
        // Finds all matches on the grid
        public List <HexagonMatch> GetAllMatchingPiecesOnGrid()
        {
            matchesOnGrid.Clear();
            matchesOnGridSet.Clear();

            // We can skip odd columns, if there is a match, it will be found while iterating the even columns
            for (int x = 0; x < gridInfo.x; x += 2)
            {
                for (int y = 0; y < gridInfo.y; y++)
                {
                    HexagonMatch match = TryGetMatchingPiecesAt(grid[x][y]);
                    if (match != null)
                    {
                        matchesOnGrid.Add(match);
                    }
                }
            }
            return(matchesOnGrid);
        }
    // Returns true if there are no possible moves that result in a match on the grid
    public bool CheckDeadlock()
    {
        matchesOnGridSet.Clear();

        // We can skip odd columns, if there is a match, it will be found while iterating the even columns
        for (int x = 0; x < gridWidth; x += 2)
        {
            for (int y = 0; y < gridHeight; y++)
            {
                for (int i = 0; i < 6; i++)
                {
                    // For each possible tuple on the grid
                    HexagonTuple tuple = GetTupleAtCorner(x, y, (HexagonPiece.Corner)i);
                    if (!tuple.IsEmpty)
                    {
                        // Check if rotating the tuple once or twice results in a match
                        for (int j = 0; j < 2; j++)
                        {
                            tuple.RotateClockwise();
                            HexagonMatch match = GetMatchingPiecesAt(tuple);
                            if (match != null)
                            {
                                PoolManager.Instance.Push(match);
                                tuple.RotateClockwise(2 - j);

                                return(false);
                            }
                        }

                        // There is no match after 2 rotations, rotate the tuple one last time to restore its original state
                        tuple.RotateClockwise();
                    }
                }
            }
        }

        return(true);
    }
Exemple #11
0
        private void OnSwipe(PointerEventData eventData)
        {
            if (_isBusy)
            {
                return;
            }

            if (!selection.IsVisible)
            {
                return;
            }

            // Check if this is a clockwise swipe or a counter-clockwise swipe
            Vector2 center    = CameraManager.Instance.WorldToScreenPoint(selection.transform.localPosition);
            bool    clockwise = Vector2.SignedAngle(eventData.pressPosition - center, eventData.position - center) < 0f;
            // Check if rotating the selection by a certain amount results in a match on the grid
            int          rotationAmount;
            HexagonMatch match = null;

            for (rotationAmount = 1; rotationAmount < 3; rotationAmount++)
            {
                SoundManager.Instance.PlayFx("rotation");
                selection.Group.RotateClockwise(clockwise ? 1 : -1);
                match = GridManager.Instance.TryGetMatchingPiecesAt(selection.Group);
                if (match != null)
                {
                    break;
                }
            }

            if (match == null)
            {
                selection.Group.RotateClockwise(clockwise ? 1 : -1); // So that the selection will rotate 360 degrees
                SoundManager.Instance.PlayFx("rotation");
            }

            StartCoroutine(RotateSelection(clockwise, rotationAmount, match));
        }
Exemple #12
0
 public void Push(HexagonMatch match)
 {
     _matchPool.Push(match);
 }
Exemple #13
0
        private IEnumerator RotateSelection(bool clockwise, int amount, HexagonMatch match)
        {
            _isBusy = true;
            // Wait for the rotate animation to finish
            yield return(StartCoroutine(AnimationManager.Instance.RotateSelection(selection, amount * (clockwise ? -120f : 120f))));

            // The grid will be updated if there is a match
            if (match != null)
            {
                // Don't show the selection while updating the grid
                selection.IsVisible = false;
                UIManager.Instance.ToggleSettingGroup(false);

                // Wait for a short interval so that users can also realize the match
                yield return(new WaitForSeconds(0.5f));

                // A column index that is selected randomly from the matching pieces
                int possibleBombColumn = match[Random.Range(0, match.Count)].GridPos.x;

                // Update the score and etc.
                ProcessMatch(match);

                // Start filling in the blank slots (slots previously occupied by matching pieces) but don't wait for it to finish yet
                Coroutine fillBlanksCoroutine = StartCoroutine(GridManager.Instance.FillBlankSlots());
                if (_score >= _nextBombSpawnScore)
                {
                    // Spawn a bomb at a random column if we've reached the target score
                    _nextBombSpawnScore += _bombInterval;

                    HexagonBomb bomb = PoolManager.Instance.PopBomb();
                    bomb.InitBomb(GridManager.Instance[possibleBombColumn][GridManager.Instance.Height - 1], _bombExplosionCounter + 1); // Counter will decrement after this round
                    _bombs.Add(bomb);
                }

                // Wait for the blank slots to be filled
                yield return(fillBlanksCoroutine);

                // Check if there are another matches on the grid after the blank slots are filled
                // If so, continue to update the grid until there is no match left
                List <HexagonMatch> matchesOnGrid = GridManager.Instance.GetAllMatchingPiecesOnGrid();
                while (matchesOnGrid != null && matchesOnGrid.Count > 0)
                {
                    yield return(new WaitForSeconds(0.5f));

                    for (int i = 0; i < matchesOnGrid.Count; i++)
                    {
                        ProcessMatch(matchesOnGrid[i]);
                    }

                    yield return(StartCoroutine(GridManager.Instance.FillBlankSlots()));

                    matchesOnGrid = GridManager.Instance.GetAllMatchingPiecesOnGrid();
                }

                // Decrement the counters of the bombs and end the game if a bomb reaches 0
                for (int i = _bombs.Count - 1; i >= 0; i--)
                {
                    if (!_bombs[i].Pulse())
                    {
                        SoundManager.Instance.PlayFx("bomb_explode");
                        EndGame();
                        yield break;
                    }
                }

                // Update the selection with the new pieces
                selection.SelectGroup(selection.transform.localPosition);

                // Check if there are no more possible matches on the grid (i.e. deadlock)
                if (GridManager.Instance.IsDeadlocked())
                {
                    SoundManager.Instance.PlayFx("oops");
                    EndGame();
                    yield break;
                }
            }

            _isBusy = false;
        }