Lost on how to make enemy movement the same as player's

So, your check_occupied doesn’t actually do any calculations.

You need it to return the value of your point in the dict.

So, you need to return occupation[point] which will get you the value stored at that point. Though you may need to convert that point to a map coord.

With that, I also noticed you made var free and occupy as string. If you want those for clarity they need to be bool, free = false, occupy = true.

Currently you are storing string values in your dict, you want boolean values.

Hmmmm I tried to fix the map code but now I get error Invalid access to property or key '(16, 176)' on a base object of type 'Dictionary'. (Shown tile coord is id_path[0]). Here is the map code, I changed free and occupy to bool and modified check_occupied func:

extends TileMapLayer

var astar: AStarGrid2D
var tile_position: Vector2i
var occupation: Dictionary = {}
var free: bool = false
var occupy: bool = true

func _ready():
	astar = AStarGrid2D.new()
	astar.region = get_used_rect()
	astar.cell_size = Vector2(32, 32)
	astar.diagonal_mode = AStarGrid2D.DIAGONAL_MODE_NEVER
	astar.update()
	for x in get_used_rect().size.x:
		for y in get_used_rect().size.y:
			tile_position = Vector2i(
				x + get_used_rect().position.x,
				y + get_used_rect().position.y
			)
			var tile_data = get_cell_tile_data(tile_position)
			if tile_position == null or tile_data.get_custom_data("Walkable") == false:
				astar.set_point_solid(tile_position)
				occupation[tile_position] = occupy
			else:
				occupation[tile_position] = free
func find_path(start, end) -> Array:
	var id_path = astar.get_point_path(
		local_to_map(to_local(start)),
		local_to_map(to_local(end))
		)
	for i in id_path.size():
		id_path[i] = id_path[i] + Vector2(16, 16)
	return id_path

func set_occupied(free, occupy):
	occupation[free] = false
	occupation[occupy] = true

func check_occupied(point: Vector2i):
	if occupation[point] == false:
		return occupation[point]
	return false

So, your check_occupied will always return false how you have it set up. You only need 1 line of code for that func.

The reason you are getting that error is because how you are setting up the dict and how you are searching for it.

I told you you would need to convert your coords.

So, I think if I understand how you set up your AStar you used the tilemap rect. So, that should mean that the you set up the dict with your tile map coords.

func check_occupied(point) -> bool:
return occupation[local_to_map(to_local(point))]

If you set up your dict with your tilemap coords that should return the value you want.

In set_occupied(free,occupy) you’ll have to do same conversion because you are sending global coords, that or convert the coords to global while creating your dict.

So, I edited some things, I changed it so your dict keys are global coords so you don’t have to convert the Vector2’s you send each time, I placed some comments in your code, but I’ll also make them here. Honestly you didn’t need the var free and occupy just for creating your dictionary, so I personally deleted them.

You were creating keys/values for solid points in your AStarGrid, however it doesn’t seem like those points will ever be changed to not solid, so that was a bit redundant. You already won’t navigate to those points since they are solid, and won’t return a path coord.

The real issue I realized is that you having to add that 16 pixel offset to recalculate your path. That means that your global_position and the map tiles converted global_position won’t be the same.

Why do you need that offset? Be detailed and specific please, it may be possible to eliminate the offset.

extends TileMapLayer

var astar: AStarGrid2D
var tile_position: Vector2i
var occupation: Dictionary = {}
func _ready():
	astar = AStarGrid2D.new()
	astar.region = get_used_rect()
	astar.cell_size = Vector2(32, 32)
	astar.diagonal_mode = AStarGrid2D.DIAGONAL_MODE_NEVER
	astar.update()
	for x in get_used_rect().size.x:
		for y in get_used_rect().size.y:
			tile_position = Vector2i(
				x + get_used_rect().position.x,
				y + get_used_rect().position.y
			)
			var tile_data = get_cell_tile_data(tile_position)
			if tile_position == null or tile_data.get_custom_data("Walkable") == false:
				astar.set_point_solid(tile_position)
				#occupation[to_global(map_to_local(tile_position))] = true This is unnecessary unless these points can become not solid
			else:
				occupation[to_global(map_to_local(tile_position))] = false
func find_path(start, end) -> Array:
	var id_path = astar.get_point_path(
		local_to_map(to_local(start)),
		local_to_map(to_local(end))
		)
	#for i in id_path.size():
		#This here is now going to cause you issues with calculating, why do you need this offset?
		#id_path[i] = id_path[i] + Vector2(16, 16) 
	return id_path
func set_occupied(free: Vector2, occupy: Vector2):
	occupation[free] = false
	occupation[occupy] = true
func check_occupied(point: Vector2) -> bool:
	return occupation[point]

Okkkkk. Kind of works!!! Haven’t tried to fix yet but there are some issues.
Enemies don’t recalculate available paths to the player. In the photo they should suround the player but they don’t.

Another issue is when the enemy is close to the player, I can’t click on a lot of tile around the enemy

Oh also enemies ignore occupied player tile when player spawns in detection area.
I’m heading to sleep so gonna try and fix tomorow if i’m not busy with homework. Thanks a lot

So, one thing I did in my game to get better paths with that was set point weight to 10 when occupied then back to 1 when not occupied, and also when calculating path set find_partial to true. These two things helped me fix the issues you have.

They aren’t recalculating because the best path is through an occupied cell. Changing the weight of the tiles to 10 for occupy and 1 for free should work.

The reason the ignore on spawn is because you don’t have anywhere setting up your player spawn location as occupied.

Fixed everything with your help!!! Huge THANKS! At one point i wanted to quit even. Now gotta implement targeting and fighting wooo

1 Like

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