private void Awake()
    {
        S = this;

        gridBackgroundSprite = transform.Find("GridBackground").GetComponent <SpriteRenderer>();
        if (gridBackgroundSprite == null)
        {
            Debug.LogError("GridDisplayer.cs : gridBackgroundSprite couldn't be found. Is there a SpriteRenderer on a child of this object?");
        }

        cellContainer = transform.Find("CellContainer");
        if (cellContainer == null)
        {
            Debug.LogError("GridDisplayer.cs : GridContainer object couldn't be found in children of this object.");
        }

        gridElementContainer = transform.Find("GridElementContainer");
        if (gridElementContainer == null)
        {
            Debug.LogError("GridManager.cs : GridElementContainer object couldn't be found in children of this object.");
        }

        poolContainer = transform.Find("PoolContainer");
        if (poolContainer == null)
        {
            Debug.LogError("GridManager.cs : PoolContainer object couldn't be found in children of this object.");
        }

        if (gridCellBackgroundPrefab == null)
        {
            Debug.LogError("GridDisplayer.cs : The grid cell prefab is null. Has it been assigned in the inspector?");
        }
    }
Пример #2
0
    /// <summary>
    /// Called by Input.cs on the frame a primary touch stops being detected.
    /// </summary>
    /// <param name="worldTouchPos">The world-space position of the touch when it left the screen.</param>
    public static void TouchEnd(Vector3 worldTouchPos)
    {
        TouchInfo touchInfo = S.primaryTouchInfo;

        // world position and end world position
        touchInfo.worldPosition = touchInfo.endWorldPosition = worldTouchPos;

        // gridPosition and endGridPosition
        Vector2Int gridPos = GridDisplayer.WorldToGrid(worldTouchPos);

        if (gridPos.x >= GRID_WIDTH || gridPos.x < 0 || gridPos.y >= GRID_HEIGHT || gridPos.y < 0)
        {
            touchInfo.gridPosition = new Vector2Int(int.MinValue, int.MinValue);
        }
        else
        {
            touchInfo.gridPosition = touchInfo.endGridPosition = gridPos;
        }

        S.primaryTouchInfo = touchInfo;

        if (touchInfo.swipeDirection != Vector2.zero)
        {
            S.shouldGetSwipedCell = true;
        }
    }
Пример #3
0
    /// <summary>
    /// Called by Input.cs starting every frame a primary touch is detected, starting from the frame after TouchBegin is called.
    /// </summary>
    /// <param name="worldTouchPos">The world-space position of the primary touch.</param>
    public static void TouchMove(Vector3 worldTouchPos)
    {
        TouchInfo touchInfo = S.primaryTouchInfo;

        //world position
        touchInfo.worldPosition = worldTouchPos;

        // gridPosition
        Vector2Int gridPos = GridDisplayer.WorldToGrid(worldTouchPos);

        if (gridPos.x >= GRID_WIDTH || gridPos.x < 0 || gridPos.y >= GRID_HEIGHT || gridPos.y < 0)
        {
            touchInfo.gridPosition = new Vector2Int(int.MinValue, int.MinValue);
        }
        else
        {
            touchInfo.gridPosition = gridPos;
        }


        S.primaryTouchInfo = touchInfo;

        //if ((touchInfo.gridPosition - touchInfo.startGridPosition).magnitude >= 1 && !S.swipeHappenedThisTouch)
        //{
        //    S.shouldGetSwipedCell = true;
        //    S.swipeHappenedThisTouch = true;
        //}
    }
