From 5f0af52710c03e486122820c9edd8bf004c43d4a Mon Sep 17 00:00:00 2001 From: Jesus Castro Date: Mon, 15 Dec 2025 04:55:05 +0800 Subject: [PATCH] Separate Bomb Logic --- Assets/Scripts/Services/BombService.cs | 32 +++++++---------- Assets/Scripts/Services/GameBoardService.cs | 39 ++++++--------------- Assets/Scripts/Services/MatchService.cs | 1 - 3 files changed, 24 insertions(+), 48 deletions(-) diff --git a/Assets/Scripts/Services/BombService.cs b/Assets/Scripts/Services/BombService.cs index 53b6b11..16c1ebf 100644 --- a/Assets/Scripts/Services/BombService.cs +++ b/Assets/Scripts/Services/BombService.cs @@ -16,13 +16,8 @@ namespace Services { if (matchPositions == null || matchPositions.Count == 0) return Array.Empty(); - - // Activation: any match cell that is a bomb OR cardinal-adjacent to a bomb. - // NOTE: The actual "is bomb?" check depends on the board, so we only return - // the positions to be checked/queued by caller if desired. - // To keep BombService isolated, we’ll let DetonateChainAsync validate bombs via getGemAt. - // Here we return: all matched positions + their cardinal neighbors. - HashSet candidates = new HashSet(matchPositions); + + HashSet candidates = new HashSet(); foreach (Vector2Int p in matchPositions) { @@ -65,13 +60,11 @@ namespace Services processed.Add(bombPos); - // Delay before neighbor blast int neighborDelayMs = Mathf.Max(0, Mathf.RoundToInt(bombDelaySeconds * 1000f)); if (neighborDelayMs > 0) await UniTask.Delay(neighborDelayMs); - // Blast neighbors first (cross) - foreach (Vector2Int n in CrossNeighbors(bombPos, radius)) + foreach (Vector2Int n in DiamondNeighbors(bombPos, radius)) { if (!inBounds(n)) continue; @@ -80,7 +73,6 @@ namespace Services if (g == null) continue; - // Chain: if another bomb is in blast area, queue it if (g.Type == GemType.Bomb) { if (!processed.Contains(n)) @@ -91,26 +83,28 @@ namespace Services await destroyAtAsync(n); } - // Delay before destroying the bomb itself int selfDelayMs = Mathf.Max(0, Mathf.RoundToInt(bombSelfDelaySeconds * 1000f)); if (selfDelayMs > 0) await UniTask.Delay(selfDelayMs); - // Destroy bomb last Gem stillBomb = getGemAt(bombPos); if (stillBomb is { Type: GemType.Bomb }) await destroyAtAsync(bombPos); } } - private static IEnumerable CrossNeighbors(Vector2Int center, int radius) + private static IEnumerable DiamondNeighbors(Vector2Int center, int radius) { - for (int i = 1; i <= radius; i++) + for (int x = -radius; x <= radius; x++) { - yield return center + Vector2Int.left * i; - yield return center + Vector2Int.right * i; - yield return center + Vector2Int.up * i; - yield return center + Vector2Int.down * i; + int maxY = radius - Mathf.Abs(x); + for (int y = -maxY; y <= maxY; y++) + { + if (x == 0 && y == 0) + continue; + + yield return new Vector2Int(center.x + x, center.y + y); + } } } } diff --git a/Assets/Scripts/Services/GameBoardService.cs b/Assets/Scripts/Services/GameBoardService.cs index 9bd503c..61f68cc 100644 --- a/Assets/Scripts/Services/GameBoardService.cs +++ b/Assets/Scripts/Services/GameBoardService.cs @@ -181,7 +181,6 @@ namespace Services { } private async UniTask DestroyMatchesAsync(List protectedPositions) { - // Collect match positions, excluding protected (bomb creation slots). List matchPositions = new List(this.matchService.CurrentMatches.Count); for (int i = 0; i < this.matchService.CurrentMatches.Count; i++) { var m = this.matchService.CurrentMatches[i]; @@ -194,13 +193,12 @@ namespace Services { matchPositions.Add(pos); } - // Bombs are handled by BombService so they can respect delays + chaining. foreach (Vector2Int pos in matchPositions.Distinct().ToList()) { - var g = GetGem(pos); - if (g == null) continue; - if (g.Type == GemType.Bomb) continue; + Gem gem = GetGem(pos); + if (gem == null) continue; + if (gem.Type == GemType.Bomb) continue; - this.scoreService.ScoreCheck(g.ScoreValue); + this.scoreService.ScoreCheck(gem.ScoreValue); DestroyMatchedGems(pos); } @@ -209,22 +207,17 @@ namespace Services { List initialBombs = new List(); foreach (Vector2Int p in bombCandidates) { if (!InBounds(p)) continue; - var g = GetGem(p); - if (g is { Type: GemType.Bomb }) + + if (protectedPositions != null && protectedPositions.Contains(p)) + continue; + + Gem gem = GetGem(p); + if (gem is { Type: GemType.Bomb }) initialBombs.Add(p); } initialBombs = initialBombs.Distinct().ToList(); - await this.bombService.DetonateChainAsync( - initialBombs, - InBounds, - GetGem, - DestroyAtAsync, - this.gameVariables.bombRadius, - this.gameVariables.bombDelay, - this.gameVariables.bombSelfDelay - ); - + await this.bombService.DetonateChainAsync(initialBombs, InBounds, GetGem, DestroyAtAsync, this.gameVariables.bombRadius, this.gameVariables.bombDelay, this.gameVariables.bombSelfDelay); await MoveGemsDown(); } @@ -238,16 +231,6 @@ namespace Services { return UniTask.CompletedTask; } - private static IEnumerable CrossNeighbors(Vector2Int center, int radius) { - // center excluded for "neighbors first" - for (int i = 1; i <= radius; i++) { - yield return center + Vector2Int.left * i; - yield return center + Vector2Int.right * i; - yield return center + Vector2Int.up * i; - yield return center + Vector2Int.down * i; - } - } - private async UniTask MoveGemsDown() { await UniTask.Delay(50); diff --git a/Assets/Scripts/Services/MatchService.cs b/Assets/Scripts/Services/MatchService.cs index d582661..d7b4e00 100644 --- a/Assets/Scripts/Services/MatchService.cs +++ b/Assets/Scripts/Services/MatchService.cs @@ -92,7 +92,6 @@ namespace Services { this.currentMatches = this.currentMatches.Distinct().ToList(); DetectBombSpawnFromLastSwap(); - CheckForBombs(); } private void DetectBombSpawnFromLastSwap() {