Example #1
0
        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);
        }
Example #2
0
        // 合并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);
        }
Example #3
0
        // 在某个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);
        }
Example #4
0
        // 碰撞到泡泡回调
        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);
        }
Example #5
0
        // 碰到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);
        }
Example #6
0
        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();
            }
        }
Example #7
0
        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();
        }
Example #8
0
        // 消除泡泡,返回消除的个数
        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
        }