unity 消消乐制作(二)

整体代码解析:

整体常量存储:

public const int Column=6;
	public const int Row=7;
	public int ConstraintCount;

	public GameObject count_Text;
	public GameObject combo_Text;
	public GameObject target_Text;

	public static int count=0;
	public int sum = 0;
	public static int combo = 0;
	public int origicombo;

	public static int step = 15;

	public int targetCount=200;

	void Awake()
	{
		count_Text.GetComponent<Text>().text = "当前分数:" + count;
		combo_Text.GetComponent<Text>().text = combo+"连击!";
		target_Text.GetComponent<Text>().text = "目标分数:" + targetCount;
		origicombo = combo;

		ConstraintCount = Row + 1;
		gameObject.GetComponent<GridLayoutGroup>().constraintCount = ConstraintCount;
	}
	void Update()
	{
		if (count >= targetCount)
		{
			count_Text.GetComponent<Text>().text = "恭喜通关!";
		}
		else
		{
			if (step <= 0)
			{
				count_Text.GetComponent<Text>().text = "Game Over!";

			}
			else
			{
				combo_Text.GetComponent<Text>().text = (combo - 1) + "连击!";
				//连击奖励
				if (origicombo != combo && combo > 1)
				{
					count += (combo - 1) * 5;
					origicombo = combo;
				}

				count_Text.GetComponent<Text>().text = "当前分数:" + count + "\n" + "步数:" + step;
				if (combo >= 2)
				{
					combo_Text.SetActive(true);
					combo_Text.transform.DOScale(new Vector3(2f, 2f, 2f), 0.5f);
				}
				else
				{
					combo_Text.SetActive(false);
					combo_Text.transform.DOScale(new Vector3(1f, 1f, 1f), 0.5f);
				}
			}
		}
	}

这里主要是对一些常量数据进行存储,单独列出一个脚本存储方便后面的修改,比如行和列,还有全局唯一的变量,比如分数和连击数等,同时相关逻辑也在这里进行了修改。

方块内部的数据:

//自身的二维坐标:
	public Vector2 localPosition = new Vector2();
	//自身的图片:
	public Texture localTexture = new Texture();
	//自身的真实坐标,方便自身做动画的时候进行移动:
	public Vector3 localPrePo = new Vector3();

	//是否是炸弹
	public bool boomFlag = false;

初始化逻辑:

public void CellInit()
	{
	
		int cellTexture = Random.Range(1, 6);
		localTexture = Resources.Load("Texture/" + cellTexture.ToString())as Texture;
	}

通过随机数来进行随机的材质添加,然后在Awake里面给自身的localTexture赋值就行,还有自身的坐标等。不过这里我遇到的问题就是刚开始初始化的时候坐标都是在一个点,所以用了一个延时初始化坐标,这样就可以保证在整体排列好以后坐标也不会错误,遇到这种问题的可以debug测验一下然后尝试一下这种方法。

void ListInit()
	{
		for (int i = 0; i <= ConstClass.Row; i++)
		{
			for (int j = 0; j <= ConstClass.Column; j++)
			{
				GameObject obj = GameObject.Instantiate(Resources.Load<GameObject>("Prefabs/Button"));
				obj.name = "item" + count;
				obj.transform.SetParent(gameObject.transform);
				obj.GetComponent<ZYCell>().localPosition = new Vector2(i, j);
				buttonsList.Add(obj);
				objStore.Add(new Vector2(i,j),obj);
				count++;
			}
		}
	}

这一段逻辑是用来初始化整体列表的,所有的物体都需要存储在一个数据结构上面方便后期存取。这里我使用的是一个Dictionary结构,键是每个点的二维坐标(不是真实坐标),值的话是物体本身。后面每一次对物体的交换或者消除,其实本质是对每个方块内部的数据进行改变和判断,同时也是对整个存储字典的数据维护,这两个搞不对或者忘记了维护的话,会产生各种问题,有问题的时候可以看看有对这两个进行维护没有。

拖拽的判断:

