Check my pathfinding code

Godot Version

4.5

Question

Hi, I made some code for an enemy in a top down 2d game like the old Zelda games.

I haven’t actually implemented the actual pathfinding code yet. The code I have here is supposed to get the enemy to pick a tile to pathfind to.

How it’s supposed to work is that the enemy has a predetermined direction it wants to go in and then checks for traversable tiles within a certain radius and then picks one that’s in the direction that’s closest to the direction it wants to head in based on which one has the lowest difference between the angle between the angles of the two vectors.

I think I have the logic mostly figured out but the code is still a bit wonky and I would like help fixing it.

If you share code, please wrap it inside three backticks or replace the code in the next block:

extends CharacterBody2D

@onready var nav_tiles = $"../Tiles/NavTiles"
@onready var debug_tiles = $"../Tiles/DebugTiles"
@onready var bug = $"."

var surrounding_tile_positions = []
#var position = Vector2.ZERO
var direction = Vector2.ZERO
var next_destination = Vector2i.ZERO



# Main functions
func _ready() -> void:
	direction = Vector2(-1, 0)
	

func _physics_process(delta: float) -> void:
	var position = nav_tiles.local_to_map(bug.position)
	
	
	surrounding_tile_positions = get_surrounding_tile_positions(position, 2)
	#print(surrounding_tile_positions.size())
	if surrounding_tile_positions.size() > 0:
		next_destination = get_tile_in_direction(position, direction, surrounding_tile_positions)
		print(next_destination)



# Secondary functions
func get_surrounding_tile_positions(position: Vector2, vision_radius: int):
	var surrounding_tile_positions = []
	# Gets positions of surrounding navicable tiles
	for x in range(position.x - vision_radius, position.x + vision_radius + 1):
		for y in range(position.y - vision_radius, position.y + vision_radius + 1):
			var cell = Vector2(x, y)
			# Sorts out navicable tiles
			var tile_data = nav_tiles.get_cell_tile_data(cell)
			if tile_data == null:
				pass
			elif tile_data.get_custom_data("navicable"):
				surrounding_tile_positions.append(cell)
			else:
				pass
		#print(surrounding_tile_positions.size())
		
	return surrounding_tile_positions



func get_tile_in_direction(position: Vector2, direction: Vector2, surrounding_tile_positions: Array):
	# Gets angles to tiles
	var angles_to_tiles = []
	for i in surrounding_tile_positions:
		angles_to_tiles.append(position.angle_to(i))
	# Gets angle differences
	var angle_differences = []
	for i in angles_to_tiles:
		angle_differences.append(abs(direction.angle() - i))
	# Gets lowest angle difference
	var lowest_angle_difference = angles_to_tiles.min()
	# Gets corrasponding tiles
	var tiles_in_rough_direction = []
	for i in surrounding_tile_positions:
		if position.angle_to(i) == lowest_angle_difference:
			tiles_in_rough_direction.append(i)
	# Gets the furthest corrasponding tile
	if tiles_in_rough_direction.size() > 1:
		var distances_to_tiles = []
		for i in tiles_in_rough_direction:
			distances_to_tiles.append(position.distance_to(i))
		var furthest_tile = distances_to_tiles.max()
		for i in tiles_in_rough_direction:
			if position.distance_to(i) == furthest_tile:
				return Vector2i(i)
	else:
		return Vector2i(tiles_in_rough_direction[0])

Is there a reason you’re not using NavigationRegion2D and NavigationAgent2D and letting them do all the heavy lifting?

1 Like

This code is for a wandering behavior where the enemy will wander around a maze before spotting the player. I didn’t want the direction the enemy heads in to be completely random to minimize unnecessary backtracking.

Also I’m a beginner so ignorance is definitely a factor.

Some reading to get you started

2 Likes

Read the link @OleNic posted. Then maybe check out some videos on it. You can do the random wandering with it. Just randomly pick a spot and pathfind to it.

You’ll need to be more specific. What is the code doing vs. what you’re expecting it to do?

Quite right, quite right. I think there might be something wrong with the part of the code that measures the differences between the angles because the direction I set for the enemy is straight to the left but the tile the tile picking function spits out is not.

Plus the preset direction doesn’t change but the tile it selects does depending on which quadrant of the map its in.

The enemy is in a different quarter of the map in each photo.

position in get_tile_in_direction() is not in map space.

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