欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Unity實現(xiàn)俄羅斯方塊游戲

 更新時間:2020年06月21日 10:20:06   作者:LLLLL__  
這篇文章主要為大家詳細(xì)介紹了Unity實現(xiàn)俄羅斯方塊游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了Unity實現(xiàn)俄羅斯方塊游戲的具體代碼,供大家參考,具體內(nèi)容如下

一、演示

二、實現(xiàn)思路

創(chuàng)建每一個方塊可移動到的位置點,可以理解為創(chuàng)建一個游戲地圖,從(0,0)點開始依次向x軸和y軸延伸,例如x最大為9,y最大為19,則創(chuàng)建了一個20行10列的地圖

制作每一個形狀的預(yù)制體,Shape是每一個整體形狀,Block是每一塊小方塊,CenterPos代表這個形狀的旋轉(zhuǎn)中心

創(chuàng)建GameController腳本控制游戲邏輯,掛載到面板物體上。創(chuàng)建Shape腳本控制每個形狀的操作,掛載到每個形狀上

在GameController腳本中編寫生成形狀的邏輯

//當(dāng)前方塊
public Shape CurShape { get; set; }
 
private void Update()
{
 if (CurShape == null)
 {
  SpawnBlock();
 }
}
 
/// <summary>
/// 生成方塊
/// </summary>
private void SpawnBlock()
{
 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.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;
 }
}
 
 
/// <summary>
/// 下落
/// </summary>
private void Fall()
{
 Vector3 curPos = transform.position;
 Vector3 targetPos = curPos;
 targetPos.y -= 1;
 transform.position = targetPos;
}

但是此時形狀是可以無限下落的,到達(dá)底部也不會停止下落,所以我們需要編寫判定能否下落的方法
在GameController腳本編寫方法判定能否下落的邏輯,需要判定兩點,每個方塊的位置是否到達(dá)邊界和每個方塊的位置是否存在于地圖數(shù)組中,注意必須對每個方塊的位置進(jìn)行四舍五入取整操作

public const int row_max = 23;
public const int column_max = 10;
public Transform[,] mapArray = new Transform[column_max, row_max];//地圖數(shù)組(保存每個方塊的位置信息)
 
/// <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>
/// 判斷是否到達(dá)邊界
/// </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;
}

在形狀下落的方法中添加判斷去控制是否能夠下落

private bool canFall = true;//能否下落
 
/// <summary>
/// 下落
/// </summary>
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();
 }
}
 
/// <summary>
/// 下落到了底部
/// </summary>
private void FallToBottom()
{
 canFall = false;
 GameController.Instance.CurBlock = null;
}

現(xiàn)在形狀與形狀之間并不會疊加,而是會重疊在一起,在GameController腳本中編寫方法,將每個方塊位置添加到地圖數(shù)組中(注意必須對每個方塊的位置進(jìn)行四舍五入取整操作)

/// <summary>
/// 將每個方塊位置添加到地圖數(shù)組中
/// </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;
 }
}

當(dāng)形狀下落到底部時,將每一個方塊的位置添加到地圖數(shù)組中

/// <summary>
/// 下落到底部
/// </summary>
private void FallToBottom()
{
 canFall = false;
 GameController.Instance.CurShape = null;
 
 //方塊下落到底部時將每個方塊位置添加到地圖數(shù)組中
 GameController.Instance.AddEachBlockTransToMapArray(transform);
}

控制形狀的左右移動

private void Update()
{
 //控制左右移動
 ControlMovement();
}
 
/// <summary>
/// 控制左右移動
/// </summary>
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;
 }
}

控制形狀的旋轉(zhuǎn)

private void Update()
{
 //控制旋轉(zhuǎn)
 ControlRotate();
}
 
/// <summary>
/// 控制旋轉(zhuǎn)
/// </summary>
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();
}
 
/// <summary>
/// 控制加速
/// </summary>
private void ControlUpspeed()
{
 if (Input.GetKeyDown(KeyCode.DownArrow))
 {
  fallTimeval = 0.05f;
 }
 if (Input.GetKeyUp(KeyCode.DownArrow))
 {
  fallTimeval = 0.5f;
 }
}

判斷整行的消除

先去判斷是否有行滿了,如果有則進(jìn)行消除操作,消除時先刪除掉當(dāng)前行的每一個方塊再將地圖數(shù)組中當(dāng)前行置空,之后再將滿的行的上面行依次向下移動一行

/// <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;
 
 //當(dāng)前方塊
 public Shape CurShape { get; set; }
 
 /// <summary>
 /// 初始化數(shù)據(jù)
 /// </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>
 /// 判斷是否到達(dá)邊界
 /// </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>
 /// 將每個方塊位置添加到地圖數(shù)組中
 /// </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;
 }
}

Shape腳本,控制每個形狀的操作

using UnityEngine;
 
public class Shape : MonoBehaviour
{
 private bool canFall = true;//能否下落
 
 private float fallTimer;//下落的計時器
 private float fallTimeval = 0.5f;//下落的時間間隔
 
 /// <summary>
 /// 初始化形狀
 /// </summary>
 /// <param name="pos"></param>
 /// <param name="color"></param>
 public void Init(Vector2 pos, Color color)
 {
  transform.position = pos;
 
  foreach (Transform child in transform)
  {
   if (child.GetComponent<SpriteRenderer>() != null)
   {
    child.GetComponent<SpriteRenderer>().color = color;
   }
  }
 }
 
