public Match3BoardPiece AttachTileToBoardAt(int rowIdx, int columnIdx, Match3Tile tile, bool offBoardTile, bool isBoardSetup = false, bool resetTilePosition = true)
    {
        // Assign the tile to the specified BoardPiece.
        Match3BoardPiece targetBoardPiece = Board[rowIdx, columnIdx] as Match3BoardPiece;

        if (isBoardSetup)
        {
            targetBoardPiece.TileRef = tile;
        }
        else
        {
            targetBoardPiece.Tile = tile;

//			if (targetBoardPiece.BottomLink != null && targetBoardPiece.BottomLink.Tile != null && targetBoardPiece.BottomLink.Tile.IsMoving) {
//				Match3Tile nextTile = targetBoardPiece.BottomLink.Tile as Match3Tile;
//				newTile.moveVel = Mathf.Clamp(nextTile.moveVel - newTile.initialVel, -newTile.initialVel, newTile.maxVel);
//			}
        }

        if (resetTilePosition)
        {
            targetBoardPiece.ResetTilePosition();
        }

//		if (offBoardTile)
//		{
//			Match3BoardPiece bottomLinkPiece = targetBoardPiece.BottomLink;
//			Vector3 tileLocalPos = newTile.LocalPosition;
//
//			if (bottomLinkPiece != null && bottomLinkPiece.Tile != null && bottomLinkPiece.LocalPosition.y < bottomLinkPiece.Tile.LocalPosition.y)
//			{
//				tileLocalPos.y = bottomLinkPiece.Tile.LocalPosition.y + verticalTileDistance + verticalTileOffset;
//			}
//			else {
//				tileLocalPos.y = targetBoardPiece.LocalPosition.y + verticalTileDistance + verticalTileOffset;
//			}
//
//			newTile.LocalPosition = tileLocalPos;
//
////			Debug.LogWarning("Spawning offboard tile at : " + tileLocalPos);
//			//Debug.Break();
//		}

        if (!isBoardSetup && !offBoardTile)
        {
            tile.InitAfterAttachedToBoard();
        }

        return(targetBoardPiece);
    }
    public bool GenerateMatch(bool _isBoardSetup)
    {
        isBoardSetup = _isBoardSetup;

        normalTiles.Clear();

        for (int i = 0; i < tilesBuffers.Length; i++)
        {
            tilesBuffers[i].Clear();
        }

//		tileBufferIndices.Clear();
        possibleMatchSlots.Clear();

        // Collect all normal tiles and create tile buffers for each color.
        Board.ApplyActionToAll((boardPiece) =>
        {
            if (boardPiece.Tile != null && boardPiece.Tile.GetType() == typeof(NormalTile) && (!isBoardSetup || !(boardPiece.Tile as NormalTile).IsTileIgnoredByAntiMatchSystems))
            {
                Match3Tile tile = boardPiece.Tile as Match3Tile;
                normalTiles.Add(tile);

                // Add tile to corresponding color buffer.
                tilesBuffers[(int)tile.TileColor].Add(tile);
            }
        });

        // No tiles allowed to be overriden by possible match generator
        if (normalTiles.Count == 0)
        {
//			Debug.LogWarning("[PossibleMatchGenerator] No normal tiles allowed to be touched by PossibleMatchGenerator...");

            return(false);
        }

//		for(int i = 1; i < tilesBuffers.Length; i++)
//		{
//			Debug.LogWarning((TileColorType)i + " => " + tilesBuffers[i].Count);
//		}

        // Sort tile buffer indices descending.
        // After sorting the tile buffers the first tile buffer will contain the tiles that have the biggest count on the board.
        // So tileBuffers[0] won't represent the colored tiles buffer of the TileColorType.None anymore. (which was an empty buffer anyway)
        SortTilesBuffersCountDescending();

        if (tilesBuffers[0].Count < 3)
        {
            TileColorType tileColorNeeded = tilesBuffers[0][0].TileColor;
//			Debug.LogWarning("[PossibleMatchGenerator] The color we need to generate: " + tileColorNeeded);

            // Go through each tile buffer and convert tiles into the color we need above to get at least 3 tiles of the same color
            // so we can create a possible match on the board.
            for (int i = 1; i < tilesBuffers.Length && tilesBuffers[0].Count < 3; i++)
            {
                int numAvailableTiles = tilesBuffers[i].Count;

                for (int j = 0; j < numAvailableTiles && tilesBuffers[0].Count < 3; j++)
                {
                    Match3BoardPiece tilePiece = tilesBuffers[i][j].BoardPiece as Match3BoardPiece;

                    // Destroy old tiles
                    GameObject.DestroyImmediate(tilePiece.Tile.gameObject);
                    tilesBuffers[i][j] = null;

                    // Create new tile of the color we need.
                    Match3Tile newTile = Match3BoardRenderer.Instance.SpawnSpecificTileAt(tilePiece.BoardPosition, typeof(NormalTile),
                                                                                          tileColorNeeded, false, isBoardSetup);
                    // Do any customization to new tiles spawned by this system.
                    if (OnNewTileSpawned != null)
                    {
                        OnNewTileSpawned(newTile);
                    }

                    tilesBuffers[0].Add(newTile);
                }
            }
        }

//		Debug.LogWarning("[PossibleMatchGenerator] After repopulating with tiles:");
//		for(int i = 0; i < tilesBuffers.Length; i++)
//		{
//			Debug.Log((TileColorType)i + " => " + tilesBuffers[i].Count);
//		}

        // Find a location on the board where to place the 3 tiles from the tile buffer 0 to create a possible match.
        if (FindPossibleMatchLocation())
        {
            // Create possible match on the board
            for (int i = 0; i < possibleMatchSlots.Count; i++)
            {
                Match3Tile       tempTile    = possibleMatchSlots[i].Tile as Match3Tile;
                Match3BoardPiece targetPiece = tilesBuffers[0][i].BoardPiece as Match3BoardPiece;

                if (tempTile != targetPiece.Tile)
                {
                    possibleMatchSlots[i].Tile = tilesBuffers[0][i];
                    targetPiece.Tile           = tempTile;

                    targetPiece.ResetTilePosition();
                    possibleMatchSlots[i].ResetTilePosition();
                }
            }

            return(true);
        }

        return(false);
//		else
//		{
//			Debug.LogWarning("No possible match location found!!!");
//		}
    }
