Collapse/Blast Puzzle Game
Level-based mobile blast game built in Unity. (Dream Games case study)
A software engineering case study for Dream Games: build a level-based mobile blast game where tapping a group of 2+ adjacent same-colored cubes clears them, spends one move, and can chain into bigger special-item explosions - all within a fixed move limit per level.

Finding groups with flood fill
Every tap needs to answer one question fast: what's connected to this cube? BoardManager answers it with a straightforward BFS flood fill over the grid, matching on block type:
private List<int> FloodFill(int startX, int startY, BlockType type, bool[] visited)
{
List<int> result = new();
Queue<Vector2Int> queue = new();
queue.Enqueue(new Vector2Int(startX, startY));
while (queue.Count > 0)
{
var c = queue.Dequeue();
if (!IsValid(c.x, c.y)) continue;
int index = GetIndex(c.x, c.y);
if (visited[index] || board[index].type != type) continue;
visited[index] = true;
result.Add(index);
queue.Enqueue(new Vector2Int(c.x + 1, c.y));
queue.Enqueue(new Vector2Int(c.x - 1, c.y));
queue.Enqueue(new Vector2Int(c.x, c.y + 1));
queue.Enqueue(new Vector2Int(c.x, c.y - 1));
}
return result;
}A second variant, FloodFillMatching, reuses the same BFS shape but matches against a predicate instead of one exact type - that's what gathers an entire connected cluster of different special items (say, a TNT touching two rockets) so a combo can be resolved as one unit instead of item-by-item.
Group size decides what a blast leaves behind: 4-5 cubes fly together into a rocket (random horizontal or vertical), 6 or more collapse into a TNT, anything smaller just clears.
private BlockType GetSpawnType(int groupSize)
{
if (groupSize >= 6) return BlockType.TNT;
if (groupSize >= 4)
return UnityEngine.Random.Range(0, 2) == 0 ? BlockType.RocketH : BlockType.RocketV;
return BlockType.Empty;
}
Obstacles with different rules, one interface
Vases, stones, and chalice boxes all implement the same ObstacleDefinition, but each overrides just enough to get different behavior for free - no special-casing scattered through the board logic. A vase takes 2 hit points and falls with gravity; a stone ignores adjacent blasts entirely and only takes damage from special-item explosions; a chalice box is a static 2x2 with an 11-point life bar - one hit to break its door, then ten more (one per chalice) to clear it:
public class ChaliceDefinition : ObstacleDefinition
{
public override BlockType Type => BlockType.Chalice;
public override int MaxLife => 11; // 1 door hit + 10 chalices
public override bool FallsWithGravity => false;
public override bool DamagedByAdjacentBlast => true;
public override GoalType? Goal => GoalType.Chalice;
public override int GoalContribution => 10;
}Combo classification follows the same "definition, not conditionals" approach - a connected cluster of specials gets classified by composition (only rockets → a +-shaped double rocket; 2+ TNTs → a 7x7 blast; one TNT plus rockets → a 3x3 array of exploding rockets) via a single ComboResolver.Classify call.

Levels as data, not code
All 10 levels are JSON files under Assets/Resources/Levels/ - grid size, move count, and a flat array of starting cell contents ("rand" for random cubes, "s"/"b"/"g" for obstacle codes) - so tuning difficulty never touches game logic. An editor-only Debug → Set Current Level window (backed by LevelProgressWindow.cs) reads and overwrites the persisted progress directly, letting anyone jump to any level - or straight to the "Finished!" state - without playing through the rest.
Result
A polished 10-level game with BFS-driven combo clusters, chained special-item explosions, three obstacle types sharing one extensible definition/view interface, and an editor debug menu for jumping between levels during testing.