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