Пример #4
0
    /// <summary>
    /// Called by Input.cs on the frame a primary touch is detected.
    /// </summary>
    /// <param name="worldTouchPos">The world-space position of the primary touch.</param>
    public static void TouchBegin(Vector3 worldTouchPos)
    {
        // touchInfo is a struct, so it's passed by value.
        // when we operate on primtouch, we're not actually updating S.primaryTouchInfo.
        TouchInfo primTouch = S.primaryTouchInfo;

        primTouch.touching = true;

        // worldPosition and startWorldPosition
        primTouch.worldPosition = primTouch.startWorldposition = worldTouchPos;

        // gridPosition and startGridPosition
        Vector2Int gridPos = GridDisplayer.WorldToGrid(worldTouchPos);

        if (gridPos.x >= GRID_WIDTH || gridPos.x < 0 || gridPos.y >= GRID_HEIGHT || gridPos.y < 0)
        {
            primTouch.gridPosition = new Vector2Int(int.MinValue, int.MinValue);
        }
        else
        {
            primTouch.gridPosition = primTouch.startGridPosition = gridPos;
        }

        // end positions
        primTouch.endWorldPosition = new Vector2(float.MinValue, float.MinValue);
        primTouch.endGridPosition  = new Vector2Int(int.MinValue, int.MinValue);

        S.primaryTouchInfo = primTouch;
    }
    public override void OnFall(int fallHeight)
    {
        DeRegisterMethodsFromCell(x, y);
        RegisterMethodsOnCell(x, y + fallHeight);

        y += fallHeight;

        MasterSequence.Append(transform.DOMove(GridDisplayer.GridToWorld(x, y), fallTweenDuration).SetEase(Ease.OutBounce));
    }
Пример #6
0
    void Awake()
    {
        Instance = this;


        m_NoColor          = new Color(0, 0, 0, 0);
        m_MoveRangeColor   = new Color(0, 0, 255, 0.5f);
        m_DestinationColor = new Color(0, 255, 0, 0.5f);
        m_AttackRangeColor = new Color(255, 222, 0, 0.5f);

        m_UnderMouseColor = new Color(0, 0, 255, 0.5f);
        m_SelectionColor  = new Color(0, 255, 0, 0.5f);
    }
    public override void OnSwap(Vector2Int newCellPos)
    {
        // deregister methods from the original cell
        DeRegisterMethodsFromCell(x, y);

        // register methods on the new cell
        RegisterMethodsOnCell(newCellPos);

        // set x and y to new cell
        x = newCellPos.x;
        y = newCellPos.y;

        // tween position
        MasterSequence.Append(transform.DOMove(GridDisplayer.GridToWorld(x, y), swapTweenDuration));

        wasSwapped = true;
    }
    public override void OnPop()
    {
        // if this cell is part of a match but isn't the one that was swapped this frame, it
        //    needs to wait for the swap tween to end before disappearing
        if (!wasSwapped)
        {
            MasterSequence.AppendInterval(swapTweenDuration);
        }

        MasterSequence.AppendCallback(() => popParticleSystem.Play());

        MasterSequence.Append(transform.DOScale(0, popTweenDuration).SetEase(Ease.InBack));

        if (!returningToPool)
        {
            MasterSequence.AppendCallback(() => GridDisplayer.ReturnCandyToPool(this));
            returningToPool = true;
        }


        // scale the game object back to 1 after returning it so that it's scaled properly when we get it back from the pool again
        MasterSequence.AppendCallback(() => transform.localScale = new Vector3(1, 1, 1));
    }
 public override void OnSwapFail(Vector2Int newCellPos)
 {
     // move to the new position then back to the old one
     MasterSequence.Append(transform.DOMove(GridDisplayer.GridToWorld(newCellPos), swapTweenDuration));
     MasterSequence.Append(transform.DOMove(GridDisplayer.GridToWorld(x, y), swapTweenDuration));
 }
