Adjust Bomb Behavior
This commit is contained in:
@@ -53,7 +53,7 @@ MonoBehaviour:
|
|||||||
scoreValue: 10
|
scoreValue: 10
|
||||||
width: 7
|
width: 7
|
||||||
height: 7
|
height: 7
|
||||||
bombDelay: 1
|
bombDelay: 2
|
||||||
bombSelfDelay: 1
|
bombSelfDelay: 1
|
||||||
bombRadius: 2
|
bombRadius: 2
|
||||||
dropHeight: 2
|
dropHeight: 2
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ namespace ScriptableObjects {
|
|||||||
[Header("Bomb")]
|
[Header("Bomb")]
|
||||||
[Tooltip("How long before the gems around the bomb explode")]
|
[Tooltip("How long before the gems around the bomb explode")]
|
||||||
public float bombDelay = 0.1f;
|
public float bombDelay = 0.1f;
|
||||||
[Tooltip("How long before the bomb itself explodes")]
|
|
||||||
public float bombSelfDelay = 0.05f;
|
|
||||||
[Tooltip("How far the explosion reaches")]
|
[Tooltip("How far the explosion reaches")]
|
||||||
public int bombRadius = 1;
|
public int bombRadius = 1;
|
||||||
|
|
||||||
|
|||||||
@@ -42,64 +42,95 @@ namespace Services
|
|||||||
Func<Vector2Int, Gem> getGemAt,
|
Func<Vector2Int, Gem> getGemAt,
|
||||||
Func<Vector2Int, UniTask> destroyAtAsync,
|
Func<Vector2Int, UniTask> destroyAtAsync,
|
||||||
int radius,
|
int radius,
|
||||||
float bombDelaySeconds,
|
float bombDelaySeconds)
|
||||||
float bombSelfDelaySeconds)
|
|
||||||
{
|
{
|
||||||
if (initialBombs == null || initialBombs.Count == 0)
|
if (initialBombs == null || initialBombs.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Queue<Vector2Int> queue = new Queue<Vector2Int>(initialBombs);
|
int waveDelayMs = Mathf.Max(0, Mathf.RoundToInt(bombDelaySeconds * 1000f));
|
||||||
HashSet<Vector2Int> processed = new HashSet<Vector2Int>();
|
|
||||||
|
|
||||||
while (queue.Count > 0)
|
HashSet<Vector2Int> processedBombs = new HashSet<Vector2Int>();
|
||||||
{
|
|
||||||
Vector2Int bombPos = queue.Dequeue();
|
|
||||||
if (processed.Contains(bombPos))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!inBounds(bombPos))
|
Queue<Vector2Int> waveQueue = new Queue<Vector2Int>(
|
||||||
continue;
|
initialBombs.Where(p =>
|
||||||
|
|
||||||
Gem bomb = getGemAt(bombPos);
|
|
||||||
if (bomb is not { Type: GemType.Bomb })
|
|
||||||
continue;
|
|
||||||
|
|
||||||
processed.Add(bombPos);
|
|
||||||
|
|
||||||
int ringDelayMs = Mathf.RoundToInt(bombDelaySeconds * 1000f);
|
|
||||||
|
|
||||||
for (int dist = 1; dist <= radius; dist++)
|
|
||||||
{
|
{
|
||||||
if (ringDelayMs > 0)
|
if (!inBounds(p)) return false;
|
||||||
await UniTask.Delay(ringDelayMs);
|
Gem g = getGemAt(p);
|
||||||
|
return g is { Type: GemType.Bomb };
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
foreach (Vector2Int n in DiamondRing(bombPos, dist))
|
while (waveQueue.Count > 0)
|
||||||
|
{
|
||||||
|
// current wave (per bomb)
|
||||||
|
List<Vector2Int> waveBombs = new List<Vector2Int>();
|
||||||
|
while (waveQueue.Count > 0)
|
||||||
|
{
|
||||||
|
Vector2Int b = waveQueue.Dequeue();
|
||||||
|
if (processedBombs.Contains(b))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!inBounds(b))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Gem g = getGemAt(b);
|
||||||
|
if (g is not { Type: GemType.Bomb })
|
||||||
|
continue;
|
||||||
|
|
||||||
|
processedBombs.Add(b);
|
||||||
|
waveBombs.Add(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waveBombs.Count == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// delay once per wave
|
||||||
|
if (waveDelayMs > 0)
|
||||||
|
await UniTask.Delay(waveDelayMs);
|
||||||
|
|
||||||
|
HashSet<Vector2Int> nextWaveBombs = new HashSet<Vector2Int>();
|
||||||
|
HashSet<Vector2Int> toDestroyNow = new HashSet<Vector2Int>();
|
||||||
|
|
||||||
|
for (int i = 0; i < waveBombs.Count; i++)
|
||||||
|
{
|
||||||
|
Vector2Int bombPos = waveBombs[i];
|
||||||
|
|
||||||
|
// destroy self when it detonates
|
||||||
|
toDestroyNow.Add(bombPos);
|
||||||
|
|
||||||
|
foreach (Vector2Int p in DiamondAreaInclusive(bombPos, radius))
|
||||||
{
|
{
|
||||||
if (!inBounds(n))
|
if (!inBounds(p))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Gem g = getGemAt(n);
|
if (p == bombPos)
|
||||||
if (g == null)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (g.Type == GemType.Bomb)
|
Gem cellGem = getGemAt(p);
|
||||||
|
if (cellGem == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (cellGem.Type == GemType.Bomb)
|
||||||
{
|
{
|
||||||
if (!processed.Contains(n))
|
// bombs in range are NOT destroyed now. triggered to explode in a later wave.
|
||||||
queue.Enqueue(n);
|
if (!processedBombs.Contains(p))
|
||||||
|
nextWaveBombs.Add(p);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
await destroyAtAsync(n);
|
// Non-bomb gem gets destroyed by this bomb
|
||||||
|
toDestroyNow.Add(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int selfDelayMs = Mathf.Max(0, Mathf.RoundToInt(bombSelfDelaySeconds * 1000f));
|
// Destroy everything for this wave (non-bombs in range + the detonating bombs themselves)
|
||||||
if (selfDelayMs > 0)
|
foreach (Vector2Int p in toDestroyNow)
|
||||||
await UniTask.Delay(selfDelayMs);
|
await destroyAtAsync(p);
|
||||||
|
|
||||||
Gem stillBomb = getGemAt(bombPos);
|
// Schedule the next wave (triggered bombs)
|
||||||
if (stillBomb is { Type: GemType.Bomb })
|
foreach (Vector2Int b in nextWaveBombs)
|
||||||
await destroyAtAsync(bombPos);
|
waveQueue.Enqueue(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,5 +150,16 @@ namespace Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<Vector2Int> DiamondAreaInclusive(Vector2Int center, int radius)
|
||||||
|
{
|
||||||
|
yield return center;
|
||||||
|
|
||||||
|
for (int dist = 1; dist <= radius; dist++)
|
||||||
|
{
|
||||||
|
foreach (Vector2Int pivot in DiamondRing(center, dist))
|
||||||
|
yield return pivot;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -217,8 +217,7 @@ namespace Services {
|
|||||||
GetGem,
|
GetGem,
|
||||||
DestroyAtAsync,
|
DestroyAtAsync,
|
||||||
this.gameVariables.bombRadius,
|
this.gameVariables.bombRadius,
|
||||||
this.gameVariables.bombDelay,
|
this.gameVariables.bombDelay);
|
||||||
this.gameVariables.bombSelfDelay);
|
|
||||||
|
|
||||||
await MoveGemsDown();
|
await MoveGemsDown();
|
||||||
return;
|
return;
|
||||||
@@ -239,8 +238,7 @@ namespace Services {
|
|||||||
GetGem,
|
GetGem,
|
||||||
DestroyAtAsync,
|
DestroyAtAsync,
|
||||||
this.gameVariables.bombRadius,
|
this.gameVariables.bombRadius,
|
||||||
this.gameVariables.bombDelay,
|
this.gameVariables.bombDelay);
|
||||||
this.gameVariables.bombSelfDelay);
|
|
||||||
|
|
||||||
await MoveGemsDown();
|
await MoveGemsDown();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ namespace Services.Interfaces
|
|||||||
Func<Vector2Int, Gem> getGemAt,
|
Func<Vector2Int, Gem> getGemAt,
|
||||||
Func<Vector2Int, UniTask> destroyAtAsync,
|
Func<Vector2Int, UniTask> destroyAtAsync,
|
||||||
int radius,
|
int radius,
|
||||||
float bombDelaySeconds,
|
float bombDelaySeconds);
|
||||||
float bombSelfDelaySeconds);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user