Centering Camera Based on Contents of Hexagonal TileMapLayer

Godot Version

4.3

Question

I am currently working on a game where I have a hexagonal TileMapLayer where the tile layout is “Stairs Right” and the tile offset axis is horizontal. I have a function named set_up_hex_board() which places some tiles as well as possibly placing some game pieces. The size of the board is determined by a board

func set_up_hex_board(add_checkers: bool = true):
	#the loop is set up to go from purple to blue to pink but in the atlas it goes pink purple blue
	var tile_color_indexes: Array[int] = [1,2,0]
	
	#Iterates through each of the three colors
	for i in range(3):
		#Uses the array defined earlier to get the column of the atlas that the color belongs to
		var tile_color_index: int = tile_color_indexes[i]
		
		#Iterate through columns
		for j in range(board_size):
			#Iterate through horizontal-ish diagonals
			for k in range(board_size):
				#Coords of the cell that we are on
				var coords := Vector2i(-1-(i%2)+j*2-k,-2+min(i,1)-j+k*2)
				#Index of the diagonal from top left to bottom right
				var diagonal_number := (3*k) + i
				#Total number of diagonals on the board
				var diagonal_count := 3*board_size
				
				#Function that adds a tile at coords, it figures out whether it should create a tile with special data indicating it is at the end of the board
				set_tile_as_king_or_regular(coords,diagonal_number,diagonal_count,tile_color_index)
				
				#Potentially create a game piece if they are being created
				if add_checkers:
					try_placing_checker(coords,diagonal_number,diagonal_count)

The function set_tile_as_king_or_regular just places a tile of the right color and places a visually identical variant of the tile if the diagonal is at the end of the board.

func set_tile_as_king_or_regular(coords: Vector2i, diagonal_number: int, diagonal_count: int, tile_color_index: int):
	#Place a tile at the coords, determining whether or not to use a varient based on if it is a king diagonal (A diagonal at the end of the board)
	if (diagonal_number == 0) or (diagonal_number == (diagonal_count) - 1):
		#Sets the cell with the appropriate tile
		#Uses a variant with is_king_diagonal as true so pieces can easily know it is a king diagonal
		set_cell(coords,0,Vector2i(tile_color_index,theme_id),1)
	else:
		#Sets the cell with the appropriate tile
		set_cell(coords,0,Vector2i(tile_color_index,theme_id),0)

The results look something like this:

I am wondering if there is a way to position the camera so that the contents of the tilemaplayer are centered.

If the tilemap were symmetric, I would think the camera would be centered when you place it as a child of the map, since it should be at (0,0) for that child’s local space.

Here is another thought: TilemapLayer has functions get_used_rect() which returns the rectangle used by the Tilemap, and map_to_local() which converts map integer coordinates to the map’s local (floating point) coordinate system. There is also to_global which converts local coordinates to global coordinates. IF the camera isn’t a child of the tilemap, you can use these to find the maps extents in global coordinates, and average those values to make the global position of the camera.

1 Like

I tried adding this to the end of the function:

	var used_rect: Rect2i = get_used_rect()
	var top_left: Vector2i = to_global(map_to_local(Vector2i(used_rect.position.x,used_rect.position.y)))
	var bottom_right: Vector2i = to_global(map_to_local(Vector2i(used_rect.position.x+used_rect.size.x,used_rect.position.y+used_rect.size.y)))
	
	camera.global_position = Vector2((top_left.x+bottom_right.x)/2.0,(top_left.y+bottom_right.y)/2.0)

That got me close but still a little bit off. For some reason adding Vector2(-45,-45) to the camera’s global position worked.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.