void Start()
	{
		beginPos = transform.position;
		image = transform.GetComponent<RawImage>();
		//Invoke("FirstDelet",0.2f);
		
	}
	public void OnBeginDrag(PointerEventData eventData)
	{
		beginPos = transform.position;
		beginMouse = eventData.position;	
		image.raycastTarget = false;
		transform.SetAsLastSibling();
	}

	public void OnDrag(PointerEventData eventData)
	{

		//进行移动条件判断,通过返回的向量角度来判度
		endMouse = eventData.position;
		float angle= Diraction(beginMouse, endMouse);
		//上移
		if (angle<135&&angle>45)
		{
			moveFlag = 1;
			transform.position = new Vector3(transform.position.x, Input.mousePosition.y, transform.position.z);
			if (Mathf.Abs(transform.position.y - beginPos.y) > 20f)
			{
				transform.position = new Vector3(transform.position.x,beginPos.y+20f,transform.position.z);
			}
		}
		//下移
		else if (angle>-135&&angle<-45 )
		{
			moveFlag = 2;
			transform.position = new Vector3(transform.position.x, Input.mousePosition.y, transform.position.z);
			if (Mathf.Abs(transform.position.y - beginPos.y) > 20f)
			{
				transform.position = new Vector3(transform.position.x,beginPos.y-20f,transform.position.z);
				
			}
		}
		//左移
		else if (angle < 180&& angle > 135  || angle >-180 && angle <-135 )
		{
			moveFlag = 3;
			transform.position = new Vector3(Input.mousePosition.x, transform.position.y, transform.position.z);
			if (Mathf.Abs(transform.position.x - beginPos.x) > 20f)
			{
				transform.position = new Vector3(beginPos.x - 20f, transform.position.y, transform.position.z);
			}
		}
		//右移
		else if (angle <45 && angle > -45 )
		{
			moveFlag = 4;
			transform.position = new Vector3(Input.mousePosition.x, transform.position.y, transform.position.z);
			if (Mathf.Abs(transform.position.x - beginPos.x) > 20f)
			{
				transform.position = new Vector3(beginPos.x + 20f, transform.position.y, transform.position.z);
			}
		}
		transform.DOScale(new Vector3(1.2f,1.2f,1.2f), 0.1f);

	}

	public void OnEndDrag(PointerEventData eventData)
	{
		//放下的时候进行条件判断,看是否满足消除条件,满足放下,不满足不放下
		Exchange();
		transform.DOScale(new Vector3(1f, 1f, 1f), 0.3f);
	}

这里比较重要的是对交换的判断,在开始拖拽的时候先获取鼠标的坐标,然后在进行拖拽的时候,进行相应的趋势判断,而不是单纯的拖拽。通过鼠标向量角度的计算,我们可以判断整体我们最后拖拽的趋势,这样当我们拖拽完成后,就可以实现让物体向我们拖拽方向的地方进行移动。同时拖拽的时候记得设置物体的raycastTarget值和 transform.SetAsLastSibling(),这样在拖拽的时候,物体就不会进行射线检测,同时物体会移到最上层,不会出现在移动的过程中去移动其他物体,其他物体会动的情况

相关关键方法

