Esempio n. 1
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;
    }