 private void Update()
 {
  if (canFall == false)
  {
   return;
  }
 
  //控制下落
  if (fallTimer >= fallTimeval)
  {
   //下落
   Fall();
 
   fallTimer = 0;
  }
  else
  {
   fallTimer += Time.deltaTime;
  }
 
  //控制加速下落
  ControlUpspeed();
 
  //控制左右移動
  ControlMovement();
 
  //控制旋轉(zhuǎn)
  ControlRotate();
 }
 
 /// <summary>
 /// 控制左右移動
 /// </summary>
 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;
  }
 }
 
 /// <summary>
 /// 控制旋轉(zhuǎn)
 /// </summary>
 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);
   }
  }
 }
 
 /// <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 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();
  }
 }
 
 /// <summary>
 /// 下落到底部
 /// </summary>
 private void FallToBottom()
 {
  canFall = false;
  GameController.Instance.CurShape = null;
 
  //方塊下落到底部時將每個方塊位置添加到地圖數(shù)組中
  GameController.Instance.AddEachBlockTransToMapArray(transform);
 
  if (GameController.Instance.IsGameover())
  {
   GameManager.Instance.Gameover();
  }
 }
}

更多俄羅斯方塊精彩文章請點擊專題:俄羅斯方塊游戲集合 進(jìn)行學(xué)習(xí)。

更多有趣的經(jīng)典小游戲?qū)崿F(xiàn)專題,分享給大家:

C++經(jīng)典小游戲匯總

python經(jīng)典小游戲匯總

python俄羅斯方塊游戲集合

JavaScript經(jīng)典游戲 玩不停

javascript經(jīng)典小游戲匯總

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C# MVC 微信支付教程系列之公眾號支付代碼

    C# MVC 微信支付教程系列之公眾號支付代碼

    本篇文章主要介紹了C# MVC 微信支付教程系列之公眾號支付代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • C#實現(xiàn)帶陰歷顯示的日期代碼

    C#實現(xiàn)帶陰歷顯示的日期代碼

    這篇文章主要介紹了C#實現(xiàn)帶陰歷顯示的日期代碼,可以顯示節(jié)假日及農(nóng)歷日期,在C#項目開發(fā)中非常具有實用價值,需要的朋友可以參考下
    2014-10-10
  • c# NPOI 如何在指定單元格導(dǎo)入導(dǎo)出圖片

    c# NPOI 如何在指定單元格導(dǎo)入導(dǎo)出圖片

    這篇文章主要介紹了c# NPOI 如何在指定單元格導(dǎo)入導(dǎo)出圖片,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下
    2021-03-03
  • WPF中圖像處理的方法介紹

    WPF中圖像處理的方法介紹

    這篇文章介紹了WPF中圖像處理的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • C#使用channel實現(xiàn)Plc異步任務(wù)之間的通信

    C#使用channel實現(xiàn)Plc異步任務(wù)之間的通信

    在C#的并發(fā)編程中,Channel是一種非常強大的數(shù)據(jù)結(jié)構(gòu),用于在生產(chǎn)者和消費者之間進(jìn)行通信,本文將給大家介紹C#使用channel實現(xiàn)Plc異步任務(wù)之間的通信,文中有相關(guān)的代碼示例供大家參考,感興趣的朋友跟著小編一起來看看吧
    2024-05-05
  • C#實現(xiàn)注冊碼的方法

    C#實現(xiàn)注冊碼的方法

    這篇文章主要介紹了C#實現(xiàn)注冊碼的方法,可實現(xiàn)C#生成軟件注冊碼的相關(guān)功能,涉及C#硬件操作及隨機數(shù)操作的相關(guān)技巧,非常具有實用價值,需要的朋友可以參考下
    2015-08-08
  • 在C#中實現(xiàn)接口事件的具體示例

    在C#中實現(xiàn)接口事件的具體示例

    在C#中,接口(interface)是一種定義類必須實現(xiàn)的方法和屬性的抽象類型,除了方法和屬性,接口還可以包含事件,實現(xiàn)接口事件可以幫助我們設(shè)計更加靈活和解耦的系統(tǒng),本文將詳細(xì)探討如何在C#中實現(xiàn)接口事件,并通過具體示例說明其應(yīng)用,需要的朋友可以參考下
    2024-08-08
  • C#控制鍵盤按鍵的常用方法

    C#控制鍵盤按鍵的常用方法

    這篇文章主要介紹了C#控制鍵盤按鍵的常用方法,涉及C#針對鍵盤大寫、滾動、數(shù)字的開啟與鎖定等功能,非常簡單實用,需要的朋友可以參考下
    2015-05-05
  • C#實現(xiàn)裝箱與拆箱操作簡單實例

    C#實現(xiàn)裝箱與拆箱操作簡單實例

    這篇文章主要介紹了C#實現(xiàn)裝箱與拆箱操作,對于新手理解裝箱與拆箱有一定的幫助,需要的朋友可以參考下
    2014-07-07
  • c#下將.cs文件編譯成dll

    c#下將.cs文件編譯成dll

    c#下將.cs文件編譯成dll...
    2007-07-07

最新評論