How to Make Video Games 11

How to Make TetrisOnly 2 videos remain until we finish Tetris! In this video we will focus on deleting full rows. We will search each column in each row to find those full of cubes. Then we’ll delete them in the array as well as in the scene. Then we have to bring all blocks above down and then increase the score on the screen.

Like always all the code is available under the video below. Do with it what ever you’d like.

If you like videos like this, consider donating $1 or simply turn off AdBlock. It helps a lot 🙂

[googleplusone]

Code From the Video

GAMEBOARD.CS

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GameBoard : MonoBehaviour {
    // Surround all GameObjects with GameObjectGroup
    // and move it the amount of space to make the 
    // gameboard lie at the 0 0 mark

    // Stores all the cubes on the gameboard
    public static Transform[,] gameBoard = new Transform[10, 20];

    public static void PrintArray()
    {
        string arrayOutput = "";

        // Gets size of gameboard array and then subtract
        // 1 because the array starts with 0
        int iMax = gameBoard.GetLength(0) - 1;
        int jMax = gameBoard.GetLength(1) - 1;

        // Cycle through the array and print N or X 
        // depending on if you have a null or transform
        for(int j = jMax; j >= 0; j--)
        {
            for (int i = 0; i <= iMax; i++)
            {

                if (gameBoard[i, j] == null)
                {
                    arrayOutput += "N ";
                } else
                {
                    arrayOutput += "X ";
                }
            }

            arrayOutput += "\n \n";

            }

        // Get a reference to the Text component
        // and change its value
        var myArrayComp = GameObject.Find("MyArray").GetComponent<Text>();
        myArrayComp.text = arrayOutput;

    }

    public static bool DeleteAllFullRows()
    {
        // Cycle through all rows 
        for (int row = 0; row < 20; ++row)
        {
            // Check for a full row
            if (IsRowFull(row))
            {
                // Delete Row
                DeleteGBRow(row);

                // TODO : Make Sound

                return true;
            }
        }
        return false;
    }

    // This test is done in a 2nd function because it 
    // answers a specific question being is a row full
    public static bool IsRowFull(int row)
    {
        // Cycle through columns and if a null is
        // found return false
        for(int col = 0; col < 10; ++col)
        {
            if (gameBoard[col, row] == null)
            {
                return false;
            }
        }

        return true;

    }

    public static void DeleteGBRow(int row)
    {
        // Cycle through row deleting in both the array
        // as well as in the scene
        for (int col = 0; col < 10; ++col)
        {
            // Destroy the cubes in the scene
            Destroy(gameBoard[col, row].gameObject);
            // Destroy the cubes in the array
            gameBoard[col, row] = null;
        }

        // Increment up a row to start moving them down
        row++;

        // Cycle through all rows
        for (int j = row; j < 20; ++j)
        {
            // Cycle through all columns
            for (int col = 0; col < 10; ++col)
            {
                // Check if there is a block in a cell
                if (gameBoard[col,j] != null)
                {
                    // Move whats above down
                    gameBoard[col, j - 1] = gameBoard[col, j];

                    // Delete the cube that was moved down
                    gameBoard[col, j] = null;

                    // Move the cube in the scene as well
                    gameBoard[col, j - 1].position += new Vector3(0, -1, 0);
                }
            }
        }

    }

}

SHAPE.CS

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using UnityEngine.UI;

public class Shape : MonoBehaviour {

    // Define that we want to fall 1 unit per second
    public float speed = 1.0f;