Esempio n. 3
0
    /// <summary>
    /// Active gravity check coroutine. When it stops, it should go back up to passive gravity checking.
    /// </summary>
    /// <returns>
    /// The gravity check.
    /// </returns>
    protected IEnumerator ActiveGravityChecker()
    {
        Match3BoardPiece curPiece      = null;
        Match3BoardPiece nextPiece     = null;
        Match3BoardPiece startingPiece = null;

        bool waitedForOtherTile = false;
        bool boardCoordUpdated;

        while (GravityUpdateEnabled)
        {
            // Safety check block. (especially for when a tile might be removed from the board meaning it has no BoardPiece that it doesn't belong to it.
            if (!enabled || !GravityEnabled || BoardPiece == null)
            {
                yield return(null);

                continue;
            }

            debugActiveGravity = true;

            curPiece = BoardPiece as Match3BoardPiece;
            if (startingPiece == null)
            {
                startingPiece = curPiece;
            }

            fallDestination    = curPiece.LocalPosition;
            boardCoordUpdated  = false;
            waitedForOtherTile = false;
            bool hasReachedBoardPieceArea = HasReachedBoardPieceArea();

            // If the tile has previously moved diagonally, we must wait for it to reach it's new current board piece position first and then
            // continue to fall down vertically.
            if (/*hasReachedBoardPieceArea &&*/ curPiece.LockCount <= 0 && curPiece.BottomLink != null &&
                !curPiece.BottomLink.IsBlocked && (tileMovedDiagonally && hasReachedBoardPieceArea || !tileMovedDiagonally))
            {
                //TODO: to the same loop check like below for the diagonal tiles to fix the bug where 2 tiles one above the other can start to move diagonally at the same time
                if (curPiece.BottomLink.Tile == null)
                {
                    nextPiece           = curPiece.BottomLink;
                    boardCoordUpdated   = true;
                    tileMovedDiagonally = false;
                }
                else if (curPiece.BottomLink.Tile.IsMoving && HasTileInArea(curPiece.BottomLink.Tile as Match3Tile))
                {
                    // Adopt the velocity of the moving tile in front only if it's in the vicinity of this current tile.
                    moveVel = (curPiece.BottomLink.Tile as Match3Tile).moveVel;
                }
            }

            //TODO: separate and merge these repeating block of code in a nice method that can be called here and remove boilerplate code (when there is human time to do so).
            //Was left like this for easier debugging and code flow following.

            // Don't move sideways if we can already move vertically and until the tile has reached it's target fallDestination.
            if (!boardCoordUpdated && hasReachedBoardPieceArea)
            {
                if (curPiece.BottomLeftLink != null && !curPiece.BottomLeftLink.IsBlocked && !curPiece.BottomLeftLink.IsTileSpawner)
                {
                    if (curPiece.Left == null || curPiece.Left.IsBlocked || curPiece.Left.IsOrphan || curPiece.Left.IsTemporaryOrphan)
                    {
                        if (curPiece.BottomLeftLink.Tile != null && curPiece.BottomLeftLink.Tile.IsMoving)
                        {
                            float nextVel = initialVel;
                            bool  raisedTileStoppedMoving = false;

                            do
                            {
                                if (!raisedTileStoppedMoving && UpdateTilePhysics(curPiece))
                                {
                                    raisedTileStoppedMoving = true;
                                    TileStoppedMoving(ref startingPiece);
                                }

                                nextVel = (curPiece.BottomLeftLink.Tile as Match3Tile).moveVel;
                                if (curPiece.BottomLeftLink.Tile.IsMoving)
                                {
                                    moveVel = nextVel;
                                }

                                yield return(null);
                            } while(curPiece.BottomLeftLink.Tile != null && curPiece.BottomLeftLink.Tile.IsMoving);

                            waitedForOtherTile = true;
                            // Apply the move speed from the moving tile after waiting
                            moveVel = nextVel;
                        }

                        if (curPiece.BottomLeftLink.Tile == null)
                        {
                            if (waitedForOtherTile)
                            {
                                moveVel = Mathf.Clamp(moveVel * (1f - velWaitDampFactor), initialVel, maxVel);
                            }

                            nextPiece           = curPiece.BottomLeftLink;
                            boardCoordUpdated   = true;
                            tileMovedDiagonally = true;
                        }
                        else if (waitedForOtherTile)
                        {
                            // The tile that we've been waiting for changed its status to IsMoving=false and it didn't clear the way for this tile
                            // so we have to go back up and re-analyze the possible directions in which this tile can move.
                            continue;
                        }
                    }
                }

                if (!boardCoordUpdated && curPiece.BottomRightLink != null && !curPiece.BottomRightLink.IsBlocked && !curPiece.BottomRightLink.IsTileSpawner)
                {
                    if (curPiece.Right == null || curPiece.Right.IsBlocked || curPiece.Right.IsOrphan || curPiece.Right.IsTemporaryOrphan)
                    {
                        if (curPiece.BottomRightLink.Tile != null && curPiece.BottomRightLink.Tile.IsMoving)
                        {
                            float nextVel = initialVel;
                            bool  raisedTileStoppedMoving = false;

                            do
                            {
                                if (!raisedTileStoppedMoving && UpdateTilePhysics(curPiece))
                                {
                                    raisedTileStoppedMoving = true;
                                    TileStoppedMoving(ref startingPiece);
                                }

                                nextVel = (curPiece.BottomRightLink.Tile as Match3Tile).moveVel;
                                if (curPiece.BottomRightLink.Tile.IsMoving)
                                {
                                    moveVel = nextVel;
                                }

                                yield return(null);
                            } while(curPiece.BottomRightLink.Tile != null && curPiece.BottomRightLink.Tile.IsMoving);

                            waitedForOtherTile = true;
                            // Apply the move speed from the moving tile after waiting
                            moveVel = nextVel;
                        }

                        if (curPiece.BottomRightLink.Tile == null)
                        {
                            if (waitedForOtherTile)
                            {
                                // Apply velocity damping for tiles that waited last time
                                moveVel = Mathf.Clamp(moveVel * (1f - velWaitDampFactor), initialVel, maxVel);
                            }

                            nextPiece           = curPiece.BottomRightLink;
                            boardCoordUpdated   = true;
                            tileMovedDiagonally = true;
                        }
                        else if (waitedForOtherTile)
                        {
                            // The tile that we've been waiting for changed its status to IsMoving=false and it didn't clear the way for this tile
                            // so we have to go back up and re-analyze the possible directions in which this tile can move.
                            continue;
                        }
                    }
                }
            }

            if (boardCoordUpdated)
            {
                fallDestination = nextPiece.LocalPosition;
                curPiece.MoveTileTo(nextPiece);
                curPiece.UpdateOrphanState();
            }

            bool hasTileReachedFallDestination = UpdateTilePhysics(curPiece);

            // Check gravity stop condition
            if (!boardCoordUpdated && hasTileReachedFallDestination &&
                (nextPiece == null || (nextPiece.Tile != null && !nextPiece.Tile.IsMoving) ||
                 curPiece == nextPiece || curPiece.LockCount > 0))
            {
                // Attach this tile to its current board piece. (correctly updating all other internal states of the board piece)
                curPiece.Tile = this;

                // Set the local position of this tile to the local position of it's new owner board piece
                curPiece.ResetTilePosition();

                TileStoppedMoving(ref startingPiece);

                RaiseEventTileFinishedActiveGravity(startingPiece);

                // Reset the current move velocity of the tile
                moveVel = 0f;

                break;
            }

            yield return(null);
        }

        debugActiveGravity = false;
    }