本文實例為大家分享了Unity實現俄羅斯方塊遊戲的具體代碼,供大家參考,具體內容如下
一、演示
二、實現思路
創建每一個方塊可移動到的位置點,可以理解為創建一個遊戲地圖,從(0,0)點開始依次向x軸和y軸延伸,例如x最大為9,y最大為19,則創建了一個20行10列的地圖
製作每一個形狀的預製體,Shape是每一個整體形狀,Block是每一塊小方塊,CenterPos代表這個形狀的旋轉中心
創建GameController腳本控制遊戲邏輯,掛載到面板物體上。創建Shape腳本控制每個形狀的操作,掛載到每個形狀上
在GameController腳本中編寫生成形狀的邏輯
//當前方塊 public Shape CurShape { get; set; } private void Update() { if (CurShape == null) { SpawnBlock(); } } ////// 生成方塊 ///private void SpawnBlock() { int randomType = Random.Range(1, 8); GameObject shape = Instantiate(Resources.Load("Prefabs/Item/Shape" + randomType)); CurShape = shape.GetComponent(); CurShape.transform.SetParent(transform); CurShape.transform.position = new Vector2(4, 20); }
在Shape腳本中編寫形狀下落的邏輯
private float fallTimer;//下落的計時器 private float fallTimeval = 0.5f;//下落的時間間隔 private void Update() { //控制下落 if (fallTimer >= fallTimeval) { //下落 Fall(); fallTimer = 0; } else { fallTimer += Time.deltaTime; } } ////// 下落 ///private void Fall() { Vector3 curPos = transform.position; Vector3 targetPos = curPos; targetPos.y -= 1; transform.position = targetPos; }
但是此時形狀是可以無限下落的,到達底部也不會停止下落,所以我們需要編寫判定能否下落的方法
在GameController腳本編寫方法判定能否下落的邏輯,需要判定兩點,每個方塊的位置是否到達邊界和每個方塊的位置是否存在於地圖數組中,注意必須對每個方塊的位置進行四捨五入取整操作
public const int row_max = 23; public const int column_max = 10; public Transform[,] mapArray = new Transform[column_max, row_max];//地圖數組(保存每個方塊的位置信息) ////// 判斷是否為合法的位置 //////每一個形狀///public bool IsValidPos(Transform shape) { foreach (Transform block in shape.transform) { if (block.GetComponent() == null) continue; Vector2 blockPos = block.transform.position; blockPos = new Vector2(Mathf.RoundToInt(blockPos.x), Mathf.RoundToInt(blockPos.y)); if (IsBorder(blockPos) || mapArray[(int)blockPos.x, (int)blockPos.y] != null) { return false; } } return true; } ////// 判斷是否到達邊界 //////每一個方塊的位置///private bool IsBorder(Vector2 blockPos) { if (blockPos.x < 0 || blockPos.x >= column_max || blockPos.y < 0) { return true; } return false; }
在形狀下落的方法中添加判斷去控制是否能夠下落
private bool canFall = true;//能否下落 ////// 下落 ///private void Fall() { if (canFall == false) { return; } Vector3 curPos = transform.position; Vector3 targetPos = curPos; targetPos.y -= 1; transform.position = targetPos; if (GameController.Instance.IsValidPos(transform) == false) { targetPos.y += 1; transform.position = targetPos; FallToBottom(); } } ////// 下落到了底部 ///private void FallToBottom() { canFall = false; GameController.Instance.CurBlock = null; }
現在形狀與形狀之間並不會疊加,而是會重疊在一起,在GameController腳本中編寫方法,將每個方塊位置添加到地圖數組中(注意必須對每個方塊的位置進行四捨五入取整操作)
////// 將每個方塊位置添加到地圖數組中 //////public void AddEachBlockTransToMapArray(Transform shape) { foreach (Transform block in shape.transform) { if (block.GetComponent() == null) { continue; } Vector2 blockPos = block.position; blockPos = new Vector2(Mathf.RoundToInt(blockPos.x), Mathf.RoundToInt(blockPos.y)); mapArray[(int)blockPos.x, (int)blockPos.y] = block; } }
當形狀下落到底部時,將每一個方塊的位置添加到地圖數組中
////// 下落到底部 ///private void FallToBottom() { canFall = false; GameController.Instance.CurShape = null; //方塊下落到底部時將每個方塊位置添加到地圖數組中 GameController.Instance.AddEachBlockTransToMapArray(transform); }
控制形狀的左右移動
private void Update() { //控制左右移動 ControlMovement(); } ////// 控制左右移動 ///private void ControlMovement() { float h = 0; if (Input.GetKeyDown(KeyCode.RightArrow)) { h = 1; } else if (Input.GetKeyDown(KeyCode.LeftArrow)) { h = -1; } Vector3 curPos = transform.position; Vector3 targetPos = curPos; targetPos.x += h; transform.position = targetPos; if (GameController.Instance.IsValidPos(transform) == false) { targetPos.x -= h; transform.position = targetPos; } }
控制形狀的旋轉
private void Update() { //控制旋轉 ControlRotate(); } ////// 控制旋轉 ///private void ControlRotate() { if (Input.GetKeyDown(KeyCode.UpArrow)) { Transform rotateTrans = transform.Find("CenterPos"); transform.RotateAround(rotateTrans.position, Vector3.forward, -90); if (GameController.Instance.IsValidPos(transform) == false) { transform.RotateAround(rotateTrans.position, Vector3.forward, 90); } } }
控制加速下落
private void Update() { //控制加速下落 ControlUpspeed(); } ////// 控制加速 ///private void ControlUpspeed() { if (Input.GetKeyDown(KeyCode.DownArrow)) { fallTimeval = 0.05f; } if (Input.GetKeyUp(KeyCode.DownArrow)) { fallTimeval = 0.5f; } }
判斷整行的消除
先去判斷是否有行滿了,如果有則進行消除操作,消除時先刪除掉當前行的每一個方塊再將地圖數組中當前行置空,之後再將滿的行的上面行依次向下移動一行
////// 檢查是否有行滿了 ///private void CheckRowFull() { for (int row = 0; row < row_max; row++) { bool isFull = true; for (int column = 0; column < column_max; column++) { if (mapArray[column, row] == null) { isFull = false; break; } } //如果有行滿了 if (isFull) { //――――――――――――――――――――消除操作 ClearRow(row); MoveDownRow(row + 1); row--; } } } ////// 清除行 //////清除的行(滿的行)private void ClearRow(int _row) { for (int coloum = 0; coloum < column_max; coloum++) { Destroy(mapArray[coloum, _row].gameObject); mapArray[coloum, _row] = null; } } ////// 將清除的行上面的每一行依次向下移動一行 //////依次移動的起始行(清除的行的上面一行)private void MoveDownRow(int _row) { for (int row = _row; row < row_max; row++) { for (int column = 0; column < column_max; column++) { if (mapArray[column, row] != null) { mapArray[column, row - 1] = mapArray[column, row]; mapArray[column, row] = null; mapArray[column, row - 1].position -= Vector3.up; } } } }
判斷遊戲是否失敗
////// 判斷遊戲失敗 //////private bool IsGameover() { for (int row = row_max - 3; row < row_max; row++) { for (int column = 0; column < column_max; column++) { if (mapArray[column, row] != null) { return true; } } } return false; }
三、完整代碼
GameController腳本,控制遊戲整體邏輯
using UnityEngine; public class GameController : MonoSingleton{ public const int row_max = 23; public const int column_max = 10; private Transform[,] mapArray; //當前方塊 public Shape CurShape { get; set; } ////// 初始化數據 ///public void InitData() { mapArray = new Transform[column_max, row_max]; } ////// 清空地圖 ///public void ClearMap() { for (int row = 0; row < row_max; row++) { for (int column = 0; column < column_max; column++) { if (mapArray[column, row] != null) { Destroy(mapArray[column, row].gameObject); mapArray[column, row] = null; } } } } private void Update() { //if (GameManager.Instance.IsPause) //{ // return; //} if (CurShape == null) { SpawnBlock(); } } ////// 生成方塊 ///private void SpawnBlock() { Color randomColor = Random.ColorHSV(); int randomType = Random.Range(1, 8); GameObject shape = Instantiate(Resources.Load("Prefabs/Item/Shape" + randomType)); CurShape = shape.GetComponent(); CurShape.transform.SetParent(transform); CurShape.Init(new Vector2(4, 20), randomColor); } ////// 判斷是否為合法的位置 //////每一個形狀///public bool IsValidPos(Transform shape) { foreach (Transform block in shape.transform) { if (block.GetComponent() == null) continue; Vector2 blockPos = block.transform.position; blockPos = new Vector2(Mathf.RoundToInt(blockPos.x), Mathf.RoundToInt(blockPos.y)); if (IsBorder(blockPos) || mapArray[(int)blockPos.x, (int)blockPos.y] != null) { return false; } } return true; } ////// 判斷是否到達邊界 //////每一個方塊的位置///private bool IsBorder(Vector2 blockPos) { if (blockPos.x < 0 || blockPos.x >= column_max || blockPos.y < 0) { return true; } return false; } ////// 將每個方塊位置添加到地圖數組中 //////public void AddEachBlockTransToMapArray(Transform shape) { foreach (Transform block in shape.transform) { if (block.GetComponent() == null) { continue; } Vector2 blockPos = block.position; blockPos = new Vector2(Mathf.RoundToInt(blockPos.x), Mathf.RoundToInt(blockPos.y)); mapArray[(int)blockPos.x, (int)blockPos.y] = block; } //檢查是否有行滿了 CheckRowFull(); } ////// 檢查是否有行滿了 ///private void CheckRowFull() { for (int row = 0; row < row_max; row++) { bool isFull = true; for (int column = 0; column < column_max; column++) { if (mapArray[column, row] == null) { isFull = false; break; } } //如果有行滿了 if (isFull) { //――――――――――――――――――――消除操作 ClearRow(row); MoveDownRow(row + 1); row--; } } } ////// 清除行 //////清除的行(滿的行)private void ClearRow(int _row) { for (int coloum = 0; coloum < column_max; coloum++) { Destroy(mapArray[coloum, _row].gameObject); mapArray[coloum, _row] = null; } UIManager.Instance.FindUI().UpdateCurScore(); } ////// 將清除的行上面的每一行依次向下移動一行 //////依次移動的起始行(清除的行的上面一行)private void MoveDownRow(int _row) { for (int row = _row; row < row_max; row++) { for (int column = 0; column < column_max; column++) { if (mapArray[column, row] != null) { mapArray[column, row - 1] = mapArray[column, row]; mapArray[column, row] = null; mapArray[column, row - 1].position -= Vector3.up; } } } } ////// 判斷遊戲失敗 //////public bool IsGameover() { for (int row = row_max - 3; row < row_max; row++) { for (int column = 0; column < column_max; column++) { if (mapArray[column, row] != null) { return true; } } } return false; } }
Shape腳本,控制每個形狀的操作
using UnityEngine; public class Shape : MonoBehaviour { private bool canFall = true;//能否下落 private float fallTimer;//下落的計時器 private float fallTimeval = 0.5f;//下落的時間間隔 ////// 初始化形狀 /////////public void Init(Vector2 pos, Color color) { transform.position = pos; foreach (Transform child in transform) { if (child.GetComponent() != null) { child.GetComponent().color = color; } } } private void Update() { if (canFall == false) { return; } //控制下落 if (fallTimer >= fallTimeval) { //下落 Fall(); fallTimer = 0; } else { fallTimer += Time.deltaTime; } //控制加速下落 ControlUpspeed(); //控制左右移動 ControlMovement(); //控制旋轉 ControlRotate(); } ////// 控制左右移動 ///private void ControlMovement() { float h = 0; if (Input.GetKeyDown(KeyCode.RightArrow)) { h = 1; } else if (Input.GetKeyDown(KeyCode.LeftArrow)) { h = -1; } Vector3 curPos = transform.position; Vector3 targetPos = curPos; targetPos.x += h; transform.position = targetPos; if (GameController.Instance.IsValidPos(transform) == false) { targetPos.x -= h; transform.position = targetPos; } } ////// 控制旋轉 ///private void ControlRotate() { if (Input.GetKeyDown(KeyCode.UpArrow)) { Transform rotateTrans = transform.Find("CenterPos"); transform.RotateAround(rotateTrans.position, Vector3.forward, -90); if (GameController.Instance.IsValidPos(transform) == false) { transform.RotateAround(rotateTrans.position, Vector3.forward, 90); } } } ////// 控制加速 ///private void ControlUpspeed() { if (Input.GetKeyDown(KeyCode.DownArrow)) { fallTimeval = 0.05f; } if (Input.GetKeyUp(KeyCode.DownArrow)) { fallTimeval = 0.5f; } } ////// 下落 ///private void Fall() { Vector3 curPos = transform.position; Vector3 targetPos = curPos; targetPos.y -= 1; transform.position = targetPos; if (GameController.Instance.IsValidPos(transform) == false) { targetPos.y += 1; transform.position = targetPos; FallToBottom(); } } ////// 下落到底部 ///private void FallToBottom() { canFall = false; GameController.Instance.CurShape = null; //方塊下落到底部時將每個方塊位置添加到地圖數組中 GameController.Instance.AddEachBlockTransToMapArray(transform); if (GameController.Instance.IsGameover()) { GameManager.Instance.Gameover(); } } }
[ljg58026 ] Unity實現俄羅斯方塊遊戲已經有540次圍觀