示例#1
0
        /// <summary>
        /// Заполнение пустых ячеек в массиве модели.
        /// </summary>
        /// <returns>Список новых камешков на обогащение спрайтами</returns>
        public GemList FillBlanks()
        {
            GemList newGems = new GemList();
            Random  rnd     = new Random();

            for (int row = 0; row < RowsNumber; row++)
            {
                for (int column = 0; column < ColumnsNumber; column++)
                {
                    if (GemArray[row, column] == null)
                    {
                        bool foundApropriateGemType = false;

                        // Создаем камешек, записываем его в массив, проверяем не создал ли он цепочку
                        // если создал - повторяем до те пор, пока не найдем камешек, который не создаст цепочку
                        while (!foundApropriateGemType)
                        {
                            GemType newGemType = (GemType)rnd.Next(Enum.GetNames(typeof(GemType)).Length);

                            GemArray[row, column] = new Gem(newGemType, row, column);

                            foundApropriateGemType = GetChainAt(row, column).Count < 3;
                        }

                        // Добавляем новый камешек в список камешков, которым позже добавят спрайты
                        newGems.Add(GemArray[row, column]);
                    }
                }
            }

            //______ДЛЯ ДЕБАГА______
            PrintOutGemArrayToConsole(false);

            return(newGems);
        }
示例#2
0
        /// <summary>
        /// Анимация счета за уничтожение цепочки
        /// </summary>
        /// <param name="chain">Уничтожаемая цепочка.</param>
        private void AnimateScore(GemList chain)
        {
            SKSpriteNode firstGem = chain.GetFirstGem().Sprite;
            SKSpriteNode lastGem  = chain.GetLastGem().Sprite;

            CGPoint centerPoint = new CGPoint(
                (firstGem.Position.X + lastGem.Position.X) / 2,
                (firstGem.Position.Y + lastGem.Position.Y) / 2 - 8);

            SKLabelNode scoreLabel = new SKLabelNode("GillSans-BoldItalic")
            {
                FontSize  = 16,
                Text      = chain.GetScore() + "",
                Position  = centerPoint,
                ZPosition = 300
            };

            gemLayer.AddChild(scoreLabel);

            SKAction moveAction = SKAction.MoveBy(0, 3, 0.7);

            //.Move(by: CGVector(dx: 0, dy: 3), duration: 0.7)
            moveAction.TimingMode = SKActionTimingMode.EaseOut;
            scoreLabel.RunAction(SKAction.Sequence(moveAction, SKAction.RemoveFromParent()));
        }
示例#3
0
        /// <summary>
        /// Прикрепление спрайтов к камешкам в списке
        /// </summary>
        /// <param name="gems">Список камешков на обогащение спрайтами</param>
        public void AttachSpritesTo(GemList gems)
        {
            // маркер появления на игровом поле разрушителя, для проигрывания
            // звука появления разрушителя
            bool hasDestroyers = false;
            bool hasBomb       = false;

            foreach (Gem gem in gems)
            {
                AttachSpriteTo(gem);

                hasDestroyers |= gem.IsALineDestroyer;
                hasBomb       |= gem.IsABomb;
            }

            // проигрывам звук появления разрушителя
            if (hasBomb)
            {
                RunAction(newBombSound);
            }
            else if (hasDestroyers)
            {
                RunAction(newDestroyerSound);
            }
        }
示例#4
0
        /// <summary>
        /// Проверяет цепочку на наличие бонусов и возвращает список бонусов
        /// </summary>
        /// <returns>Список бонусов из цепочки.</returns>
        public GemList GetAllBonuses()
        {
            GemList bonuses = new GemList();

            foreach (Gem gem in this)
            {
                if (gem.IsALineDestroyer || gem.IsABomb)
                {
                    bonuses.Add(gem);
                }
            }

            return(bonuses);
        }
