C#和Unity俄罗斯方块,素材和源代码

俄罗斯方块大家应该都玩过,规则就不用介绍了,这里只是简单开发,高级程序还需要大家开发,用到的是c#Unity开发。

我使用的unity2018版。

以下是要用到的素材:
1.小方块
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
方块一共有七种形态,其他形态都是通过这7中旋转得来的,所以只创建这七种。
在这里插入图片描述
我们开始操作:
将小方块拼成上面所示的形状
在这里插入图片描述
创建一个Create Empty空物体,将四个物体放入空物体内,改名为T1,剩下的依次累加。
将他们放入文件夹中。
在这里插入图片描述
可以用方块拉长作为边界, 左边界Position的x值为-0.65,右边界Position的x值为9.66
单个方块的Scale的x,y值均为3.5后期方便运算

随机生成方块和分数显示

创建一个空物体,将该类附给他。

public class Builder : MonoBehaviour {
	public Text sText;
	public GameObject[] Default;
	void Start () {
		Aaa();
	}
	public void Aaa()
    {
    int i = Random.Range(0, Default.Length);//随机数
    GameObject ins = Instantiate(i], transform.position, transform.rotation);//实例化
    }
    void Update () {
		sText.text = Grid.j.ToString();//这个是分数显示文本
	}
}

在这里插入图片描述

方块的左移,右移,下移和旋转

public class Move : MonoBehaviour {
	public static float lastTime = 0;
    int k = 0;
    void Start () {
        if (!isValidGridPom())//判断游戏是否结束
        {
            Debug.Log(111);
            GameObject.Find("Canvas").GetComponent<Nmzx>().GameOver();
            Destroy(gameObject);
        }
	}
	
	// Update is called once per frame
	void Update () {
		if (Input.GetKeyDown(KeyCode.A))//按A键左移
        {
			transform.position += new Vector3(-1, 0,0);

            if (isValidGridPom())//若到达边界,按A键,先向左移动一格再向右移动一格,则不会移动,下面皆同理
            {
                Data();
            }
            else
            {
                transform.position += new Vector3(1, 0, 0);
            }
        }
        else if (Input.GetKeyDown(KeyCode.D))
        {
			transform.position += new Vector3(1, 0, 0);
            if (isValidGridPom())
            {
                Data();
            }
            else
            {
                transform.position += new Vector3(-1, 0, 0);
            }
        }
        else if (Input.GetKeyDown(KeyCode.S) ||
			Time.time - lastTime >= 1)//按S键和时间差>=1时向下移动一个格
        {
			transform.position += new Vector3(0, -1, 0);
            if (isValidGridPom())
            {
                Data();
            }
            else
            {
                transform.position += new Vector3(0, 1, 0);
                //调用实例化
                Grid.deleteFullRow();//若方块落下去
                FindObjectOfType<Builder>().Aaa();//实例化
                enabled = false;
            }
            lastTime = Time.time;
        }
        else if (Input.GetKeyDown(KeyCode.W))
        {
			transform.Rotate(0, 0, -90);
            if (isValidGridPom())
            {
                Data();
            }
            else
            {
                transform.Rotate(0, 0, 90);
            }
        }
	}

通过这个可以发现,方块虽然移动,但一直向下掉,所以我们写一个边界类

边界和消除

通过二维数组将区域分为好多小方块,以便消除和形成边界。
public class Grid : MonoBehaviour {
	public static int w = 10;
	public static int h = 20;
	public static  int j = 0;
	public static Transform[,] grid = new Transform[w, h];
	public static Vector2 roundVec2(Vector2 v)
    {
		return new Vector2(Mathf.Round(v.x), Mathf.Round(v.y));
    }
	// Use this for initialization
	void Start () {
	}
	
	// Update is called once per frame
	void Update () {
		
	}
	//保证每个被检查的位置不小于左边框,不大于右边框,不小于最小的y
	public static bool insideBorder(Vector2 pos)
    {
		return (pos.x >= 0 
			&& pos.x < w 
			&& pos.y >= 0);
    }

	public static bool isRowFull(int y)
	{
		for (int i = 0; i < w; ++i)
		{
            if (grid[i,y] ==null)
            {
				return false;
            }
		}
		return true;
	}

	public static void deleteRow(int y)
    {
        for (int i = 0; i < w; ++i)
        {
			Destroy(grid[i, y].gameObject);
			
			grid[i, y] = null;
        }
		j++;
	}
	//将方块向下移动
	public static void decreaseRow(int y)
    {
        for (int i = 0; i < w; ++i)
        {
            if (grid [i,y] != null)
            {
				grid[i, y - 1] = grid[i, y];
				grid[i, y] = null;
				grid[i, y - 1].position += new Vector3(0, -1, 0);
            }
        }
    }
	
	public static void decrease(int y)
    {
        for (int i = y; i < h; i++)
        {
			decreaseRow(i);
        }
    }

	public  static void deleteFullRow()
    {
        for (int i = 0; i < h; i++)
        {
            if (isRowFull(i))
            {
				deleteRow(i);
				decrease(i + 1);
            }
            else
				i++;
        }
    }
}

接下来在Move类中写判断生成的方块是否在游戏区域和方块在区域中的位置更新

 //判断是否在格子里
     bool isValidGridPom()
     {
        foreach (Transform child in transform)
        {
            Vector2 v = Grid.roundVec2(child.position);
            //判断是否在边境之内(左、右、下)
            if (!Grid.insideBorder(v))
            {
                return false;
            }
            //2.现在的grid对应的格子里面是null
            if (Grid.grid[(int)v.x, (int)v.y] != null && Grid.grid[(int)v.x, (int)v.y].parent != transform)
            {
                return false;
            }
        }
        return true;
    }
//更新方块在区域中的位置信息,以便消除和累积
   void Data()
    {
        for (int i = 0; i < Grid.h; i++)
        {
            for (int x = 0; x < Grid.w; x++)
            {
                if (Grid.grid[x, i] != null)
                {
                    if (Grid.grid[x,i].parent == transform)
                    {
                        Grid.grid[x, i] = null;
                    }
                }
            }
        }
        //
        foreach(Transform child in transform)
        {
            Vector2 v = Grid.roundVec2(child.position);
            Grid.grid[(int)v.x, (int)v.y] = child;
        }
    }

最后写游戏结束画面

在这里插入图片描述
最后写一个游戏结束类,将该类赋给Canvas,将Image拖入实例化对象
在这里插入图片描述

public class Nmzx : MonoBehaviour {

	public GameObject gameOverUI;
	bool isEnd = false;
	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		//if (isEnd) return;
       
	}

	public void GameOver()
    {
		gameOverUI.SetActive(true);
		//isEnd = true;
    }
}

当前代码只能支持一次消除一行和时间计时功能,若需要消除多行需自己完善。

感谢大家捧场

栏目
728_90 cn stocks