Unity实现俄罗斯方块游戏

2020-06-21 13:00:01王振洲
private void Update()
{
 //控制加速下落
 ControlUpspeed();
}
 
/// <summary>
/// 控制加速
/// </summary>
private void ControlUpspeed()
{
 if (Input.GetKeyDown(KeyCode.DownArrow))
 {
  fallTimeval = 0.05f;
 }
 if (Input.GetKeyUp(KeyCode.DownArrow))
 {
  fallTimeval = 0.5f;
 }
}

判断整行的消除

先去判断是否有行满了,如果有则进行消除操作,消除时先删除掉当前行的每一个方块再将地图数组中当前行置空,之后再将满的行的上面行依次向下移动一行

/// <summary>
/// 检查是否有行满了
/// </summary>
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--;
  }
 }
}
 
/// <summary>
/// 清除行
/// </summary>
/// <param name="row">清除的行(满的行)</param>
private void ClearRow(int _row)
{
 for (int coloum = 0; coloum < column_max; coloum++)
 {
  Destroy(mapArray[coloum, _row].gameObject);
  mapArray[coloum, _row] = null;
 }
}
 
/// <summary>
/// 将清除的行上面的每一行依次向下移动一行
/// </summary>
/// <param name="row">依次移动的起始行(清除的行的上面一行)</param>
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;
   }
  }
 }
}

判断游戏是否失败

/// <summary>
/// 判断游戏失败
/// </summary>
/// <returns></returns>
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<GameController>
{
 public const int row_max = 23;
 public const int column_max = 10;
 private Transform[,] mapArray;
 
 //当前方块
 public Shape CurShape { get; set; }
 
 /// <summary>
 /// 初始化数据
 /// </summary>
 public void InitData()
 {
  mapArray = new Transform[column_max, row_max];
 }
 
 /// <summary>
 /// 清空地图
 /// </summary>
 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();
  }
 }
 
 /// <summary>
 /// 生成方块
 /// </summary>
 private void SpawnBlock()
 {
  Color randomColor = Random.ColorHSV();
  int randomType = Random.Range(1, 8);
  GameObject shape = Instantiate(Resources.Load<GameObject>("Prefabs/Item/Shape" + randomType));
  CurShape = shape.GetComponent<Shape>();
  CurShape.transform.SetParent(transform);
  CurShape.Init(new Vector2(4, 20), randomColor);
 }
 
 /// <summary>
 /// 判断是否为合法的位置
 /// </summary>
 /// <param name="shape">每一个形状</param>
 /// <returns></returns>
 public bool IsValidPos(Transform shape)
 {
  foreach (Transform block in shape.transform)
  {
   if (block.GetComponent<SpriteRenderer>() == 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;
 }
 
 /// <summary>
 /// 判断是否到达边界
 /// </summary>
 /// <param name="pos">每一个方块的位置</param>
 /// <returns></returns>
 private bool IsBorder(Vector2 blockPos)
 {
  if (blockPos.x < 0 || blockPos.x >= column_max || blockPos.y < 0)
  {
   return true;
  }
  return false;
 }
 
 /// <summary>
 /// 将每个方块位置添加到地图数组中
 /// </summary>
 /// <param name="shapeTran"></param>
 public void AddEachBlockTransToMapArray(Transform shape)
 {
  foreach (Transform block in shape.transform)
  {
   if (block.GetComponent<SpriteRenderer>() == 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();
 }
 
 /// <summary>
 /// 检查是否有行满了
 /// </summary>
 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--;
   }
  }
 }
 
 /// <summary>
 /// 清除行
 /// </summary>
 /// <param name="row">清除的行(满的行)</param>
 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<UI_Game>().UpdateCurScore();
 }
 
 /// <summary>
 /// 将清除的行上面的每一行依次向下移动一行
 /// </summary>
 /// <param name="row">依次移动的起始行(清除的行的上面一行)</param>
 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;
    }
   }
  }
 }
 
 /// <summary>
 /// 判断游戏失败
 /// </summary>
 /// <returns></returns>
 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;
 }
}