In reference to the second choice of basing the groups off of the things next to them, I've done similar in path finding code, although the two may seem pretty dissimilar at first glance. It's a long answer, but it probably suites what you want nicely...
You may want the enemies to come from neighboring tiles. Picking neighboring tiles is probably something you've already precomputed if you do pathfinding, as it's computationally expensive to compute it whenever you need to build a new path.
The idea I have is to pick one random tile in which a Swarm is to begin, then use the neighboring tiles list or functionality you have to pick a neighboring tile. If it's uninhabited, then you can spawn the next one, and keep going until you have boatloads of bees, goblins, or Scientologists.
To do this, I can offer psuedocode. First, if you don't have neighboring tiles, sometime during initialization, you'd want something like this...
public class Tile
{
// Tile stuff like location...
private List<Tile> neighbors = new List<Tile>();
public List<Tile> getNeighbors()
{
return this.neighbors;
}
}
Now, in your level object, you'd want an initialization step that does basically the following, assuming Tile objects are stored in an array of width (width) and height (height), although I know you want to dynamically create the field, so you'd probably have 16 for both values, and create neighbors listings for each. You may also want to go back and connect the previous set of 16x16 to this one too..
public void createNeighbors()
{
int i = 0;
int loc = 0;
int bounds = 0;
for(i = 0; i < this.width * this.height; i++)
{
// Get the tile above...
// Note that in normal person math, bounds cancels, but in integer math,
// it actually gives you the start of a row of tiles...
loc = i - this.width;
bounds = (i / this.width) * this.width;
if(loc >= bounds)
this.tiles[i].neighbors.add(this.tiles[loc]);
// Get the right tile...
loc = i + 1;
bounds = (i + (this.width - (i mod this.width));
if(loc < bounds)
this.tiles[i].neighbors.add(this.tiles[loc]);
// Get the bottom tile...
loc = i + this.width;
bounds = this.width * this.height;
if(loc < bounds)
this.tiles[i].neighbors.add(this.tiles[loc]);
// Get the left tile...
loc = i - 1;
bounds = (i - (i mod this.width));
if(loc >= bounds)
this.tiles[i].neighbors.add(this.tiles[loc]);
}
}
The point to that bit of code is to precompute the neighbors so you can make an algorithm that searches the neighbors to spawn the next guy in a swarm. Let's say that you want to give a function the number of enemies, and a center tile, and it returns a list of tiles in which each enemy should spawn. That looks a lot like this...
public List<Tile> spawnGroupTiles(Tile start, int number)
{
List<Tile> group = new List<Tile>();
Tile current = start;
if(number <= 0)
return group;
for(int i = 0; i < number; i++)
{
if(this.isOccupied(current) == false && group.contains(current) == false)
group.add(current);
else
{
Tile next = getNext(current, group, index);
if(next == null)
return group;
group.add(next);
}
current = group.last();
}
return group;
}
protected Tile getNext(Tile current, List<Tile> group, int index)
{
List<Tile> neighbors = current.getNeighbors();
boolean isFound = false;
int i = 0;
while(i < neighbors.size() && isFound == false)
{
Tile next = neighbors.get(i);
if(this.isOccupied(next) == false)
isFound == true;
else
i++;
}
if(isFound)
return this.tiles[i];
index--;
if(index < 0)
return null;
return getNext(group.get(index), group, index);
}
This looks complicated, but basically, we're building a search out for unoccupied Tiles. If we can't find one next to current, then we go back one index in our list and try its neighbors, and so on, until we either find an unoccupied tile, or we've exhausted every connected searchable space. It's recursive, and a bit ugly, and I bet there is an error or two, but it should build a rough cluster of spawned enemies once all that is fixed.
For extra credit, it would be nice if it picked randomly from the neighbor list, so that the groups would not build first up, then left, then down, then right, however, I'll leave that one in your able hands.