示例#5
0
        /// <summary>
        /// Падение камешков на пустые места. Сканирует колонку на пустоту,
        /// найдя пустоту сканирует снова, на нличие камешка сверху. При наличии -
        /// "роняет" его на пустое место. Упавшие амешки заносятся в колонки,
        /// Колонки заносятся в список на обновление спрайтов
        /// </summary>
        /// <returns>Список колонок камешков, которые переместились,
        /// для обновления позиции спрайтов</returns>
        public List <GemList> DropGems()
        {
            List <GemList> columns = new List <GemList>();

            // пробегаем по столбцам
            for (int column = 0; column < ColumnsNumber; column++)
            {
                GemList columnOfFallenGems = new GemList();

                for (int row = 0; row < RowsNumber; row++)
                {
                    // Если текущая ячейка пустая - сканируем текущий столбец вверх
                    if (GemArray[row, column] == null)
                    {
                        bool foundNewGemAbove = false;

                        for (int aboveRow = row + 1; aboveRow < RowsNumber && !foundNewGemAbove; aboveRow++)
                        {
                            // находим непустую ячейку и переносим камешек оттуда в текущую ячейку
                            if (GemArray[aboveRow, column] != null)
                            {
                                GemArray[row, column] = GemArray[aboveRow, column];
                                // ячейку из которой спустили камешек зануляем
                                GemArray[aboveRow, column] = null;
                                // Обновляем координату ряда у камешка
                                GemArray[row, column].Row = row;

                                //запоминаем камешек для анимации спрайтов
                                columnOfFallenGems.Add(GemArray[row, column]);

                                foundNewGemAbove = true;
                            }
                        }
                    }
                }

                // столбец из перенесенных камешков запоминаем в списке таких столбцов
                // чтобы анимировать их спрайты
                if (columnOfFallenGems.Count > 0)
                {
                    columns.Add(columnOfFallenGems);
                }
            }

            //_______ДЛЯ ДЕБАГА______
            PrintOutGemArrayToConsole(false);

            return(columns);
        }
示例#6
0
        /// <summary>
        /// Сканирование на наличие цепочки
        /// </summary>
        /// <returns><c>true</c>, если цепочка найдена, <c>false</c> если не найдена.</returns>
        public GemList RetriveChain()
        {
            for (int row = 0; row < RowsNumber; row++)
            {
                for (int column = 0; column < ColumnsNumber; column++)
                {
                    GemList chain = GetChainAt(row, column);
                    if (chain != null && chain.Count >= 3)
                    {
                        return(chain);
                    }
                }
            }

            return(null);
        }
示例#7
0
        /// <summary>
        /// Обмена местами в массиве двух камешков.
        /// </summary>
        /// <param name="swap">Объект с камешками на обмен</param>
        public void Perform(Swap swap)
        {
            int columnA = swap.GemA.Column;
            int rowA    = swap.GemA.Row;
            int columnB = swap.GemB.Column;
            int rowB    = swap.GemB.Row;

            // Меняем камешки местами
            GemArray[rowA, columnA] = swap.GemB;
            swap.GemB.Column        = columnA;
            swap.GemB.Row           = rowA;

            GemArray[rowB, columnB] = swap.GemA;
            swap.GemA.Column        = columnB;
            swap.GemA.Row           = rowB;

            GemList chain = GetChainAt(rowB, columnB);

            // проверяем получившюся цепоку на длину. если цепочка больше трех на
            // месте премещенного камешка ставим бонус
            // записываем бонус в список на добавление спрайтов для сцены
            if (chain.Count == 4)
            {
                bool isHorizontal = chain.ToArray()[0].Row == chain.ToArray()[1].Row;
                BonusesToAddSpritesTo.Add(new Gem(true, isHorizontal, GemArray[rowB, columnB].GemType, rowB, columnB));
            }

            if (chain.Count >= 5)
            {
                BonusesToAddSpritesTo.Add(new Gem(true, GemArray[rowB, columnB].GemType, rowB, columnB));
            }

            chain = GetChainAt(rowA, columnA);

            if (chain.Count == 4)
            {
                bool isHorizontal = chain.ToArray()[0].Row == chain.ToArray()[1].Row;
                BonusesToAddSpritesTo.Add(new Gem(true, isHorizontal, GemArray[rowA, columnA].GemType, rowA, columnA));
            }

            if (chain.Count >= 5)
            {
                BonusesToAddSpritesTo.Add(new Gem(true, GemArray[rowA, columnA].GemType, rowA, columnA));
            }
        }
