/// <summary> /// Обновляет состояние игрового поля. /// </summary> public void Update(GameTime gameTime) { // Пытаемся изменить состояние игры ChangeState(); // Действие разрушителей List <Destroyer> destroyerListCopy = new List <Destroyer>(destroyerList); foreach (Destroyer destroyer in destroyerListCopy) { foreach (GameBoardObject gameBoardObject in objectList) { Rectangle boundingBox = gameBoardObject.GetScreenBoundingBox(); bool boundingBoxHit = boundingBox.Contains(GameBoardObject.WorldToScreen(destroyer.spriteWorldPos)); bool alreadyImploding = implodingObjects.Contains(gameBoardObject); if (boundingBoxHit && !alreadyImploding) { implodingObjects.Add(gameBoardObject); ScaleAnimation implodeAnimation = new ScaleAnimation( gameBoardObject, beginScale: 1.0, endScale: 0.0, delay: 0.0, blocking: true, finishedCallback: _ => objectList.Remove(gameBoardObject) ); activeAnimations.Add(implodeAnimation); score++; // Если это LineBonus if (gameBoardObject.GetType() == typeof(LineBonus)) { TriggerLineBonus((LineBonus)gameBoardObject); } // Если это BombBonus if (gameBoardObject.GetType() == typeof(BombBonus)) { TriggerBombBonus((BombBonus)gameBoardObject); } } } } // Обновляем состояние анимаций activeAnimations.ForEach(animation => animation.Update(gameTime)); // Удаляем завершившиеся анимации List <Animation> animationsToDelete = activeAnimations.FindAll(animation => !animation.active); animationsToDelete.ForEach(animation => animation.OnDelete()); activeAnimations = activeAnimations.Except(animationsToDelete).ToList(); // Синхронизируем список implodingObjects с основным списком implodingObjects = implodingObjects.Intersect(objectList).ToList(); // Уменьшаем остаток времени if (currentGamePhase != GamePhase.MainMenu && currentGamePhase != GamePhase.GameOver) { timeRemaining -= gameTime.ElapsedGameTime.TotalSeconds; } }
/// <summary> /// Создать бонус Bomb. /// </summary> /// <param name="baseObject">Базовый объект.</param> public void CreateBombBonus(GameBoardObject baseObject) { // Создаем объект BombBonus newBombBonus = new BombBonus(baseObject, baseObject.worldPos, baseObject.worldPos); objectList.Add(newBombBonus); // Запускаем анимацию появления ScaleAnimation spawnAnimation = new ScaleAnimation(newBombBonus, 0.0, 1.0, blocking: true); activeAnimations.Add(spawnAnimation); }
/// <summary> /// Активирует бонус Bomb. /// </summary> public void TriggerBombBonus(BombBonus bombBonus) { // Объекты вокруг бомбы for (int x = bombBonus.worldPos.x - 1; x <= bombBonus.worldPos.x + 1; x++) { for (int y = bombBonus.worldPos.y - 1; y <= bombBonus.worldPos.y + 1; y++) { if (x == bombBonus.worldPos.x && y == bombBonus.worldPos.y) { continue; } GameBoardObject obj = GetObjectAtPosition(x, y); if (obj is null) { continue; } implodingObjects.Add(obj); ScaleAnimation implodeAnimation = new ScaleAnimation( obj, beginScale: 1.0, endScale: 0.0, delay: 0.25, blocking: true, finishedCallback: _ => objectList.Remove(obj) ); activeAnimations.Add(implodeAnimation); score++; // Если это LineBonus if (obj.GetType() == typeof(LineBonus)) { TriggerLineBonus((LineBonus)obj); } // Если это BombBonus if (obj.GetType() == typeof(BombBonus)) { TriggerBombBonus((BombBonus)obj); } } } // Сама бомба implodingObjects.Add(bombBonus); ScaleAnimation bombImplodeAnimation = new ScaleAnimation( bombBonus, beginScale: 1.0, endScale: 0.0, delay: 0.0, blocking: true, finishedCallback: _ => objectList.Remove(bombBonus) ); activeAnimations.Add(bombImplodeAnimation); score++; }
/// <summary> /// Удаление комбинаций. /// </summary> public void DeleteCombos(ComboList comboList) { // Список удаляемых объектов List <GameBoardObject> objectsToDelete = comboList.SelectMany(tempList => tempList).ToList(); score += objectsToDelete.Count; // Срабатывание бонусов List <LineBonus> lineBonuses = objectsToDelete.FindAll(obj => obj.GetType() == typeof(LineBonus)).Cast <LineBonus>().ToList(); foreach (LineBonus lineBonus in lineBonuses) { TriggerLineBonus(lineBonus); currentGamePhase = GamePhase.Bonus; } List <BombBonus> bombBonuses = objectsToDelete.FindAll(obj => obj.GetType() == typeof(BombBonus)).Cast <BombBonus>().ToList(); foreach (BombBonus bombBonus in bombBonuses) { TriggerBombBonus(bombBonus); currentGamePhase = GamePhase.Bonus; } // Если бонусы активны, то новые создавать нельзя. if (currentGamePhase == GamePhase.Bonus) { return; } // Запуск анимации исчезновения implodingObjects.Clear(); foreach (GameBoardObject obj in objectsToDelete) { implodingObjects.Add(obj); ScaleAnimation implodeAnimation = new ScaleAnimation(obj, 1.0, 0.0, blocking: true, finishedCallback: _ => objectList.Remove(obj)); activeAnimations.Add(implodeAnimation); } // Бонус Bomb // Комбинации из 5 и более List <Vector2Int> newBombPositions = new List <Vector2Int>(); ComboList combinationsOf5AndMore = comboList.FindAll(combination => combination.Count >= 5); List <GameBoardObject> combination = combinationsOf5AndMore.Find(combination => combination.Contains(objectSwap2)); if (combination != null) { CreateBombBonus(objectSwap2); newBombPositions.Add(objectSwap2.worldPos); } // Перекрестные комбинации из 3 и более CrossList crosses = new CrossList(); ComboList verticalCombinations = comboList.FindAll(combination => combination[0].worldPos.x == combination[1].worldPos.x); ComboList horizontalCombinations = comboList.FindAll(combination => combination[0].worldPos.y == combination[1].worldPos.y); foreach (List <GameBoardObject> verticalCombination in verticalCombinations) { foreach (List <GameBoardObject> horizontalCombination in horizontalCombinations) { List <GameBoardObject> intersection = verticalCombination.Intersect(horizontalCombination).ToList(); if (intersection.Count > 0) { GameBoardObject objectAtIntersection = intersection[0]; if (!newBombPositions.Contains(objectAtIntersection.worldPos)) { CreateBombBonus(objectAtIntersection); newBombPositions.Add(objectAtIntersection.worldPos); } } } } // Бонус Line ComboList combinationsOf4 = comboList.FindAll(combination => combination.Count == 4); combination = combinationsOf4.Find(combination => combination.Contains(objectSwap2)); if (combination != null && !newBombPositions.Contains(objectSwap2.worldPos)) { Debug.WriteLine($"Creating line bonus in {objectSwap2.worldPos}"); bool vertical = combination[0].worldPos.x == combination[1].worldPos.x; // Создаем объект LineBonus newLineBonus = new LineBonus(objectSwap2, vertical, objectSwap2.worldPos, objectSwap2.worldPos); objectList.Add(newLineBonus); // Запускаем анимацию появления ScaleAnimation spawnAnimation = new ScaleAnimation(newLineBonus, 0.0, 1.0, blocking: true); activeAnimations.Add(spawnAnimation); } }