unity消消乐制作(三)

匹配和掉落:

匹配算法:

public MatchItem MatchItems(GameObject item, Vector2 vector2)
	{
		 MatchItem match;
		//横向遍历到的所有相同元素
		List<GameObject> matchRowItems = new List<GameObject>();
		//纵向遍历到的所有相同元素
		List<GameObject> matchLineItems = new List<GameObject>();
		//最终可消除元素
		List<GameObject> finishedMatchItems = new List<GameObject>();

		//四方块的消除:
		List<GameObject> otherRowItems = new List<GameObject>();
		List<GameObject> otherLineItems = new List<GameObject>();

		List<GameObject> finish= new List<GameObject>();
		//先将选中的元素加入行匹配List
		matchRowItems.Add(item);
		matchLineItems.Add(item);
		//横向遍历
		//i=0代表往左遍历,i=1代表往右遍历
		//Column为横向最大值
		for (int i = 0; i <= 1; i++)
		{
			for (int xDistance = 1; xDistance <ConstClass.Column; xDistance++)
			{
				float x;
				//←左遍历的时候:
				if (i == 0)
				{
					x = vector2.y - xDistance;
				}
				//→右遍历的时候
				else
				{
					//	Debug.Log("右遍历");
					x = vector2.y + xDistance;
				}
				//判断横向是否到达边界
				if (x < 0 || x > ConstClass.Column)
				{
					break;
				}
				//判断是否为同一种元素    一个应该是itemX  ???
				if (objStore[vector2].GetComponent<ZYCell>().localTexture == objStore[new Vector2(vector2.x, x)].GetComponent<ZYCell>().localTexture)
				{

					//加入行list
					matchRowItems.Add(objStore[new Vector2(vector2.x, x)]);
					//Debug.Log(objStore[new Vector2(x, vector2.y)]);
				}
				else
				{
					break;
				}
			}
		}
		//竖向遍历
		for (int i = 0; i <= 1; i++)
		{
			for (int yDistance = 1; yDistance <ConstClass.Row; yDistance++)
			{
				float y;
				//上遍历的时候:
				if (i == 0)
				{
					y = vector2.x - yDistance;
				}
				//下遍历的时候
				else
				{
					//	Debug.Log("下遍历");
					y = vector2.x + yDistance;
				}
				//判断横向是否到达边界
				if (y < 0 || y >ConstClass.Row)
				{
					break;
				}
				//判断是否为同一种元素    一个应该是itemX  ???
				if (objStore[vector2].GetComponent<ZYCell>().localTexture == objStore[new Vector2(y, vector2.y)].GetComponent<ZYCell>().localTexture)
				{

					//加入行list
					matchLineItems.Add(objStore[new Vector2(y, vector2.y)]);
					//Debug.Log(objStore[new Vector2(x, vector2.y)]);
				}
				else
				{
					break;
				}
			}
		}
		if (matchRowItems.Count == 2)
		{
			//四个方块正方形的检测
			otherRowItems.AddRange(matchRowItems);
			Vector2 vector2_1 = otherRowItems[0].GetComponent<ZYCell>().localPosition;
			Vector2 vector2_2 = otherRowItems[1].GetComponent<ZYCell>().localPosition;
			if (vector2_1.x > 0 && vector2_2.x < ConstClass.Row)
			{
				if (objStore[new Vector2(vector2_1.x + 1, vector2_1.y)].GetComponent<ZYCell>().localTexture.Equals(otherRowItems[0].GetComponent<ZYCell>().localTexture))
				{
					if (objStore[new Vector2(vector2_2.x + 1, vector2_2.y)].GetComponent<ZYCell>().localTexture.Equals(otherRowItems[0].GetComponent<ZYCell>().localTexture))
					{
						otherLineItems.Add(objStore[new Vector2(vector2_1.x + 1, vector2_1.y)]);
						otherLineItems.Add(objStore[new Vector2(vector2_1.x + 1, vector2_2.y)]);
					}
				}
				else if (objStore[new Vector2(vector2_1.x - 1, vector2_1.y)].GetComponent<ZYCell>().localTexture.Equals(otherRowItems[0].GetComponent<ZYCell>().localTexture))
				{
					if (objStore[new Vector2(vector2_2.x - 1, vector2_2.y)].GetComponent<ZYCell>().localTexture.Equals(otherRowItems[0].GetComponent<ZYCell>().localTexture))
					{
						otherLineItems.Add(objStore[new Vector2(vector2_1.x - 1, vector2_1.y)]);
						otherLineItems.Add(objStore[new Vector2(vector2_1.x - 1, vector2_2.y)]);
					}
				}
			}
			else if (vector2_1.x == 0)
			{
				if (objStore[new Vector2(vector2_1.x + 1, vector2_1.y)].GetComponent<ZYCell>().localTexture.Equals(otherRowItems[0].GetComponent<ZYCell>().localTexture))
				{
					if (objStore[new Vector2(vector2_2.x + 1, vector2_2.y)].GetComponent<ZYCell>().localTexture.Equals(otherRowItems[0].GetComponent<ZYCell>().localTexture))
					{
						otherLineItems.Add(objStore[new Vector2(vector2_1.x + 1, vector2_1.y)]);
						otherLineItems.Add(objStore[new Vector2(vector2_1.x + 1, vector2_2.y)]);
					}
				}
			}
			else if (vector2_2.x == ConstClass.Row)
			{
				if (objStore[new Vector2(vector2_1.x - 1, vector2_1.y)].GetComponent<ZYCell>().localTexture.Equals(otherRowItems[0].GetComponent<ZYCell>().localTexture))
				{
					if (objStore[new Vector2(vector2_2.x - 1, vector2_2.y)].GetComponent<ZYCell>().localTexture.Equals(otherRowItems[0].GetComponent<ZYCell>().localTexture))
					{
						otherLineItems.Add(objStore[new Vector2(vector2_1.x - 1, vector2_1.y)]);
						otherLineItems.Add(objStore[new Vector2(vector2_1.x - 1, vector2_2.y)]);
					}
				}
			}
			if (otherLineItems.Count >= 2 && otherRowItems.Count >= 2)
			{
				Debug.Log(otherLineItems[0]);
				tempGo = otherLineItems[0];
				Invoke("DoBoom",0.3f);
			
				finishedMatchItems.AddRange(otherLineItems);
				finishedMatchItems.AddRange(otherRowItems);
			
			}
			else
			{
				otherRowItems.Clear();
				otherLineItems.Clear();
			}
		}
		//测试横向删除
		else if (matchRowItems.Count >= 3)
		{
			finishedMatchItems.AddRange(matchRowItems);
			
		}
		
		else
		{
			matchRowItems.Clear();
		}
		if (matchLineItems.Count >= 3)
		{
			finishedMatchItems.AddRange(matchLineItems);
			
		}
		else
		{
			matchLineItems.Clear();
		}



		if (finishedMatchItems.Count >= 3)
		{
			finish.AddRange(finishedMatchItems);
			match = new MatchItem(true, finish);
		}
		else
		{
			finishedMatchItems.Clear();
			match = new MatchItem(false, null);
		}
		matchRowItems.Clear();
		matchLineItems.Clear();
		finishedMatchItems.Clear();
		return match;
	}