示例#8
0
        public List <GemList> RetriveAllChainsOnLevel()
        {
            List <GemList> chains = new List <GemList>();

            for (int row = 0; row < RowsNumber; row++)
            {
                for (int column = 0; column < ColumnsNumber; column++)
                {
                    GemList chain = GetChainAt(row, column);

                    if (chain != null && chain.Count >= 3 && !chains.Contains(chain))
                    {
                        chains.Add(chain);
                    }
                }
            }

            return(chains);
        }
示例#9
0
        /// <summary>
        /// Уничтожение цепей в массиве камешков:
        /// метод сканирует массив на цепочки до тех пор, пока они есть,
        /// найдя цепочку заносит ее в список удаляемых цепочек, после чего
        /// уничтожает соответствующие камешки в массиве. Так же проверяет цепочки
        /// в них бонусов, заполняет список с бонусами.
        /// </summary>
        /// <returns><c>true</c> если нашелся хотя бы один активируемый бонус</returns>
        public void DestroyChains()
        {
            GemList chain = RetriveChain();

            // Повторяем процесс пока находим цепочку на уровне
            while (chain != null)
            {
                GemList bonuses;
                bool    needToReiterrate = true;

                while (needToReiterrate)
                {
                    needToReiterrate = false;

                    bonuses = chain.GetAllBonuses();

                    foreach (Gem bonus in bonuses)
                    {
                        // Запоминаем разрушитель в списке разрушителей на анимацию
                        if (!BonusesToAnimate.Contains(bonus))
                        {
                            BonusesToAnimate.Add(bonus);
                        }

                        // Заносим в цепочку весь ряд илил столбец,
                        // в зависимости от напрваленности разрушителя
                        if (bonus.IsALineDestroyer)
                        {
                            if (bonus.IsHorizontal)
                            {
                                for (int column = 0; column < ColumnsNumber; column++)
                                {
                                    if (GemArray[bonus.Row, column] != null && !chain.Contains(GemArray[bonus.Row, column]))
                                    {
                                        chain.Add(GemArray[bonus.Row, column]);
                                    }
                                }
                            }
                            else
                            {
                                for (int row = 0; row < RowsNumber; row++)
                                {
                                    if (GemArray[row, bonus.Column] != null && !chain.Contains(GemArray[row, bonus.Column]))
                                    {
                                        chain.Add(GemArray[row, bonus.Column]);
                                    }
                                }
                            }
                        }

                        if (bonus.IsABomb)
                        {
                            int i;
                            int j;
                            if (bonus.Row == 0)
                            {
                                i = 0;
                            }
                            else
                            {
                                if (bonus.Row - Properties.BombBlastRadius < 0)
                                {
                                    i = 0;
                                }
                                else
                                {
                                    i = bonus.Row - Properties.BombBlastRadius;
                                }
                            }
                            if (bonus.Column == 0)
                            {
                                j = 0;
                            }
                            else
                            {
                                if (bonus.Column - Properties.BombBlastRadius < 0)
                                {
                                    j = 0;
                                }
                                else
                                {
                                    j = bonus.Column - Properties.BombBlastRadius;
                                }
                            }

                            for (int row = i; row <= bonus.Row + Properties.BombBlastRadius && row <= RowsNumber - 1; row++)
                            {
                                for (int column = j; column <= bonus.Column + Properties.BombBlastRadius && column <= ColumnsNumber - 1; column++)
                                {
                                    if (GemArray[row, column] != null && !chain.Contains(GemArray[row, column]))
                                    {
                                        chain.Add(GemArray[row, column]);
                                    }
                                }
                            }
                        }
                    }

                    needToReiterrate = bonuses.Count < chain.GetAllBonuses().Count;
                }

                // подсчитываем очки за цепочку, добавляем их к общему счету
                // int chainScore = (chain.Count - 2) * 10;
                Score += chain.GetScore();

                // заносим цепочку в список на анимацию
                DestroyedChains.Add(chain);

                // удаляем из массива камешки в соответствии с цепью
                chain.ForEach(gem => GemArray[gem.Row, gem.Column] = null);

                // Получаем новую цепочку
                chain = RetriveChain();
            }

            //______ДЛЯ ДЕБАГА______
            PrintOutGemArrayToConsole(false);
        }
