俄罗斯方块大家应该都玩过,规则就不用介绍了,这里只是简单开发,高级程序还需要大家开发,用到的是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;
}
}
当前代码只能支持一次消除一行和时间计时功能,若需要消除多行需自己完善。
感谢大家捧场
转载:https://blog.csdn.net/m0_47605113/article/details/109111715
查看评论