Separate Bomb Logic
This commit is contained in:
@@ -16,13 +16,8 @@ namespace Services
|
|||||||
{
|
{
|
||||||
if (matchPositions == null || matchPositions.Count == 0)
|
if (matchPositions == null || matchPositions.Count == 0)
|
||||||
return Array.Empty<Vector2Int>();
|
return Array.Empty<Vector2Int>();
|
||||||
|
|
||||||
// Activation: any match cell that is a bomb OR cardinal-adjacent to a bomb.
|
HashSet<Vector2Int> candidates = new HashSet<Vector2Int>();
|
||||||
// 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<Vector2Int> candidates = new HashSet<Vector2Int>(matchPositions);
|
|
||||||
|
|
||||||
foreach (Vector2Int p in matchPositions)
|
foreach (Vector2Int p in matchPositions)
|
||||||
{
|
{
|
||||||
@@ -65,13 +60,11 @@ namespace Services
|
|||||||
|
|
||||||
processed.Add(bombPos);
|
processed.Add(bombPos);
|
||||||
|
|
||||||
// Delay before neighbor blast
|
|
||||||
int neighborDelayMs = Mathf.Max(0, Mathf.RoundToInt(bombDelaySeconds * 1000f));
|
int neighborDelayMs = Mathf.Max(0, Mathf.RoundToInt(bombDelaySeconds * 1000f));
|
||||||
if (neighborDelayMs > 0)
|
if (neighborDelayMs > 0)
|
||||||
await UniTask.Delay(neighborDelayMs);
|
await UniTask.Delay(neighborDelayMs);
|
||||||
|
|
||||||
// Blast neighbors first (cross)
|
foreach (Vector2Int n in DiamondNeighbors(bombPos, radius))
|
||||||
foreach (Vector2Int n in CrossNeighbors(bombPos, radius))
|
|
||||||
{
|
{
|
||||||
if (!inBounds(n))
|
if (!inBounds(n))
|
||||||
continue;
|
continue;
|
||||||
@@ -80,7 +73,6 @@ namespace Services
|
|||||||
if (g == null)
|
if (g == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Chain: if another bomb is in blast area, queue it
|
|
||||||
if (g.Type == GemType.Bomb)
|
if (g.Type == GemType.Bomb)
|
||||||
{
|
{
|
||||||
if (!processed.Contains(n))
|
if (!processed.Contains(n))
|
||||||
@@ -91,26 +83,28 @@ namespace Services
|
|||||||
await destroyAtAsync(n);
|
await destroyAtAsync(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delay before destroying the bomb itself
|
|
||||||
int selfDelayMs = Mathf.Max(0, Mathf.RoundToInt(bombSelfDelaySeconds * 1000f));
|
int selfDelayMs = Mathf.Max(0, Mathf.RoundToInt(bombSelfDelaySeconds * 1000f));
|
||||||
if (selfDelayMs > 0)
|
if (selfDelayMs > 0)
|
||||||
await UniTask.Delay(selfDelayMs);
|
await UniTask.Delay(selfDelayMs);
|
||||||
|
|
||||||
// Destroy bomb last
|
|
||||||
Gem stillBomb = getGemAt(bombPos);
|
Gem stillBomb = getGemAt(bombPos);
|
||||||
if (stillBomb is { Type: GemType.Bomb })
|
if (stillBomb is { Type: GemType.Bomb })
|
||||||
await destroyAtAsync(bombPos);
|
await destroyAtAsync(bombPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<Vector2Int> CrossNeighbors(Vector2Int center, int radius)
|
private static IEnumerable<Vector2Int> 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;
|
int maxY = radius - Mathf.Abs(x);
|
||||||
yield return center + Vector2Int.right * i;
|
for (int y = -maxY; y <= maxY; y++)
|
||||||
yield return center + Vector2Int.up * i;
|
{
|
||||||
yield return center + Vector2Int.down * i;
|
if (x == 0 && y == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
yield return new Vector2Int(center.x + x, center.y + y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,7 +181,6 @@ namespace Services {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async UniTask DestroyMatchesAsync(List<Vector2Int> protectedPositions) {
|
private async UniTask DestroyMatchesAsync(List<Vector2Int> protectedPositions) {
|
||||||
// Collect match positions, excluding protected (bomb creation slots).
|
|
||||||
List<Vector2Int> matchPositions = new List<Vector2Int>(this.matchService.CurrentMatches.Count);
|
List<Vector2Int> matchPositions = new List<Vector2Int>(this.matchService.CurrentMatches.Count);
|
||||||
for (int i = 0; i < this.matchService.CurrentMatches.Count; i++) {
|
for (int i = 0; i < this.matchService.CurrentMatches.Count; i++) {
|
||||||
var m = this.matchService.CurrentMatches[i];
|
var m = this.matchService.CurrentMatches[i];
|
||||||
@@ -194,13 +193,12 @@ namespace Services {
|
|||||||
matchPositions.Add(pos);
|
matchPositions.Add(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bombs are handled by BombService so they can respect delays + chaining.
|
|
||||||
foreach (Vector2Int pos in matchPositions.Distinct().ToList()) {
|
foreach (Vector2Int pos in matchPositions.Distinct().ToList()) {
|
||||||
var g = GetGem(pos);
|
Gem gem = GetGem(pos);
|
||||||
if (g == null) continue;
|
if (gem == null) continue;
|
||||||
if (g.Type == GemType.Bomb) continue;
|
if (gem.Type == GemType.Bomb) continue;
|
||||||
|
|
||||||
this.scoreService.ScoreCheck(g.ScoreValue);
|
this.scoreService.ScoreCheck(gem.ScoreValue);
|
||||||
DestroyMatchedGems(pos);
|
DestroyMatchedGems(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,22 +207,17 @@ namespace Services {
|
|||||||
List<Vector2Int> initialBombs = new List<Vector2Int>();
|
List<Vector2Int> initialBombs = new List<Vector2Int>();
|
||||||
foreach (Vector2Int p in bombCandidates) {
|
foreach (Vector2Int p in bombCandidates) {
|
||||||
if (!InBounds(p)) continue;
|
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.Add(p);
|
||||||
}
|
}
|
||||||
initialBombs = initialBombs.Distinct().ToList();
|
initialBombs = initialBombs.Distinct().ToList();
|
||||||
|
|
||||||
await this.bombService.DetonateChainAsync(
|
await this.bombService.DetonateChainAsync(initialBombs, InBounds, GetGem, DestroyAtAsync, this.gameVariables.bombRadius, this.gameVariables.bombDelay, this.gameVariables.bombSelfDelay);
|
||||||
initialBombs,
|
|
||||||
InBounds,
|
|
||||||
GetGem,
|
|
||||||
DestroyAtAsync,
|
|
||||||
this.gameVariables.bombRadius,
|
|
||||||
this.gameVariables.bombDelay,
|
|
||||||
this.gameVariables.bombSelfDelay
|
|
||||||
);
|
|
||||||
|
|
||||||
await MoveGemsDown();
|
await MoveGemsDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,16 +231,6 @@ namespace Services {
|
|||||||
return UniTask.CompletedTask;
|
return UniTask.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<Vector2Int> 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() {
|
private async UniTask MoveGemsDown() {
|
||||||
await UniTask.Delay(50);
|
await UniTask.Delay(50);
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,6 @@ namespace Services {
|
|||||||
this.currentMatches = this.currentMatches.Distinct().ToList();
|
this.currentMatches = this.currentMatches.Distinct().ToList();
|
||||||
|
|
||||||
DetectBombSpawnFromLastSwap();
|
DetectBombSpawnFromLastSwap();
|
||||||
CheckForBombs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DetectBombSpawnFromLastSwap() {
|
private void DetectBombSpawnFromLastSwap() {
|
||||||
|
|||||||
Reference in New Issue
Block a user