【Unity游戏】——1.俄罗斯方块

发布于:2025-07-29 ⋅ 阅读:(16) ⋅ 点赞:(0)

搭建场景

使用任意方块、纯色瓦片或者其他图形作为背景,设置其大小与目标大小一致或者更大,设置左下角为场景顶点,并放置在(0,0)处。调整摄像机至合适位置。

制作游戏预制体

每个方块预制体包含有4个小方块以及一个围绕旋转的节点。先设置一个小方块的坐标为(0,0),在此基础上摆放其他小方块,设置一个合适的旋转节点。

脚本

思路

实现方块自由下落        -> Block.cs

实现方块左右移动、加速下落、旋转        -> Block.cs

限制方块移动范围         -> Block.cs

把方块加入到场景中        -> Board.cs

禁用该方块的脚本       -> Block.cs

检测方块是否满行         -> Board.cs

满行则消除该行         -> Board.cs

下移该行上面的方块        -> Board.cs

实现代码

Block.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum MoveType
{
    Move,
    Rotate,
    MoveDown,
    MoveRight,
    MoveLeft,
    Stop
}

public class Block : MonoBehaviour
{
    private float timer = 0;
    private float moveSpeed = 0.8f;
    private float moveDownSpeed = 0.2f;
    private bool isCanMove = true;
    private Transform rotatePoint = null;
    private MoveType moveType = MoveType.Move;

    private void Start()
    {
        Init();
    }

    private void Update()
    {
        if (isCanMove)
        {
            if (Input.GetKeyDown(KeyCode.W))
            {
                controlMove(MoveType.Rotate);
            }

            if (Input.GetKeyDown(KeyCode.S))
            {
                controlMove(MoveType.MoveDown);
            }
            if (Input.GetKeyUp(KeyCode.S))
            {
                controlMove(MoveType.Move);
            }

            if (Input.GetKeyDown(KeyCode.A))
            {
                controlMove(MoveType.MoveLeft);
            }

            if (Input.GetKeyDown(KeyCode.D))
            {
                controlMove(MoveType.MoveRight);
            }
            TryMove(MoveType moveType);
        }
    }

    // 初始化方块
    public void Init()
    {
        // 初始化旋转点
        rotatePoint = transform.GetChild(transform.childCount - 1);
    }

    // 改变移动类型
    private void controlMove(MoveType moveType)
    {
        if (isCanMove)
        {
            this.moveType = moveType;
        }
    }

    // 方块移动
    private void TryMove(MoveType moveType = MoveType.Move)
    {
        switch (moveType)
        {
            case MoveType.Move:
                MoveFall();
                break;
            case MoveType.Rotate:
                Rotate();
                break;
            case MoveType.MoveDown:
                MoveDown();
                break;
            case MoveType.MoveLeft:
                MoveLeft();
                break;
            case MoveType.MoveRight:
                MoveRight();
                break;
            case MoveType.Stop:
                Stop();
                break;
        }
    }

    // 检查方块是否可以移动
    private bool IsCanMove()
    {
        // 检查是否超出边界
        for (int i = 0; i < transform.childCount - 1; i++)
        {
            int roundX = Mathf.RoundToInt(transform.GetChild(i).position.x);
            int roundY = Mathf.RoundToInt(transform.GetChild(i).position.y);
            if (roundY < 0 || roundX < 0 || roundX >= 10)
            {
                return false;
            }
            // 检查是否与其他方块重叠
            if (Board.grid[roundX, roundY] != null)
            {
                return false;
            }
        }
        return true;
    }

    // 方块下落
    private void MoveFall()
    {
        timer += Time.deltaTime;
        if (timer >= moveSpeed)
        {
            transform.position += Vector3.down;
            if (!IsCanMove())
            {
                transform.position -= Vector3.down;
                moveType = MoveType.Stop;
            }
            timer = 0;
        }
    }

    // 方块加快下落
    private void MoveDown()
    {
        timer += Time.deltaTime;
        if (timer >= moveDownSpeed)
        {
            transform.position += Vector3.down;
            if (!IsCanMove())
            {
                transform.position -= Vector3.down;
                moveType = MoveType.Stop;
            }
            timer = 0;
        }
    }
    // 方块向左移动
    private void MoveLeft()
    {

        transform.position += Vector3.left;
        if (!IsCanMove())
        {
            transform.position -= Vector3.left;
        }
        moveType = MoveType.Move;
    }

    // 方块向右移动
    private void MoveRight()
    {
        transform.position += Vector3.right;
        if (!IsCanMove())
        {
            transform.position -= Vector3.right;
        }
        moveType = MoveType.Move;
    }