Пример #10
0
    private void Update()
    {
        // if we're currently animating, don't update grid state until the display of the grid is caught up ith the current grid state.
        if (GridDisplayer.TweenInProgress())
        {
            return;
        }

        if (primaryTouchInfo.touching && !cellSelected)
        {
            // user is touching inside the grid
            if (primaryTouchInfo.startGridPosition != new Vector2Int(int.MinValue, int.MinValue))
            {
                selectedCell = primaryTouchInfo.startGridPosition;
                cellSelected = true;
                Debug.Log(grid[selectedCell.x, selectedCell.y].cellContent);
            }
        }

        if (!primaryTouchInfo.touching && cellSelected)
        {
            cellSelected = false;
        }

        #region Candy Swapping
        if (shouldGetSwipedCell)
        {
            // user has touched inside the grid
            if (primaryTouchInfo.startGridPosition != new Vector2Int(int.MinValue, int.MinValue))
            {
                int x = primaryTouchInfo.startGridPosition.x + primaryTouchInfo.swipeDirection.x;
                int y = primaryTouchInfo.startGridPosition.y - primaryTouchInfo.swipeDirection.y;

                // user is swiping inside the grid
                if (x < GRID_WIDTH && y < GRID_HEIGHT && x >= 0 && y >= 0)
                {
                    // the cell the player is swiping
                    swipedCell = new Vector2Int(x, y);

                    // swap the cellContent variables of the cells being swapped
                    CellContents temp = grid[swipedCell.x, swipedCell.y].cellContent;
                    grid[swipedCell.x, swipedCell.y].cellContent     = grid[selectedCell.x, selectedCell.y].cellContent;
                    grid[selectedCell.x, selectedCell.y].cellContent = temp;

                    // check for matches
                    List <Vector2Int> matches = new List <Vector2Int>();
                    matches.AddRange(GetMatchesAtCell(swipedCell));
                    matches.AddRange(GetMatchesAtCell(selectedCell));

                    if (matches.Count != 0)
                    {
                        // this is kind of a hack :
                        // Basically, when a GridElement swaps, it deregisters its swap method from its
                        //    current cell and registers it on the new cell. however, since the new
                        //    cell's swap method gets called right after, the first GridElement's swap
                        //    method was being called twice.
                        //    We "solve" this by taking a "snapshot" of the swiped gridcell before the
                        //    first GridElement registers its swap method on it, and calling the swap
                        //    method of this "snapshot". The first GridElement's swap method is only
                        //    called once and still registers itself on the right cell.
                        GridCell swipedCellCopy = grid[swipedCell.x, swipedCell.y];

                        if (grid[selectedCell.x, selectedCell.y].Swap != null)
                        {
                            grid[selectedCell.x, selectedCell.y].Swap(swipedCell);
                        }

                        if (swipedCellCopy.Swap != null)
                        {
                            swipedCellCopy.Swap(selectedCell);
                        }


                        foreach (Vector2Int cell in matches)
                        {
                            if (grid[cell.x, cell.y].Pop != null)
                            {
                                grid[cell.x, cell.y].Pop();
                            }

                            grid[cell.x, cell.y].cellContent = CellContents.empty;
                        }
                        return;
                    }
                    else
                    {
                        // call swap fail event (no need for the above hack since GridElement_Candy's
                        //    SwapFail method doesn't do any registering/deregistering)
                        if (grid[selectedCell.x, selectedCell.y].SwapFail != null)
                        {
                            grid[selectedCell.x, selectedCell.y].SwapFail(swipedCell);
                        }

                        if (grid[swipedCell.x, swipedCell.y].SwapFail != null)
                        {
                            grid[swipedCell.x, swipedCell.y].SwapFail(selectedCell);
                        }


                        // swap cell contents back
                        CellContents temp2 = grid[swipedCell.x, swipedCell.y].cellContent;
                        grid[swipedCell.x, swipedCell.y].cellContent     = grid[selectedCell.x, selectedCell.y].cellContent;
                        grid[selectedCell.x, selectedCell.y].cellContent = temp2;
                    }
                }
            }

            //shouldGetSwipedCell = false;
        }
        #endregion

        #region Candy Falling
        if (GridHasEmptyCells())
        {
            // check for cells i which new candies should be spawned
            for (int i = GRID_WIDTH - 1; i >= 0; --i)
            {
                int topColumnCellYCoord = 0;

                // if the top cell of the column is a hole, go down until we find one that's not
                if (grid[i, topColumnCellYCoord].cellContent == CellContents.hole)
                {
                    for (int j = 0; j < GRID_HEIGHT; ++j)
                    {
                        if (grid[i, j].cellContent == CellContents.hole)
                        {
                            ++topColumnCellYCoord;
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                if (grid[i, topColumnCellYCoord].cellContent == CellContents.empty)
                {
                    // get a random color for the new candy
                    // FIND A BETTER WAY TO DO THIS
                    CellContents color = (CellContents)Random.Range(1, 6);

                    // Call a GridDisplayer Function to spawn in a new candy in the top row cell
                    GridDisplayer.SpawnNewCandy(color, new Vector2Int(i, topColumnCellYCoord));

                    grid[i, topColumnCellYCoord].cellContent = color;
                }
            }

            bool candiesFellThisFrame = false;

            // go backwards throught the grid, starting 1 line above the bottom because we're checking if cells below are emtpy
            for (int j = GRID_HEIGHT - 2; j >= 0; --j)
            {
                for (int i = GRID_WIDTH - 1; i >= 0; --i)
                {
                    if (grid[i, j].cellContent == CellContents.hole)
                    {
                        continue;
                    }

                    // if we find a non empty cell above an empty cell or a hole
                    if ((grid[i, j + 1].cellContent == CellContents.empty || grid[i, j + 1].cellContent == CellContents.hole) && grid[i, j].cellContent != CellContents.empty)
                    {
                        int dist        = 0;
                        int holeCounter = 0;

                        // go down until we find a cell that's above a non empty cell or at the bottom of the grid
                        for (int y = j + 1; y < GRID_HEIGHT; ++y)
                        {
                            if (grid[i, y].cellContent == CellContents.hole)
                            {
                                // if the cell we're checking is a hole, we don't want to add to dist just yet in
                                //    case its holes all the way down, in which case the candy should not drop, so
                                //    we keep a separate counter for holes
                                holeCounter++;
                            }
                            else
                            {
                                dist++;

                                // if we've hit a cell that's not a hole and the holeCounter is greater than 0,
                                //    that means the ccandy can fall down through the holes. we add the holecounter
                                //    to dist and we reset it in case we find more holes lower in the grid.
                                if (holeCounter > 0)
                                {
                                    dist       += holeCounter;
                                    holeCounter = 0;
                                }
                            }

                            if (y < GRID_HEIGHT - 1)
                            {
                                // break if the cell below the one we're checking is not empty and not a hole
                                if (grid[i, y + 1].cellContent != CellContents.empty && grid[i, y + 1].cellContent != CellContents.hole)
                                {
                                    break;
                                }
                            }
                        }

                        // dist is now the number of empty cells between the cell we're at and the next non-empty cell under it
                        // we call Fall on grid[i,j] and pass it dist

                        if (dist > 0)
                        {
                            if (grid[i, j].Fall != null)
                            {
                                grid[i, j].Fall(dist);
                            }

                            grid[i, j + dist].cellContent = grid[i, j].cellContent;
                            grid[i, j].cellContent        = CellContents.empty;

                            candiesFellThisFrame = true;
                        }
                    }
                }
            }

            if (candiesFellThisFrame)
            {
                return;
            }


            //for each grid column i, check if grid[i, 0] is empty. if yes, new candies should be spawned.
            //for (int i = GRID_WIDTH - 1; i >= 0; --i)
            //{
            //    int topColumnCellYCoord = 0;
            //
            //    // if the top cell of the column is a hole, go down until we find one that's not
            //    if (grid[i, topColumnCellYCoord].cellContent == CellContents.hole)
            //    {
            //        for (int j = 0; j < GRID_HEIGHT; ++j)
            //        {
            //            if (grid[i, j].cellContent == CellContents.hole)
            //            {
            //                ++topColumnCellYCoord;
            //            }
            //            else
            //            {
            //                break;
            //            }
            //        }
            //    }
            //
            //    if (grid[i, topColumnCellYCoord].cellContent == CellContents.empty)
            //    {
            //        // "probe" down to see how far down the next non-empty cell is
            //        int dist = 0;
            //        int holeCounter = 0;
            //
            //        for (int j = topColumnCellYCoord+1; j < GRID_WIDTH; ++j)
            //        {
            //            if (grid[i, j].cellContent == CellContents.empty )
            //            {
            //                ++dist;
            //
            //                if (holeCounter > 0)
            //                {
            //                    dist += holeCounter;
            //                    holeCounter = 0;
            //                }
            //            }
            //            else if (grid[i, j].cellContent == CellContents.hole)
            //            {
            //                ++holeCounter;
            //            }
            //            else
            //            {
            //                break;
            //            }
            //        }
            //
            //        // get a random color for the new candy
            //        // FIND A BETTER WAY TO DO THIS
            //        CellContents color = (CellContents)Random.Range(1, 6);
            //
            //        // Call a GridDisplayer Function to spawn in a new candy in the top row cell
            //        GridDisplayer.SpawnNewCandy(color, new Vector2Int(i, topColumnCellYCoord));
            //
            //        // call Fall on this top row cell if dist > 0
            //        if (dist > 0)
            //        {
            //            if (grid[i, 0].Fall != null)
            //                grid[i, 0].Fall(dist);
            //
            //            grid[i, dist].cellContent = color;
            //        }
            //        else
            //        {
            //            grid[i, 0].cellContent = color;
            //        }
            //
            //    }
            //}
        }
        #endregion

        if (!GridHasEmptyCells())
        {
            // check the whole grid for matches and pop them
            // for some reason this doesn't detect 4+ matches sometimes ?
            for (int i = 0; i < GRID_WIDTH; ++i)
            {
                for (int j = 0; j < GRID_HEIGHT; ++j)
                {
                    foreach (Vector2Int cellPos in GetMatchesAtCell(new Vector2Int(i, j)))
                    {
                        if (grid[cellPos.x, cellPos.y].Pop != null)
                        {
                            grid[cellPos.x, cellPos.y].Pop();
                        }
                        grid[cellPos.x, cellPos.y].cellContent = CellContents.empty;
                    }
                }
            }
        }
    }
Пример #11
0
    public void SetupGrid()
    {
        GridDisplayer.TeardownGridDisplay();

        if (level == null)
        {
            // create random grid
            grid = new GridCell[GRID_WIDTH, GRID_HEIGHT];
            for (int i = 0; i < GRID_WIDTH; ++i)
            {
                for (int j = 0; j < GRID_HEIGHT; ++j)
                {
                    grid[i, j] = new GridCell()
                    {
                        visible = true,
                        empty   = false,
                        x       = i,
                        y       = j,

                        // FIND A BETTER WAY TO DO THIS
                        cellContent = (CellContents)Random.Range(1, 6)
                    };
                }
            }
        }
        else
        {
            // load info from level
            GRID_WIDTH  = level.gridWidth;
            GRID_HEIGHT = level.gridHeight;

            grid = new GridCell[GRID_WIDTH, GRID_HEIGHT];

            // go through level.grid, a 1D array
            for (int i = 0; i < GRID_WIDTH * GRID_HEIGHT; ++i)
            {
                // find x and y 2D grid positions of the cell at i with the formula : i = x * gridHeight + y
                int gridX = i / gridHeight;
                int gridY = i % gridHeight;

                grid[gridX, gridY] = new GridCell()
                {
                    visible = true,
                    empty   = false,
                    x       = gridX,
                    y       = gridY
                };

                // cell contents
                if (level.grid[i].hole)
                {
                    grid[gridX, gridY].cellContent = CellContents.hole;
                }
                else
                {
                    // if the current cell is empty in the level SO, it hasn't been defined and we should fill it with a random color
                    if (level.grid[i].content == CellContents.empty)
                    {
                        grid[gridX, gridY].cellContent = level.GetRandomColor();
                    }
                    else
                    {
                        grid[gridX, gridY].cellContent = level.grid[i].content;
                    }
                }
            }
        }



        // INITIAL MATCH DETECTION FOR CLEAN GRID
        List <Vector2Int> allMatches = new List <Vector2Int>();

        do
        {
            // we first remove the matches if there are any.
            for (int i = 0; i < allMatches.Count; i++)
            {
                Vector2Int cell = allMatches[i];

                if (level != null)
                {
                    grid[cell.x, cell.y].cellContent = level.GetRandomColor();
                }
                else
                {
                    grid[cell.x, cell.y].cellContent = (CellContents)Random.Range(1, 6);
                }

                allMatches.Remove(cell);
            }

            // then we check the grid for matches. The above operation might have created new matches.
            for (int i = 0; i < GRID_WIDTH; ++i)
            {
                for (int j = 0; j < GRID_HEIGHT; ++j)
                {
                    foreach (Vector2Int cellPos in GetMatchesAtCell(new Vector2Int(i, j)))
                    {
                        if (!allMatches.Contains(cellPos))
                        {
                            allMatches.Add(cellPos);
                        }
                    }
                }
            }

            // finally we loop back as long as the above nested for loop has found at least one match
        } while (allMatches.Count != 0);


        GridDisplayer.InitializeGridDisplay();
    }