private bool IsFriend(ZYCell cellBegin, ZYCell cellEnd)
	{
		return (cellBegin.localPosition.x == cellEnd.localPosition.x && Mathf.Abs(cellBegin.localPosition.y -cellEnd.localPosition.y) == 1) || (cellBegin.localPosition.y== cellEnd.localPosition.y && Mathf.Abs(cellBegin.localPosition.x -cellEnd.localPosition.x) == 1);
	}

	//计算鼠标点和x轴的夹角,(45,135) 上,(-135,-45)下,(135,180)和(-180,-135)左,(-45,45)右
	public float Diraction(Vector3 beginMouse,Vector3 endMouse)
	{
		Vector3 dir = Vector3.Normalize(endMouse - beginMouse);
		Vector3 normalDir = new Vector3(1,0,0);
		dir = dir - Vector3.Project(dir, Vector3.forward);
		normalDir = normalDir - Vector3.Project(normalDir, Vector3.up);
		Vector3 cross = Vector3.Cross(dir, normalDir);
		float angle = Vector3.Angle(dir,normalDir);
		return cross.z > 0 ? -angle : angle;
	}

	public void Exchange()
	{
		//根据趋势来判断是否交换,拖到屏幕外的话就不交换	
			switch (moveFlag)
			{
				case 1:
				if (gameObject.GetComponent<ZYCell>().localPosition.x >0)
				{
					moveObj = ListCtr.objStore[new Vector2(gameObject.GetComponent<ZYCell>().localPosition.x - 1f, gameObject.GetComponent<ZYCell>().localPosition.y)];
				}
				else
				{
					gameObject.GetComponent<ZYCell>().MoveBack();
				}
				break;
				case 2:
				if(gameObject.GetComponent<ZYCell>().localPosition.x < ConstClass.Row)
				{ 
					moveObj = ListCtr.objStore[new Vector2(gameObject.GetComponent<ZYCell>().localPosition.x+1f, gameObject.GetComponent<ZYCell>().localPosition.y)];
				}
				else
				{
					gameObject.GetComponent<ZYCell>().MoveBack();
				}
				break;
				case 3:
				if (gameObject.GetComponent<ZYCell>().localPosition.y > 0)
				{
					moveObj = ListCtr.objStore[new Vector2(gameObject.GetComponent<ZYCell>().localPosition.x, gameObject.GetComponent<ZYCell>().localPosition.y - 1)];
				}
				else
				{
					gameObject.GetComponent<ZYCell>().MoveBack();
				}
				break;
				case 4:
				if (gameObject.GetComponent<ZYCell>().localPosition.y < ConstClass.Column)
				{
					moveObj = ListCtr.objStore[new Vector2(gameObject.GetComponent<ZYCell>().localPosition.x, gameObject.GetComponent<ZYCell>().localPosition.y + 1)];
				}
				else
				{
					gameObject.GetComponent<ZYCell>().MoveBack();
				}
				break;
			}
		if (moveObj != null)
		{
			DoMove(moveObj);
		}
		
	}
	//交换数据并消除
	public void DoMove(GameObject drag)
	{
		MatchItem match_1;
		MatchItem match_2;
		List<GameObject> finishList=new List<GameObject>();
		//交换位置
		Vector3 pos = drag.transform.position;
		drag.GetComponent<RawImage>().raycastTarget = false;
		//先交换两者内部数据,不交换位置
		LocalDataExchange(gameObject.GetComponent<ZYCell>(),drag.GetComponent<ZYCell>());
		//判断是否可以消除
		match_1 = ListCtr.Ins.MatchItems(gameObject, gameObject.GetComponent<ZYCell>().localPosition);
		if (match_1.finish != null)
		{
			finishList.AddRange(match_1.finish);
		}
		
		match_2 = ListCtr.Ins.MatchItems(drag, drag.GetComponent<ZYCell>().localPosition);
	
		if (match_2.finish!=null)
		{
			finishList.AddRange(match_2.finish);
		}

		//如果可以消除交换位置并执行消除逻辑
		if (match_1.isDelet || match_2.isDelet)
		{
			gameObject.GetComponent<ZYCell>().MoveBack();
			drag.GetComponent<ZYCell>().MoveBack();
			foreach (var item in finishList)
			{
				//如果里面有炸弹
				if (item.GetComponent<ZYCell>().boomFlag == true)
				{
					for (int i = 0; i <= ConstClass.Row; i++)
					{
						for (int j = 0; j <= ConstClass.Column; j++)
						{
							if (ListCtr.objStore[new Vector2(i, j)].GetComponent<ZYCell>().localPosition.x == item.GetComponent<ZYCell>().localPosition.x || ListCtr.objStore[new Vector2(i, j)].GetComponent<ZYCell>().localPosition.y == item.GetComponent<ZYCell>().localPosition.y)
							{
								ListCtr.objStore[new Vector2(i, j)].transform.DOScale(new Vector3(0f, 0f, 0f), 0.1f);
								ListCtr.objStore[new Vector2(i, j)].GetComponent<RawImage>().color = Color.black;
								ListCtr.objStore[new Vector2(i, j)].GetComponent<ZYCell>().localTexture = null;
								ListCtr.objStore[new Vector2(i, j)].transform.SetAsFirstSibling();
							}
						}
					}
					item.GetComponent<ZYCell>().boomFlag = false;
					item.transform.DOScale(new Vector3(1, 1, 1), 0.3f);
				}
				else
				{
					item.transform.transform.DOScale(new Vector3(0f, 0f, 0f), 0.1f);
					item.GetComponent<RawImage>().color = Color.black;
					item.GetComponent<ZYCell>().localTexture = null;
					item.transform.SetAsFirstSibling();

				}
			}
			ConstClass.count += finishList.Count;
			ConstClass.step--;
			finishList.Clear();
			ListCtr.Ins.Drop();
		}
		//否则把内部数据交换回来并回到原来的位置
		else
		{
			LocalDataExchange(gameObject.GetComponent<ZYCell>(), drag.GetComponent<ZYCell>());
			gameObject.GetComponent<ZYCell>().MoveBack();
			drag.GetComponent<ZYCell>().MoveBack();
		}

	}
	public void LocalDataExchange(ZYCell disShow, ZYCell show)
	{
		//个体维护
		Vector2 vector_a = disShow.localPosition;
		Vector2 vector_b = show.localPosition;
		disShow.localPosition = vector_b;
		show.localPosition = vector_a;
		Vector3 tra_a = disShow.localPrePo;
		Vector3 tra_b = show.localPrePo;
		disShow.localPrePo = tra_b;
		show.localPrePo = tra_a;

		//维护字典:
		ListCtr.objStore[disShow.localPosition] = disShow.gameObject;
		ListCtr.objStore[show.localPosition] = show.gameObject;
	}

代码会有些复杂,其实用字典存储可能不是更好的方法,因为寻找的时候整个代码巨长,根据大佬提示最好使用二维数组来进行整体的存储,会让代码简洁很多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值