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':
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;
}