示例#10
0
        /// <summary>
        /// Проверка нахождения камешка в цепочке одинаковых камешков
        /// В этом проекте приоритет отдается горизонтальным цепочкам.
        /// Иерархия появилась т.к. Т- и Х- образные цепочки не проверяются и не просчитываются.
        /// </summary>
        /// <returns>Цепочка камешков</returns>
        /// <param name="gemRow">Ряд</param>
        /// <param name="gemColumn">Колонка</param>
        private GemList GetChainAt(int gemRow, int gemColumn)
        {
            GemList possibleChain = new GemList();

            // Если камешка в данной позиции вообще нет - возвращаем пустой список
            if (GemArray[gemRow, gemColumn] == null)
            {
                return(possibleChain);
            }

            possibleChain.Add(GemArray[gemRow, gemColumn]);

            GemType gemTypeToCheck = GemArray[gemRow, gemColumn].GemType;

            // Флаг разпыва цепочки
            bool chainIsNotBroken = true;

            //Проверка влево
            for (int column = gemColumn - 1; column >= 0 && chainIsNotBroken; column--)
            {
                if (GemArray[gemRow, column] != null && gemTypeToCheck == GemArray[gemRow, column].GemType)
                {
                    possibleChain.Add(GemArray[gemRow, column]);
                }
                else
                {
                    chainIsNotBroken = false;
                }
            }

            chainIsNotBroken = true;

            // Проверка вправо
            for (int column = gemColumn + 1; column < ColumnsNumber && chainIsNotBroken; column++)
            {
                if (GemArray[gemRow, column] != null && gemTypeToCheck == GemArray[gemRow, column].GemType)
                {
                    possibleChain.Add(GemArray[gemRow, column]);
                }
                else
                {
                    chainIsNotBroken = false;
                }
            }

            // Если в цепочке три и более элементов - цепочка возвращается
            if (possibleChain.Count >= 3)
            {
                return(possibleChain);
            }

            // Сбрасываем цепочку, если не нашлось цепочки по горизонтали
            possibleChain.Clear();
            possibleChain.Add(GemArray[gemRow, gemColumn]);

            chainIsNotBroken = true;

            // Проверка вниз
            for (int row = gemRow - 1; row >= 0 && chainIsNotBroken; row--)
            {
                if (GemArray[row, gemColumn] != null && gemTypeToCheck == GemArray[row, gemColumn].GemType)
                {
                    possibleChain.Add(GemArray[row, gemColumn]);
                }
                else
                {
                    chainIsNotBroken = false;
                }
            }

            chainIsNotBroken = true;

            // Проверка вверх
            for (int row = gemRow + 1; row < RowsNumber && chainIsNotBroken; row++)
            {
                if (GemArray[row, gemColumn] != null && gemTypeToCheck == GemArray[row, gemColumn].GemType)
                {
                    possibleChain.Add(GemArray[row, gemColumn]);
                }
                else
                {
                    chainIsNotBroken = false;
                }
            }

            return(possibleChain);
        }