    // 方块旋转
    private void Rotate()
    {
        transform.RotateAround(rotatePoint.position, Vector3.forward, -90);

        if (!IsCanMove())
        {
            transform.RotateAround(rotatePoint.position, Vector3.forward, 90);
        }
        moveType = MoveType.Move;
    }

    // 方块停止
    private void Stop()
    {
        isCanMove = false;
        // Debug.Log("Stop");
        for (int i = 0; i < transform.childCount - 1; i++)
        {
            int roundX = Mathf.RoundToInt(transform.GetChild(i).position.x);
            int roundY = Mathf.RoundToInt(transform.GetChild(i).position.y);
            // 添加方块到Board中
            Board.Instance.AddBlock(roundX, roundY, transform.GetChild(i));
        }

        // 检查游戏是否结束Debug.Log("检查游戏是否结束!");

        Board.Instance.IsGameOver(transform);

        // 消除行Debug.Log("检查是否消除行!");
        Board.Instance.CheckLine();

        // 生成新方块
        Board.Instance.SpawnBlock();

        enabled = false;
    }
}

Board.cs

这里继承了一个单例模式的泛型类,简而言之就是这里需要创建单例模式。

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

public class Board : SingletonMono<Board>
{
    public static int width = 10;
    public static int height = 15;
    public static Transform[,] grid = new Transform[width, height + 5];
    private int randIndex;       // 随机生成方块的索引
    private float timer = 0f;         // 计时器
    private float countdown = 1f;// 倒计时

    private GameObject generatorPoint;
    private Vector3 createPos;
    private GameObject[] blocks;
    private List<GameObject> blockList;


    protected override void Awake()
    {
        base.Awake();
        Init();
    }

    private void Start()
    {
        // Debug.Log(blockList.Count);
        SpawnBlock();
    }

    private void Update()
    {
        timer += Time.deltaTime;
        if (timer >= countdown)
        {
            ClearNullBlock();
            timer = 0;
        }
    }

    // 初始化
    private void Init()
    {
        generatorPoint = new GameObject();
        createPos = new Vector3(width / 2 - 1, height + 1, 0);
        generatorPoint.transform.position = createPos;
        // generatorPoint.transform.parent = transform;

        blockList = new List<GameObject>();
        blocks = Resources.LoadAll<GameObject>("Prefabs/Block");
        foreach (GameObject block in blocks)
        {
            blockList.Add(block);
        }

    }

    // 生成方块
    public void SpawnBlock()
    {
        randIndex = Random.Range(0, blockList.Count);
        if (blockList[randIndex].GetComponent<Block>() == null)
        {
            blockList[randIndex].AddComponent<Block>();
        }

        Instantiate(blockList[randIndex], generatorPoint.transform.position, Quaternion.identity, transform);
    }

    // 添加方块
    public void AddBlock(int x, int y, Transform block)
    {
        grid[x, y] = block.transform;
    }

    // 检查游戏是否结束
    public void IsGameOver(Transform block)
    {
        if (block.position.y >= createPos.y)
        {
            Debug.Log("Game Over");
        }
    }

    // 检查是否有可以消除的行
    public void CheckLine()
    {
        for (int i = height - 1; i >= 0; i--)
        {
            if (IsLineFull(i))
            {
                RemoveLine(i);
            }
        }
    }

    // 检查行是否满
    private bool IsLineFull(int y)
    {
        for (int i = 0; i < width; i++)
        {
            if (grid[i, y] == null)
            {
                return false;
            }
        }
        return true;
    }

    // 消除方块
    public void RemoveLine(int x)
    {
        for (int i = 0; i < width; i++)
        {
            Destroy(grid[i, x].gameObject);
            grid[i, x] = null;
        }
        MoveBlockdown(x);
    }

    // 下移方块
    public void MoveBlockdown(int h)
    {
        for (int i = h; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                if (grid[j, i] != null)
                {
                    grid[j, i - 1] = grid[j, i];
                    grid[j, i] = null;
                    grid[j, i - 1].position += Vector3.down;
                }
            }
        }
    }

    // 清理空对象
    private void ClearNullBlock()
    {
        for (int i = 1; i < transform.childCount; i++)
        {
            if (transform.GetChild(i).childCount == 1)
            {
                Destroy(transform.GetChild(i).gameObject);
            }
        }
    }
}

了解更多

【日志】unity俄罗斯方块(一)——边界限制检测-CSDN博客【日志】unity俄罗斯方块(二)——方块碰撞检测-CSDN博客


网站公告

今日签到

点亮在社区的每一天
去签到