    // Tracks the last time the shape moved down
    float lastMoveDown = 0;

	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {

        if (Input.GetKeyDown("a"))
        {
            // Modify position
            transform.position += new Vector3(-1, 0, 0);

            if (!IsInGrid())
            {
                // Switch to previous
                transform.position += new Vector3(1, 0, 0);
            } else {

                // Update the GameBoard array
                UpdateGameBoard();
            }
        }

        if (Input.GetKeyDown("d"))
        {
            transform.position += new Vector3(1, 0, 0);

            if (!IsInGrid())
            {
                transform.position += new Vector3(-1, 0, 0);
            } else {
                UpdateGameBoard();
            }
        }

        // Move Shape down when s is pressed, or once every second
        // First time through Time.time will have a value of 1 and
        // then 2, etc. 
        // lastMoveDown will increment each time through as well

        if (Input.GetKeyDown("s") || Time.time - lastMoveDown >= 1)
        {
            transform.position += new Vector3(0, -1, 0);

            if (!IsInGrid())
            {
                transform.position += new Vector3(0, 1, 0);

                // Delete all full rows found
                bool rowDeleted = GameBoard.DeleteAllFullRows();

                // If you deleted a row verify that another doesn't
                // exist
                if (rowDeleted)
                {
                    GameBoard.DeleteAllFullRows();

                    IncreaseTextUIScore();
                }

                // Disconnect the script actions from the shape
                enabled = false;

                // Spawn another shape
                FindObjectOfType<ShapeSpawner>().SpawnShape();
            } else {
                UpdateGameBoard();
            }

            lastMoveDown = Time.time;
        }

        if (Input.GetKeyDown("w"))
        {
            transform.Rotate(0, 0, 90);

            if (!IsInGrid())
            {
                transform.Rotate(0, 0, -90);
            }
            else
            {
                UpdateGameBoard();
            }
        }

        if (Input.GetKeyDown("e"))
        {
            transform.Rotate(0, 0, -90);

            if (!IsInGrid())
            {
                transform.Rotate(0, 0, 90);
            }
            else
            {
                UpdateGameBoard();
            }
        }

    }

    public bool IsInGrid()
    {
        // Cycle through every block in the shape
        foreach(Transform childBlock in transform)
        {
            // Get location of the block and round to int
            Vector2 vect = RoundVector(childBlock.position);

            // Check if the position is within the border
            if (!IsInBorder(vect))
            {
                return false;
            }

            // Check what is located in the GameBoard array
            // This should be its own method
            if(GameBoard.gameBoard[(int)vect.x, (int)vect.y] != null &&
                GameBoard.gameBoard[(int)vect.x, (int)vect.y].parent != transform)
            {
                return false;
            }

        }
        return true;
    }

    // Round the cubes position to an int so it can fit 
    // in the array
    public Vector2 RoundVector(Vector2 vect)
    {
        return new Vector2(Mathf.Round(vect.x), Mathf.Round(vect.y));
    }

    // Check if between the border
    public static bool IsInBorder(Vector2 pos)
    {
        return ((int)pos.x >= 0 &&
            (int)pos.x <= 9 &&
            (int)pos.y >= 0);
    }

    // 
    public void UpdateGameBoard()
    {
        for(int y = 0; y < 20; ++y)
        {
            for(int x = 0; x < 10; ++x)
            {

                // If the 1st isn't null that means there
                // is a cube at that position
                // Then we check if the shape passed in
                // is already there
                if (GameBoard.gameBoard[x, y] != null &&
                    GameBoard.gameBoard[x, y].parent == transform)
                {
                    // If the shape moves down then we want
                    // to remove it from the gameBoard array
                    GameBoard.gameBoard[x, y] = null;
                }

            }
        }

        // Iterate over all spaces on our gameboard
        // and add the new cubes for out shape
        foreach (Transform childBlock in transform)
        {
            // Shorten our position object
            Vector2 vect = RoundVector(childBlock.position);

            // Put our cube in the gameboard array
            GameBoard.gameBoard[(int)vect.x, (int)vect.y] = childBlock;

            Debug.Log("Cube At : " + vect.x + " " + vect.y);

        }

        // GameBoard.PrintArray();

    }

    // Increases the score the text UI 
    void IncreaseTextUIScore()
    {
        // Find the matching text UI component
        var textUIComp = GameObject.Find("Score").GetComponent<Text>();

        // Get the string stored in it and convert to an int
        int score = int.Parse(textUIComp.text);

        // Increment it
        score++;

        // Save new score in Text UI
        textUIComp.text = score.ToString();
    }

}

SHAPESPAWNER.CS

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ShapeSpawner : MonoBehaviour {

// Array that holds all the shapes
public GameObject[] shapes;

public void SpawnShape()
{
// Generate a random index
int shapeIndex = Random.Range(0, 6);

// Create the shape at the ShapeSpawners location
Instantiate(shapes[shapeIndex],
transform.position,
Quaternion.identity);
}

// Use this for initialization
void Start () {

// Spawn the default first shape
SpawnShape();
}

// Update is called once per frame
void Update () {

}
}

Leave a Reply

Your email address will not be published. Required fields are marked *