Only 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 () {
}
}