【Unity】Simple Tetris production

Original video: https://www.youtube.com/watch?v=T5P8ohdxDjo

Reposted from station b: [UNITY] Make Tetris in 13 minutes! (Attached download)_bilibili_bilibili

1. Key points in background and block production

1. Move the lower left corner of the background to the coordinate (0, 0) point

2. Rotation point setting of the block

3. The block coordinates need to be integer values

2. Script

1、TetrisBlock

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

public class TetrisBlock : MonoBehaviour
{
    public Vector3 rotationPoint;//方块旋转的坐标点
    private float previousTime;
    public float fallTime = 0.8f;//下落时间
    public static int height = 20;//界面高度
    public static int width = 10;//界面宽度
    private static Text points;//分数(消除行数)
    private static int lines = 0;

    public static Transform[,] grid = new Transform[width, height];//界面网格
    // Start is called before the first frame update
    void Start()
    {
        points = GameObject.Find("Points").GetComponent<Text>();
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.LeftArrow))//键盘左键
        {
            transform.position += new Vector3(-1, 0, 0);//向左移动一格
            if (!validMove())//判断是否超出界面,超出就反向移动一下抵消
                transform.position -= new Vector3(-1, 0, 0);
        }
        else if (Input.GetKeyDown(KeyCode.RightArrow))
        {
            transform.position += new Vector3(1, 0, 0);
            if (!validMove())
                transform.position -= new Vector3(1, 0, 0);
        }
        else if (Input.GetKeyDown(KeyCode.UpArrow))
        {
            transform.RotateAround(transform.TransformPoint(rotationPoint), new Vector3(0, 0, 1), 90);//旋转点、旋转轴、旋转度数
            if (!validMove())
                transform.RotateAround(transform.TransformPoint(rotationPoint), new Vector3(0, 0, 1), -90);
        }

        if (Time.time - previousTime > (Input.GetKey(KeyCode.DownArrow) ? fallTime/10 : fallTime))//如果按下向下,下落时间改为0.08
        {
            transform.position += new Vector3(0, -1, 0);
            if (!validMove())
            {
                transform.position -= new Vector3(0, -1, 0);
                addToGrid();//不再下落后将对应数据存入网格中
                checkLines();//检查是否有连成一行
                this.enabled = false;
                FindObjectOfType<SpawnTetromino>().newTetromino();//生成下一个方块
            }
            previousTime = Time.time;
        }

        if (Input.GetKey(KeyCode.Escape))
        {
            Application.Quit();
        }

        if (Input.GetKey(KeyCode.Space))
        {
            if (Time.timeScale != 0)
                Time.timeScale = 0;
            else if (Time.timeScale == 0)
                Time.timeScale = 1;
        }
    }

    void checkLines()
    {
        for(int i = height - 1; i >= 0; i--)//对每一行进行扫描
        {
            if (hasLine(i))
            {
                deleteLine(i);
                rowDown(i);//将该行上方的所有方块向下移动一格
                lines++;
                points.text = "Points:" + lines;
            }
        }
    }

    bool hasLine(int i)
    {
        for (int j = 0; j < width; j++)//对每一行中的每一个格子进行扫描
        {
            if (grid[j,i] == null)//只要有一个格子为空就返回false
            {
                return false;
            }
        }
        return true;
    }

    void deleteLine(int i)
    {
        for (int j = 0; j < width; j++)
        {
            Destroy(grid[j, i].gameObject);
            grid[j, i] = null;
        }

    }

    void rowDown(int i)
    {
        for (int y = i; y < height; y++)//选择从第i行往上的所有行
        {
            for (int j = 0; j < width; j++)
            {
                if (grid[j, y] != null)//只要方格不为空
                {
                    grid[j, y - 1] = grid[j, y];//就将方块复制到下一行
                    grid[j, y] = null;//同时清除原本方格中的方块
                    grid[j, y - 1].transform.position -= new Vector3(0, 1, 0);
                }
            }
        }
    }

    void addToGrid()
    {
        foreach (Transform children in transform)
        {
            int roundedX = Mathf.RoundToInt(children.transform.position.x);
            int roundedY = Mathf.RoundToInt(children.transform.position.y);
            grid[roundedX, roundedY] = children;
        }
    }

    bool validMove()
    {
        foreach(Transform children in transform)
        {
            int roundedX = Mathf.RoundToInt(children.transform.position.x);
            int roundedY = Mathf.RoundToInt(children.transform.position.y);
            if(roundedX < 0 || roundedX >= width || roundedY < 0 || roundedY >= height)
            {
                return false;
            }
            if (grid[roundedX, roundedY] != null)
                return false;
        }
        return true;
    }
}

(1) Rotate and RotateAround: target point, rotation axis, angle

RotateAround(Vector3 point, Vector3 axis, float angle);

(2) TransformPoint: Convert the coordinates relative to the "current game object" into coordinates based on the world coordinate system 

(3) RoundToInt: Round to the nearest integer

2、SpawnTetromino

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

public class SpawnTetromino : MonoBehaviour
{
    public GameObject[] Tetrominoes;
    // Start is called before the first frame update
    void Start()
    {
        newTetromino();
    }

    public void newTetromino()
    {
        Instantiate(Tetrominoes[Random.Range(0, Tetrominoes.Length)], transform.position, Quaternion.identity);//Quaternion.identity就是指Quaternion(0,0,0,0),
    }
}

Guess you like

Origin blog.csdn.net/simplenthpower/article/details/129469862
Recommended