C#和Unity俄羅斯方塊,素材和原始碼

2020-10-17 17:00:11

俄羅斯方塊大家應該都玩過,規則就不用介紹了,這裡只是簡單開發,高階程式還需要大家開發,用到的是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;
    }
}

當前程式碼只能支援一次消除一行和時間計時功能,若需要消除多行需自己完善。

感謝大家捧場