0
\$\begingroup\$

I'm trying to create a clone of the popular mobile game 1010! However I am struggling to determine when the player can no longer make any moves and therefore it is game over. Can you see any flaws in my logic?

This is my Game Board - It's a 9x9 Grid which is stored as a 2dArray of transforms. The three shapes at the bottom are held in a 'ToolBox':

Game Board

The shapes are just a Game Object which contain 1-5 child Game Objects which have a SpriteRenderer

My current Game Over logic loops through the Tool Box and for each shape it loops through the grid and sets the position to the grid[x, y] and then calls my IsValidPosition(Shape shape) method.

The IsValidPosition(Shape shape) gets each child transform of the shape and checks whether it is within the Game Board or if the position in the grid is currently occupied by another shape.

This is where the Game Over check starts:

void PlaceShape(Shape shape) {
    if (m_gameBoard.IsValidPosition (m_activeShape)) {
        m_gameBoard.StoreShapeInGrid (m_activeShape);
        m_activeShape.m_placed = true;
        m_toolBox.RemoveShape (m_activeShape);

        //When placed, set sorting layer to board so that sprites dont render over unplaced shapes, also set color back to solid.
        foreach (SpriteRenderer sprite in m_activeShape.GetComponentsInChildren <SpriteRenderer> ()) {
            sprite.sortingLayerName = "Board";
            sprite.color = m_activeShape.m_color;
        }

        //If we completed any lines then score them.
        if (m_gameBoard.m_completedLines > 0) {
            m_scoreManager.ScoreLines (m_gameBoard.m_completedLines);
        }

        if (IsGameOver ()) {
            Debug.Log ("GAME OVER");
            if (m_gameOverPanel) {
                m_gameOverPanel.SetActive (true);
            }
        }

        //Destroy game objects with no children.
        Cleanup ();
    } else {
        m_toolBox.PutShapeBack (shape);
    }
}

This is the method that loops through the shapes that are currently in the tool box:

bool IsGameOver() {
    foreach(Shape shape in m_toolBox.m_toolBox) {
        Debug.Log (shape.name);
        shape.m_fitsOnBoard = m_gameBoard.WillItFit (shape); //Tell shape if it fits on the board.
        shape.Reset ();
    }

    foreach (Shape shape in m_toolBox.m_toolBox) { //If at least 1 shape can fit on the board then it's not game over yet.
        if (shape.m_fitsOnBoard) {
            return false;
        }
    }
    return true;
}

The Game Board's WillItFit(Shape shape) method is then called for each shape in the tool box:

public bool WillItFit(Shape shape) {
    for (int y = 0; y < m_height; y++) {
        for (int x = 0; x < m_width; x++) {
            shape.transform.position = new Vector2 (x, y);
            if(IsValidPosition (shape)) {
                Debug.Log(shape.name + " fits at x: " + x + ", y: " + y);
                return true;
            }
        }
    }
    return false;
}

Then the IsValidPosition(Shape) method is called which subsequently calls the IsWithinBoard and IsOccupied methods:

bool IsWithinBoard(int x, int y) {
    return (x >= 0 && x < m_width && y >= 0 && y < m_height);
}

bool IsOccupied(int x, int y, Shape shape) {
    return (m_grid [x, y] != null && m_grid [x, y].parent != shape.transform);
}

public bool IsValidPosition(Shape shape) {

    foreach (Transform child in shape.transform) {
        Vector2 pos = Vectorf.Round (child.position);

        if (!IsWithinBoard ((int) pos.x, (int) pos.y)) {
            Debug.Log (shape.name + " position: " + pos + " IS NOT WITHIN THE BOARD");
            return false;
        }

        if(IsOccupied ((int) pos.x, (int) pos.y, shape)) {
            Debug.Log (" position: " + pos + " IS ALREADY OCCUPIED");
            return false;
        }
    }

    return true;
}
\$\endgroup\$
  • \$\begingroup\$ does Shape.Reset() modify the value of Shape.m_fitsOnBoard? \$\endgroup\$ – monty May 22 '17 at 13:22
0
\$\begingroup\$

Finally got to the bottom of this. The shapes that are stored in the toolbox are scaled down to 50% of the actual size. So when I was iterating through the tool box and moving all the shapes to every given position the child transforms of the shape game object weren't where they were supposed to be.

I figured this out by making the WillItFit(Shape shape) method a coroutine and making it wait 0.5s in between each loop so that I could see what was happening.

The fix was to set

shape.transform.localScale = Vector3.One;

in the first line of the WillItFit(Shape shape) method

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.