I'm looking for a solution to group my games tiles by the type of tile they are. The tiles are stored in a 2d array and have the types empty and water, the tiles that are group will be stored in a Group class.
So if I have the 2d array:
0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 0, 0, 0, 0,
0, 1, 1, 0, 0, 0, 1, 1,
0, 1, 0, 0, 0, 0, 1, 1
where 0's are empty and 1's are water there would be two water groups.
I have spent all afternoon trying to figure it out, here is what i have at the moment.
public void GenerateGroups(){
//Debug.Log("Generate Groups");
m_Groups = new List<Group>();
List<Tile> groupingTiles = new List<Tile>();
int groupId = 1;
foreach(Tile t in m_Tiles){
t.IsGrouped = false;
}
for(int y = 0; y < Height; y++){
for (int x = 0; x < Width; x++) {
Tile tile = m_Tiles[x, y];
if(tile.Type == TileType.Water && !tile.IsGrouped){
// if(m_Tiles[x+1, y].IsGrouped || m_Tiles[x, y + 1].IsGrouped){
// if(m_Groups.Count > 0){
// foreach(Group g in m_Groups){
// if(g.m_Tiles.Contains(m_Tiles[x+1, y]) || g.m_Tiles.Contains(m_Tiles[x, y + 1])){
// g.m_Tiles.Add(tile);
// tile.IsGrouped = true;
// continue;
// }
// }
// }
// }else{
// groupingTiles.Add(tile);
// }
groupingTiles.Add(tile);
tile.IsGrouped = true;
Tile next = m_Tiles[x + 1, y];
int pos = x + 1;
while(next.Type == TileType.Water && !next.IsGrouped && pos < Width){
// Debug.Log("Going right!");
groupingTiles.Add(next);
pos++;
next.IsGrouped = true;
next = m_Tiles[pos, y];
}
next = m_Tiles[x, y + 1];
pos = y + 1;
while(next.Type == TileType.Water && !next.IsGrouped && pos < Height){
//Debug.Log("Going up!");
groupingTiles.Add(next);
pos++;
next.IsGrouped = true;
next = m_Tiles[x, pos];
}
}
if(groupingTiles.Count > 0){
//Debug.Log("Group Tiles: " + groupingTiles.Count);
m_Groups.Add(new Group("Group_" + groupId, groupingTiles));
groupId++;
groupingTiles = new List<Tile>();
}
}
}
Debug.Log(m_Groups.Count);
}
Any help would be appreciated thanks!
I would approach this by saving a reference of the group inside the tile. When encountering a water tile, check if either it's left or bottom neighbour is also a water tile. This could end in four cases:
I wrote a piece of code as a demonstration, but note that it is untested and simplified. I think the merging of two groups is kind of a hassle, since you have the update the reference of each of it's tile. Also, you have to sort out the groups with just one tile later (if needed). But it should point you in the right direction:
for(int y = 0; y < Height; y++)
{
for(int x = 0; x < Width; x++)
{
Tile currentTile = GetTile(x, y);
if(!currentTile.IsWater)
continue;
Tile leftTile = GetLeftNeighbour(currentTile);
Tile bottomTile = GetBottomNeighbour(currentTile);
if(!leftTile.IsWater && !bottomTile.IsWater)
{
//first case
Group newGroup = new Group();
newGroup.Tiles.Add(currentTile);
currentTile.Group = newGroup;
}
else if(leftTile.IsWater && !bottomTile.IsWater)
{
//second case A
leftTile.Group.Tiles.Add(currentTile);
currentTile.Group = leftTile.Group;
}
else if(!leftTile.IsWater && bottomTile.IsWater)
{
//second case B
bottomTile.Group.Tiles.Add(currentTile);
currentTile.Group = bottomTile.Group;
}
else
{
if(leftTile.Group == bottomTile.Group)
{
//third case
leftTile.Group.Tiles.Add(currentTile);
currentTile.Group = leftTile.Group;
}
else
{
//fourth case
leftTile.Group.Merge(bottomTile.Group);
leftTile.Group.Tiles.Add(currentTile);
currentTile.Group = leftTile.Group;
}
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.