private bool IsMustFillNode(StageNode node) { var downLeft = node.GetDownLeft(); var downRight = node.GetDownRight(); if (downLeft != null && downLeft.BubbType != BubbType.Empty) { var downLeftUpLeft = downLeft.GetUpLeft(); if (downLeftUpLeft == null || downLeftUpLeft.BubbType == BubbType.Empty) { return(true); } } if (downRight != null && downRight.BubbType != BubbType.Empty) { var downRightUpRight = downRight.GetUpRight(); if (downRightUpRight == null || downRightUpRight.BubbType == BubbType.Empty) { return(true); } } return(false); }
// 合并parent private void CombineParentSet(StageNode parent1, StageNode parent2) { var parent = parent2.Row < parent1.Row ? parent2 : parent1; var child = parent2.Row < parent1.Row ? parent1 : parent2; foreach (var node in _parentRecords[child]) { node.ParentNode = parent; } _parentRecords[parent].UnionWith(_parentRecords[child]); _parentRecords.Remove(child); }
// 在某个Node生成泡泡,并更新并查集 private void SpawnStageBubble(StageNode node) { if (node.BubbType == BubbType.Empty || node.BubbType == BubbType.Colorful) { return; } // 遍历周围的泡泡,重设parent foreach (var sideNode in node) { // 同色的合并 if (sideNode?.BubbType == node.BubbType) { // ReSharper disable once PossibleNullReferenceException if (sideNode.ParentNode == null && node.ParentNode == null) { node.ParentNode = node; sideNode.ParentNode = node; _parentRecords[node] = new HashSet <StageNode> { node, sideNode }; } else if (sideNode.ParentNode != null && node.ParentNode == null) { node.ParentNode = sideNode.ParentNode; _parentRecords[sideNode.ParentNode].Add(node); } else if (sideNode.ParentNode == null && node.ParentNode != null) { sideNode.ParentNode = node.ParentNode; _parentRecords[node.ParentNode].Add(sideNode); } else if (sideNode.ParentNode != node.ParentNode) { CombineParentSet(sideNode.ParentNode, node.ParentNode); } } } // 如果周围没同色的 if (node.ParentNode == null) { node.ParentNode = node; _parentRecords[node] = new HashSet <StageNode> { node }; } var stageBubble = Instantiate(GameCfg.StageBubble, node.AnchorPos, Quaternion.identity, _stageBubbParent).GetComponent <StageBubble>(); stageBubble.Respawn(node); }
// 碰撞到泡泡回调 public void OnCollideStageBubble(Collision2D collision) { var involveBubb = collision.gameObject.GetComponent <StageBubble>(); var involveNode = involveBubb.StageNode; var contactPoint = collision.GetContact(0).point; var flyBubble = _lazyFlyBubble.Value; StageNode targetNode = null; foreach (var sideNode in involveNode) { if (sideNode == null || sideNode.BubbType != BubbType.Empty) { continue; } // 空泡泡位置离飞行泡泡的距离超过一个半径 var flyPos = new Vector2(flyBubble.transform.position.x, flyBubble.transform.position.y); var ditanceToFly = Vector2.SqrMagnitude(sideNode.AnchorPos - flyPos); if (ditanceToFly > GameConstant.BubbRadius * GameConstant.BubbRadius) { continue; } if (targetNode == null) { targetNode = sideNode; } else { var distancePre = Vector2.SqrMagnitude(targetNode.AnchorPos - contactPoint); var distanceNow = Vector2.SqrMagnitude(sideNode.AnchorPos - contactPoint); if (distanceNow < distancePre) { targetNode = sideNode; } } } if (targetNode == null) { StartCoroutine(SetLevelResult(LevelResult.FailToFindNode)); return; } targetNode.BubbType = flyBubble.BubbType == BubbType.Colorful ? involveNode.BubbType : flyBubble.BubbType; OnFindNodeSuccAfterCollide(targetNode); }
// 碰到Stage上边缘 public void OnCollideStageTopEdge(Collision2D collision) { var contactPoint = collision.contacts[0].point; StageNode targetNode = null; foreach (var rowNode in StageNodeData[0]) { if (rowNode.BubbType != BubbType.Empty) { continue; } if (targetNode == null) { targetNode = rowNode; } else { var disPre = Vector2.SqrMagnitude(targetNode.AnchorPos - contactPoint); var disNow = Vector2.SqrMagnitude(rowNode.AnchorPos - contactPoint); if (disNow < disPre) { targetNode = rowNode; } } } if (targetNode == null) { StartCoroutine(SetLevelResult(LevelResult.FailToFindNode)); return; } if (_lazyFlyBubble.Value.BubbType == BubbType.Colorful) { var weights = GameCfg.LevelTunnings[Level].StageBubbWeights; targetNode.BubbType = weights.SelectByWeight(); } else { targetNode.BubbType = _lazyFlyBubble.Value.BubbType; } OnFindNodeSuccAfterCollide(targetNode); }
private void OnFindNodeSuccAfterCollide(StageNode stageNode) { SpawnStageBubble(stageNode); var wipeCount = WipeBubbleAfterCollide(stageNode); if (wipeCount > 0) { // 计算得分 var wipeLevel = CalcWipeScore(wipeCount); _gamePanel.UpdateScore(wipeLevel); // 通关 _stageBubbParent.GetComponentsInChildren(_bubbsCache); if (_bubbsCache.Count == wipeCount) { StartCoroutine(SetLevelResult(LevelResult.Pass)); return; } } // 下移 var cfgTimes = GameCfg.LevelTunnings[Level].MoveDownFlyTimes; if (cfgTimes != 0 && FlyCount % cfgTimes == 0) { if (CanMoveDown()) { var leftBubbs = _stageBubbParent.childCount - wipeCount; StartCoroutine(MoveDownWait(leftBubbs)); } else { StartCoroutine(SetLevelResult(LevelResult.FailToMoveDown)); } } else { _gamePanel.SpawnWaitBubble(); } }
private void InitLevelStage() { // 数据 foreach (var row in StageNodeData) { row.Clear(); } var lvlTunning = GameCfg.LevelTunnings[Level]; var initBubbs = lvlTunning.InitBubles; for (var row = 0; row < StageNodeData.Count; ++row) { var rowCount = StageAnchorData.GetRowAnchorsCount(row); for (var col = 0; col < rowCount; ++col) { var cfgClr = row < initBubbs.GetLength(0) ? initBubbs[row, col] : BubbType.Empty; if (cfgClr == BubbType.Colorful) { cfgClr = BubbTypeUtil.GetRandomStageType(); } var node = new StageNode { Row = row, Col = col, BubbType = cfgClr, AnchorPos = StageAnchorData[row, col] }; StageNodeData[row].Add(node); } } foreach (var rowNodes in StageNodeData) { foreach (var node in rowNodes) { SpawnStageBubble(node); } } _gamePanel.Reset(); }
// 消除泡泡,返回消除的个数 private int WipeBubbleAfterCollide(StageNode stageNode) { var wipeNodes = _parentRecords[stageNode.ParentNode]; if (wipeNodes.Count < GameConstant.BubbWipeThreshold) { return(0); } // 没有挂载点的泡泡 for (var row = 0; row < GameConstant.StageRowCount; ++row) { for (var col = 0; col < StageNodeData[row].Count; ++col) { var node = StageNodeData[row][col]; GenLinkDataByBubb(node); } } _nodesCache.Clear(); // GenLinkDataByBubb 用到了缓存 foreach (var wipe in wipeNodes) { if (wipe.ParentNode == wipe) { _parentRecords.Remove(wipe); } wipe.BubbType = BubbType.Empty; wipe.ParentNode = null; } _stageBubbParent.GetComponentsInChildren(_bubbsCache); _bubbsCache.RemoveAll(bubb => !wipeNodes.Contains(bubb.StageNode)); foreach (var bubb in _bubbsCache) { bubb.PlayWipeAnim(); } return(wipeNodes.Count); #region 局部函数 // 从某个泡泡生成连接数据 void GenLinkDataByBubb(StageNode node) { if (node.BubbType == BubbType.Empty || _nodesCache.Contains(node) || wipeNodes.Contains(node)) { return; } var isLink = IsBubbLinkToTop(node, _nodesPathCache); if (isLink) { _nodesCache.UnionWith(_nodesPathCache); } else { wipeNodes.UnionWith(_nodesPathCache); } _nodesPathCache.Clear(); } // 判断某个泡泡是否连到顶部 bool IsBubbLinkToTop(StageNode node, HashSet <StageNode> path) { if (!path.Add(node) || wipeNodes.Contains(node)) { return(false); } if (node.Row == 0 || wipeNodes.Contains(node)) { return(true); } foreach (var sideNode in node) { if (sideNode == null || sideNode.BubbType == BubbType.Empty) { continue; } var isLink = IsBubbLinkToTop(sideNode, path); if (isLink) { return(true); } } return(false); } #endregion }