Tetris / 俄罗斯方块

游戏展示

Tetris

游戏开发

Shape / 形状

  • Assets > Create > Sprites > Square
  • Hierarchy

Ctrl+D, W, Crrl + 方向键

  • Inspector
    • Transform
      • Scale
        • X: 0.9
        • Y: 0.9
    • Sprite Renderer
      • Color: Pink

制作 7 种方块

Move Left Right / 左右移动

添加坐标原点

ValidMove() 每一个小方块如果超出边界,为非法操作,需要退回上一状态。

1
bool ValidMove()
2
{
3
    foreach (Transform child in transform)
4
    {
5
        int roundedX = Mathf.RoundToInt(child.transform.position.x);
6
        int roundedY = Mathf.RoundToInt(child.transform.position.y);
7
8
        if (roundedX < 0 || roundedX >= width || roundedY < 0 || roundedY >= height)
9
        {
10
            return false;
11
        }
12
    }
13
14
    return true;
15
}

左右移动,如果移动非法,还原。

1
void Update()
2
{
3
    if (Input.GetKeyDown(KeyCode.LeftArrow))
4
    {
5
        transform.position += new Vector3(-1, 0, 0);
6
7
        if (!ValidMove())
8
        {
9
            transform.position -= new Vector3(-1, 0, 0);
10
        }
11
    }
12
    else if (Input.GetKeyDown(KeyCode.RightArrow))
13
    {
14
        transform.position += new Vector3(1, 0, 0);
15
16
        if (!ValidMove())
17
        {
18
            transform.position -= new Vector3(1, 0, 0);
19
        }
20
    }
21
22
    if (Time.time - previousTime > (Input.GetKey(KeyCode.DownArrow) ? fallTime / 10 : fallTime))
23
    {
24
        transform.position += new Vector3(0, -1, 0);
25
26
        previousTime = Time.time;
27
    }
28
}

Rotate / 旋转

找到旋转的中心,我这里没有按照图片上的操作,除了 字方块为 (0.5, 0.5, 0) 为旋转中心外,其它均为 0 号方块的中心 (0, 0, 0)

1
void Update()
2
{
3
    // ...
4
    else if (Input.GetKeyDown(KeyCode.UpArrow))
5
    {
6
        // local position -> global position
7
        transform.RotateAround(transform.TransformPoint(rotationPoint), new Vector3(0, 0, 1), 90f);
8
9
        if (!ValidMove())
10
        {
11
            transform.RotateAround(transform.TransformPoint(rotationPoint), new Vector3(0, 0, 1), -90f);
12
        }
13
    }
14
}

Collider / 碰撞检测

生成器生成方块

1
using UnityEngine;
2
3
public class Spawn : MonoBehaviour
4
{
5
    public GameObject[] tetrominoes;
6
7
    void Start()
8
    {
9
        NewTetromino();
10
    }
11
12
    public void NewTetromino()
13
    {
14
        Instantiate(tetrominoes[Random.Range(0, tetrominoes.Length)], transform.position, Quaternion.identity);
15
    }
16
}

使用二维数组存放小方块的值

1
private void AddToGrid()
2
{
3
    foreach (Transform child in transform)
4
    {
5
        int roundedX = Mathf.RoundToInt(child.transform.position.x);
6
        int roundedY = Mathf.RoundToInt(child.transform.position.y);
7
8
        grid[roundedX, roundedY] = child;
9
    }
10
}

当前小方块为 null,才可以移动

1
bool ValidMove()
2
{
3
    foreach (Transform child in transform)
4
    {
5
        // ...
6
        
7
        if (grid[roundedX, roundedY] != null)
8
        {
9
            return false;
10
        }
11
    }
12
13
    return true;
14
}

Clean Line / 消行

算法

1
1. 检测每一行,如果成行
2
    1. 删除当前行
3
    1. 上面的行下移
1
private void CheckForLines()
2
{
3
    for (int row = height - 1; row >= 0; row--)
4
    {
5
        if (HasLine(row))
6
        {
7
            DeleteLine(row);
8
            RowDown(row);
9
        }
10
    }
11
}

如果成行

1
private bool HasLine(int row)
2
{
3
    for (int col = 0; col < width; col++)
4
    {
5
        if (grid[col, row] == null)
6
        {
7
            return false;
8
        }
9
    }
10
11
    return true;
12
}
删除当前行
1
private void DeleteLine(int row)
2
{
3
    for (int col = 0; col < width; col++)
4
    {
5
        Destroy(grid[col, row].gameObject);
6
        grid[col, row] = null;
7
    }
8
}
上面的行下移
private void RowDown(int currentRow)
{
    for (int row = currentRow; row < height; row++)
    {
        for (int col = 0; col < width; col++)
        {
            if (grid[col, row] != null)
            {
                grid[col, row - 1] = grid[col, row];
                grid[col, row] = null;
                grid[col, row - 1].transform.position -= new Vector3(0, 1, 0);
            }
        }
    }
}

Audio / 音效

Background 添加 Audio Source

  • Inspector
    • Audio Source
      • AudioClip: Tetris
      • Play On Awake: true
      • Loop: true

导出游戏

  • File
    • Build Settings (Shift + Cmd + B)

Build Settings

  • Project Settings

小结

按照教程终于实现了,10 分钟的教程,做了几个小时才完成,主要是对大方块的 (x, y, z) 坐标一开始没有归整,0 号方块应该中心点是 (0, 0, 0) ,在部分大方块都应该按照 0 号方块旋转。

参考:

  1. CODING MY OWN TETRIS (Unity)

下载

游戏

Release: https://github.com/GameDevLog/GameDevLogTemplete/releases

源码

GitHub: https://github.com/GameDevLog/GameDevLogTemplete

找到游戏列表对应的 GameDevLog

本文标题:Tetris / 俄罗斯方块

文章作者:iOSDevLog

发布时间:2019年12月14日 - 19:09:37

最后更新:2019年12月19日 - 15:40:59

原始链接:https://game.iosdevlog.com/2019/12/14/Tetris/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

iOSDevLog wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!