Reputation: 511
I have a two dimensional array that stores all hexagons. It's an array of Hexagon
objects that is indexed with 2 integers.
I want to swap 3 hexagons with each other like i showed in the picture.
Can anyone help me with the algorithm that should do the job?
Thanks!
Here is the functions for creating hexagons.
public void CreateGrid(int gridWidth, int gridHeight)
{
for (int y = 0; y < gridHeight; y++)
{
for (int x = 0; x < gridWidth; x++)
{
GameObject Hexagon = Instantiate(HexagonPre,
Vector2.zero,
Quaternion.identity,
HexGrid);
Vector2 gridPos = new Vector2(x, y);
Hexagon.transform.position = CalcWorldPos(gridPos);
Hexagon.transform.name = "X: " + x + " | Y: " + y;
}
}
}
Vector2 CalcWorldPos(Vector2 gridPos)
{
float offset = 0;
if(gridPos.y %2 != 0)
offset = hexWidth / 2f;
float x = startPos.x + gridPos.x * hexWidth + offset;
float y = startPos.y - gridPos.y * hexHeight * 0.75f;
return new Vector2(x, y);
}
Okay I shared how the game looks like. I click somewhere in the game. The game finds 3 closest hexagons on where i click. Then I change the locations of those 3 hexagons. (I already did that). But somehow i need my array to know that those 3 hexagons swapped with each other. Be careful this would be any 3 hexagons. So we need an algorithm for this to work for any 3 hexagons to swap their place in the array.
Video showing what I already have: youtube.com/watch?v=fVvQd47OswQ&feature=youtu.be
Upvotes: 2
Views: 177
Reputation: 20269
If you already have the coordinates of the 3 hexagons, then you can determine which hexagon has the unique Y coordinate, and determine which of the other two is on the right and which is on the left:
Vector2Int hexagonACoord;
Vector2Int hexagonBCoord;
Vector2Int hexagonCCoord;
Vector2Int loneHexagonCoord;
Vector2Int leftHexagonCoord;
Vector2Int rightHexagonCoord;
if (hexagonACoord.y != hexagonBCoord.y && hexagonACoord.y != hexagonCCoord.y)
{
loneHexagonCoord = hexagonACoord;
leftHexagonCoord = hexagonBCoord;
rightHexagonCoord = hexagonCCoord;
}
else if (hexagonBCoord.y != hexagonCCoord.y && hexagonBCoord.y != hexagonACoord.y)
{
loneHexagonCoord = hexagonBCoord;
leftHexagonCoord = hexagonACoord;
rightHexagonCoord = hexagonCCoord;
}
else
{
loneHexagonCoord = hexagonCCoord;
leftHexagonCoord = hexagonACoord;
rightHexagonCoord = hexagonBCoord;
}
if (leftHexagonCoord.x > rightHexagonCoord.x)
{
Vector2Int tempCoord = leftHexagonCoord;
leftHexagonCoord = rightHexagonCoord;
rightHexagonCoord = tempCoord;
}
Then depending on if the lone hex is on top, we can determine which direction to rotate in order to rotation clockwise:
if (loneHexagonCoord.y > leftHexagonCoord.y)
{
Hexagon tempHex = hexagonsArray[loneHexagonCoord.x, loneHexagonCoord.y];
hexagonsArray[loneHexagonCoord.x, loneHexagonCoord.y] =
hexagonsArray[rightHexagonCoord.x, rightHexagonCoord.y];
hexagonsArray[rightHexagonCoord.x, rightHexagonCoord.y] =
hexagonsArray[leftHexagonCoord.x, leftHexagonCoord.y];
hexagonsArray[leftHexagonCoord.x, leftHexagonCoord.y] = tempHex;
}
else
{
Hexagon tempHex = hexagonsArray[loneHexagonCoord.x, loneHexagonCoord.y];
hexagonsArray[loneHexagonCoord.x, loneHexagonCoord.y] =
hexagonsArray[leftHexagonCoord.x, leftHexagonCoord.y];
hexagonsArray[leftHexagonCoord.x, leftHexagonCoord.y] =
hexagonsArray[rightHexagonCoord.x, rightHexagonCoord.y];
hexagonsArray[rightHexagonCoord.x, rightHexagonCoord.y] = tempHex;
}
Then, update their HexCoordinates
components on where they are:
hexagonsArray[loneHexagonCoord.x, loneHexagonCoord.y]
.GetComponent<HexCoordinates>().Coordinates = new Vector2Int(
loneHexagonCoord.x, loneHexagonCoord.y);
hexagonsArray[leftHexagonCoord.x, leftHexagonCoord.y]
.GetComponent<HexCoordinates>().Coordinates = new Vector2Int(
leftHexagonCoord.x, leftHexagonCoord.y);
hexagonsArray[rightHexagonCoord.x, rightHexagonCoord.y]
.GetComponent<HexCoordinates>().Coordinates = new Vector2Int(
rightHexagonCoord.x, rightHexagonCoord.y);
When I answered below, there was no indication that logic to select the 3 hexagons was already complete. I'm going to leave this up because it answers a very related question:
Well, we can divide the intersections of the hex grid into triangles, and pair them into parallelograms like so:
The Y coordinate of the parallelogram that a mouse position (in world space) is in is simply:
float pgYCoord = Mathf.Floor((startPos.y - mousePos.y) / (hexHeight * 0.75f));
The X coordinate of the parallelogram that a mouse position is in is more complicated:
float xOffsetAtMouseY = startPos.x + hexWidth / 2f * (startPos.y - mousePos.y) / (hexHeight * 0.75f)
float pgXCoord = Mathf.Floor((mousePos.x - xOffsetAtMouseY) / hexWidth);
And then determine if the mouse in the A or the B triangle of that parallelogram:
float vertDistFromTopEdge = Mathf.Repeat(startPos.y-mousePos.y, hexHeight * 0.75f );
float horizDistFromTopLeftCorner = mousePos.x - startPos.x - pgXCoord*hexWidth - pgYCoord * hexWidth / 2f;
bool isInATriangle =
vertDistFromTopEdge
< 1.5f * hexHeight
- horizDistFromTopLeftCorner * (hexHeight * 0.75) / (hexWidth / 2f);
Then depending on if we're in an A triangle or not, we can determine the coordinates of the hexagons in clockwise order:
Vector2Int hexagonCoordA;
Vector2Int hexagonCoordB;
Vector2Int hexagonCoordC;
if (isInATriangle)
{
hexagonCoordA = new Vector2Int(pgXCoord, pgYCoord);
hexagonCoordB = new Vector2Int(pgXCoord+1, pgYCoord);
hexagonCoordC = new Vector2Int(pgXCoord, pgYCoord+1);
}
else
{
hexagonCoordA = new Vector2Int(pgXCoord, pgYCoord+1);
hexagonCoordB = new Vector2Int(pgXCoord+1, pgYCoord);
hexagonCoordC = new Vector2Int(pgXCoord+1, pgYCoord+1);
}
// every 2 rows, the pg x coord grows 1 additional higher than the hex x coord
hexagonCoordA.x += Mathf.Floor(0.5f*hexagonCoordA.y);
hexagonCoordB.x += Mathf.Floor(0.5f*hexagonCoordB.y);
hexagonCoordC.x += Mathf.Floor(0.5f*hexagonCoordC.y)
If any of the hexagonCoord variables have invalid indices (more appropriate in a separate question), then the mouse is not currently over an intersection of 3 hexagons. Otherwise, you can then swap the 3 hexagons.
int arrayXSize = hexagonArray.GetLength(0);
int arrayYSize = hexagonArray.GetLength(1);
if ( hexagonCoordA.x >= 0 && hexagonCoordA.x < arrayXSize
&& hexagonCoordA.y >= 0 && hexagonCoordA.y < arrayYSize
&& hexagonCoordB.x >= 0 && hexagonCoordB.x < arrayXSize
&& hexagonCoordB.y >= 0 && hexagonCoordB.y < arrayYSize
&& hexagonCoordC.x >= 0 && hexagonCoordC.x < arrayXSize
&& hexagonCoordC.y >= 0 && hexagonCoordC.y < arrayYSize)
{
Hexagon tempHex = hexagonsArray[hexagonCoordA.x, hexagonCoordA.y];
hexagonsArray[hexagonCoordA.x, hexagonCoordA.y] =
hexagonsArray[hexagonCoordC.x, hexagonCoordC.y];
hexagonsArray[hexagonCoordC.x, hexagonCoordC.y] =
hexagonsArray[hexagonCoordB.x, hexagonCoordB.y];
hexagonsArray[hexagonCoordB.x, hexagonCoordB.y] = tempHex;
Vector3 temp = hexagonA.transform.position;
hexagonA.transform.position = hexagonB.transform.position;
hexagonB.transform.position = hexagonC.transform.position;
hexagonC.transform.position = temp;
}
Upvotes: 1
Reputation: 7724
This should do the job
void Rotate3Hexagons(GameObject hexagon1, GameObject hexagon2, GameObject hexagon3){
Vector3 firstPos = hexagon1.transform.position;
hexagon1.transform.position = hexagon2.transform.position;
hexagon2.transform.position = hexagon3.transform.position;
hexagon3.transform.position = firstPos;
}
In order to convert from world coordinates to grid coordinates, you need to set an inverse function for your CalcWorldPos
function.
Vector2 CalcGridPos(Vector2 worldPos)
{
float offset = 0;
//the first thing to do is to decide if offset is 0 or hexWidth/2
//I guess you can figure it out
Vector2 gridPos = new Vector2();
gridPos.x = (worldPos.x - startPos.x - offset) / hexWidth;
gridPos.y = (-worldPos.y + startPos.y) / hexHeight * 0.75f;
return gridPos;
}
Upvotes: 1
Reputation: 129
if you just want to swap the positions between them its easy:
Vector3 tmpPos = hexagon1.transform.position;
hexagon1.transform.position = hexagon2.transform.position;
hexagon2.transform.position = hexagon3.transform.position;
hexagon3.transform.position = tmpPos;
Upvotes: 0