Reputation: 13
I am following couple of tutorials for random hex generation for a map. I am currently trying to randomly generate continents based on single hex on the map by getting other hexes surrounding that particular hex.
This is my code for putting all the neighboring hexes into an array:
public HexCell[] GetHexWithinRange (HexCell centerHex, int range)
{
List<HexCell> hexWithinRange = new List<HexCell>();
int x = centerHex.coordinates.X;
int y = centerHex.coordinates.Y;
int z = centerHex.coordinates.Z;
int sequence = 0;
for (int dy = -range; dy < range + 1; dy++)
{
for (int dz = -range; dz < range + 1; dz++)
{
for (int dx = -range; dx < range + 1; dx++)
{
HexCell neighborHex = GetCellFromCoord(x + (float)dx,
y + (float)dy, z + (float)dz);
if (neighborHex == null)
{ continue; }
else
{
neighborHex.sequenceCheck = sequence++;
hexWithinRange.Add(neighborHex);
}
}
}
}
return hexWithinRange.ToArray();
}
Perfectly hexagonal shaped continent
Although the code return a perfectly shaped continent, it is putting the other hexes diagonally from the outside ring into the center hex:
Sequence when the code is putting the neighboring hex into array
What I would really want it to do is to get the neighboring hex from within the continent and move outside from there until it reaches the intended radius such as this:
Sequence how I want the code to put the neighboring hex into array
I tried coming out with a formula to put the neighboring hexes in the array ring-by-ring. But I'd like to keep my radius from center hex to be a variable. How do I do that?
Upvotes: 0
Views: 217
Reputation: 13
I figured it out. Instead of using the range as the limit for the loop, I created an incremental range within the original range. To avoid the initial problem crops up again, I make it that the loop check for a duplicates cell in the list/array before adding the cell it is currently on.
for (int curRange = 1; curRange < range + 1; curRange++)
{
for (int dy = -curRange; dy < curRange + 1; dy++)
{
for (int dz = -curRange; dz < curRange + 1; dz++)
{
for (int dx = -curRange; dx < curRange + 1; dx++)
{
HexCell neighborHex = GetCellFromCoord(x + (float)dx, y + (float)dy, z + (float)dz);
if (neighborHex == null)
{
continue;
}
else if (x == neighborHex.coordinates.X &&
y == neighborHex.coordinates.Y &&
z == neighborHex.coordinates.Z)
{
continue;
}
else
{
if (hexWithinRange.Contains(neighborHex))
{
continue;
}
else
{
hexWithinRange.Add(neighborHex);
}
}
}
}
}
}
Upvotes: 0
Reputation: 1945
Notice that you want to walk each "axis" by the radius.
For example, if you start at [36,-57,21] with Radius == 1, you move 1 Hex along X, then 1 along Y, then 1 along z, then backward along X, Y and Z, and arrive back at [36, -57, 21].
When Radius == 2, its the same, only you march each axis 2 times. And so on.
So, I think something like this would work (if your Vector3 hex representation is correct and has addition defined)
var center = centerHex.coordinates;
var offset = new Vector3(0, 0, 0);
int radius = 0;
for(radius = 0; radius < 4 radius ++){
for(i = 0; i < radius; i++){
AddCell(center + offset);
offset.X++;
}
for(i = 0; i < radius; i++){
AddCell(center + offset);
offset.Y--;
}
for(i = 0; i < radius; i++){
AddCell(center + offset);
offset.Z--;
}
for(i = 0; i < radius; i++){
AddCell(center + offset);
offset.X--;
}
for(i = 0; i < radius; i++){
AddCell(center + offset);
offset.Y++;
}
for(i = 0; i < radius; i++){
AddCell(center + offset);
offset.Z++;
}
offset.Z++;
}
}
Upvotes: 1