思路很简单,就是遍历,遍历某个方块十字方向的方块,然后存储在相关的对应的数组里面,最后综合起来,计算长度,判断数量,完成了相关的匹配,匹配以后一定要清空相关的数组。
这里有大佬提供了另一种思路,就是将每一种可以消除的形状,存储在一个配置表里面,采用枚举的方法去看整个图里面有没有和形状相符的连接体,这个思路和代码会更简单,虽然看上去似乎你觉得这个方法有点平淡无奇,觉得枚举是个很小白的操作,但是这种方法后期的扩展性会变得非常好,假如后期要加入一些比较奇怪的形状进行扩展,使用复杂的算法的时候后期就需要去修改你的算法,很容易出错,但是这种配置的思路,就只需要简简单单加一个配置形状就行,扩展性非常好,值得研究。

掉落算法:

	public void Drop()
	{
		for (int i = 0; i <= ConstClass.Column; i++)
		{
			for (int j = ConstClass.Row; j >= 0; j--)
			{
				ZYCell DisShow = null;
				ZYCell Show = null;
				if (objStore[new Vector2(j, i)].GetComponent<ZYCell>().localTexture == null && j != 0)
				{
					DisShow = objStore[new Vector2(j, i)].GetComponent<ZYCell>();
					for (int k = j; k >= 0; k--)
					{
						if (objStore[new Vector2(k, i)].GetComponent<ZYCell>().localTexture != null)
						{
							Show = objStore[new Vector2(k, i)].GetComponent<ZYCell>();
							//更新个体内部数据
							DoExchange(DisShow, Show);
							MoveList.Add(Show);
							MoveList.Add(DisShow);
							
						}
					}
				}
			}
		}

		ConstClass.combo++;
		foreach (var item in MoveList)
		{
			item.MoveBack();

		}
		MoveList.Clear();
		Invoke("ChangeTexture", 0.3f);
		StartCoroutine("Judge");
	}
	IEnumerator Judge()
	{
		yield return new WaitForSeconds(0.5f);
		MatchItem match_1;
		List<GameObject> finishList = new List<GameObject>();
		foreach (var item in objStore.Values)
		{

			item.GetComponent<RawImage>().raycastTarget = false;
			//判断是否可以消除
			match_1 =MatchItems(item, item.GetComponent<ZYCell>().localPosition);
			if (match_1.finish != null)
			{
				//Debug.Log(item.name);
				list.Add(item);
			}
		}

		if (list.Count != 0)
		{
			foreach (var item in list)
			{
				if (item.GetComponent<ZYCell>().boomFlag == true)
				{
					for (int i = 0; i <= ConstClass.Row; i++)
					{
						for (int j = 0; j <= ConstClass.Column; j++)
						{
							if (objStore[new Vector2(i, j)].GetComponent<ZYCell>().localPosition.x == item.GetComponent<ZYCell>().localPosition.x || objStore[new Vector2(i, j)].GetComponent<ZYCell>().localPosition.y == item.GetComponent<ZYCell>().localPosition.y)
							{
								objStore[new Vector2(i, j)].transform.DOScale(new Vector3(0f, 0f, 0f), 0.1f);
								objStore[new Vector2(i, j)].GetComponent<RawImage>().color = Color.black;
								objStore[new Vector2(i, j)].GetComponent<ZYCell>().localTexture = null;
								objStore[new Vector2(i, j)].transform.SetAsFirstSibling();
							}
						}
					}
					item.GetComponent<ZYCell>().boomFlag = false;
					item.transform.DOScale(new Vector3(1, 1, 1), 0.3f);
				}
				else
				{
					item.GetComponent<RawImage>().color = Color.black;
					item.GetComponent<ZYCell>().localTexture = null;
					item.transform.SetAsFirstSibling();
					item.transform.DOScale(new Vector3(0f, 0f, 0f), 0.3f);
					ConstClass.count++;
				}
			}
			
			list.Clear();
			Drop();
		}
		else
		{
			Invoke("ClearCombo", 0.5f);
		}
	}
	public void ChangeTexture()
	{
		for (int p = 0; p <= ConstClass.Row; p++)
		{
			for (int q = 0; q <= ConstClass.Column; q++)
			{
				if (objStore[new Vector2(p, q)].GetComponent<ZYCell>().localTexture == null)
				{

					int cellTexture2 = Random.Range(1, 6);
					Texture newTexture = Resources.Load<Texture>("Texture/" + cellTexture2.ToString());
					objStore[new Vector2(p, q)].GetComponent<RawImage>().texture = newTexture;
					objStore[new Vector2(p, q)].GetComponent<ZYCell>().localTexture = objStore[new Vector2(p, q)].GetComponent<RawImage>().texture;
					objStore[new Vector2(p, q)].GetComponent<RawImage>().color = Color.white;
					objStore[new Vector2(p, q)].transform.DOScale(new Vector3(1f,1f,1f),0.3f);
					objStore[new Vector2(p, q)].transform.SetAsLastSibling();
				}
			}
		}
	}

掉落的整体思路其实很多,可以看到之前我们消除的时候其实不是真正的把消除物体Destroy掉,而是将上面的材质和颜色进行替换,内部的材质数据变成null,所以这里的思路就是当遇到内部材质数据是null的物体的时候,就往上寻找第一个材质不为空的物体,然后进行内部数据的更新和位置的交换,以此类推。如果上面没有物体了,那这个空物体就会自动生成一个材质,进行更换。其中Judge方法是干嘛的呢?当方块掉落之后,整个场景会重新出现可以消除的物体,这个时候就需要进行一个类似递归的操作,对整个场景进行遍历,有可以消除的,再次消除,然后掉落,直到最后没有可以消除的时候,跳出整个循环。这里一定要注意要有相应的跳出循环判断,不然整个unity会瞬间卡死,只能任务管理器来关闭了。
同时需要注意一个问题,在有数据交换的时候尽量不要在循环里面使用Dotween,会产生很多莫名其妙的bug,个人分析可能是因为dotween动画是一个过程,而在这个过程中,数据交换其实很快就会完成,然后继续向下个循环或者其他地方进行,不会等待动画完成,哪怕你使用了OnComplete方法也不行,所以最好将使用dotween方法的地方想办法移出循环。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值