Tile Hopper is a game where you have to reach the other side of the playing field whilst avoiding the vision cones of the enemies.
This was a solo project where I learned how to make a grid based game, which was challenging, but also a lot of fun.
UnityC#4 weeksSolo project
Trailer video:
My contribution:
Map generation
Because I decided to make the map out of hexagons, it was quite a challenge to make it spawn in correctly, luckily I figured out how to do it, though some things
are kind of magic, like how the offset.z has to be multiplied by 0.85f, which I only figured out because I tried out a bunch of diffrent variables. But in the end I think it
turned out quite good.
// create a grid level
private void MakeLevel(Vector3 pos)
{
// adjust dirtsize value (dirt size is size of one hexagon) based on gap variable
dirtSize.x += dirtSize.x * gap;
dirtSize.z += dirtSize.z * gap;
// calculate offset
Vector3 offset = new Vector3(dirtSize.x, 0, dirtSize.z * 0.85f);
Vector3 startOffset;
// choose which tile is the winning tile
winningTilePos = new Vector2((int)Random.Range(1, gridSize.x), gridSize.y);
// loop through rows and collumns
for (int i = 0; i < gridSize.y; i++)
{
for (int j = 0; j < gridSize.x; j++)
{
// decide start offset for each row based on being odd or even
if (i % 2 != 0)
{
startOffset = Vector3.zero;
}
else
{
startOffset = new Vector3(dirtSize.x / 2, 0, dirtSize.z * 1.7f);
}
// instantiate new tile
Tile newTile = Instantiate(dirtPrefab, new Vector3(pos.x + startOffset.x + j * offset.x, pos.y, pos.z + startOffset.z + i * offset.z), Quaternion.identity).GetComponent<Tile>();
tiles.Add(newTile);
// set grid position of new tile
int y = i % 2 != 0 ? i : i + 2;
newTile.gridPos = new Vector2(j + 1, y);
// check if tilepos is that of the winning tile
if (newTile.gridPos == winningTilePos)
{
// set TileState of this tile to WinTile
newTile.tileState = TileState.WinTile;
// instantiate flag on winning tile
MeshRenderer mesh = flag.GetComponent<MeshRenderer>();
Vector3 flagOffset = new Vector3(0, mesh.bounds.size.y / 2, 0);
Instantiate(flag, newTile.transform.position + flagOffset, Quaternion.identity);
}
}
}
}
Enemy behaviour
The enemy behaviour had the same problem as the map did, the damn hexagons, I had to figure out a way to make it select a new tile to move towards, but it would then obviously need to
know what tiles were next to it, and because the map is made out of hexagons there were six of them.
private Vector2 ChooseRandomTilePos()
{
// Set chooseNewPos bool to false.
chooseNewPos = false;
// Get the grid size from the level creator.
Vector2 grdSize = lvlCreator.gridSize;
// Define possible neighbor tile positions relative to the current tile.
Vector2[] NeighbourTiles =
{
new Vector2(-1, 1),
new Vector2(0, 1),
new Vector2(-1, 0),
new Vector2(1, 0),
new Vector2(-1, -1),
new Vector2(0, -1)
};
// Check if the current row is even or odd.
bool isEvenRow = gridPos.y % 2 == 0;
// Loop until a valid tile position is found.
while (true)
{
// Choose a random neighboring tile.
int randomTile = Random.Range(0, NeighbourTiles.Length);
Vector2 neighbourPos = gridPos + NeighbourTiles[randomTile];
// Check if the neighboring position is within bounds.
if (neighbourPos.y != 0)
{
// Adjust x-coordinate for even rows if needed. (might be magic)
if (isEvenRow && (randomTile == 0 || randomTile == 1 || randomTile == 4 || randomTile == 5))
neighbourPos.x += 1;
// Check if the neighboring position is within the grid boundaries.
if (neighbourPos.x <= grdSize.x && neighbourPos.y <= grdSize.y && neighbourPos.x > 0)
{
// Get the tile object at the neighboring position.
Tile tile = gridObj.FindTileInGrid(neighbourPos).GetComponent<Tile>();
// Check if the tile is unoccupied and not a winning or selected tile.
if (tile.tileState != TileState.Occupied && tile.tileState != TileState.Selected && tile.tileState != TileState.WinTile)
{
// Set the tile state to selected and return its position.
Debug.Log(tile.tileState);
tile.tileState = TileState.Selected;
return tile.gridPos;
}
}
}
}
}