diff --git a/addons/nezvers_library/nodes/Navigation/TileNavigationGetter.gd b/addons/nezvers_library/nodes/Navigation/TileNavigationGetter.gd index 3a892bdd..a9c48c7a 100644 --- a/addons/nezvers_library/nodes/Navigation/TileNavigationGetter.gd +++ b/addons/nezvers_library/nodes/Navigation/TileNavigationGetter.gd @@ -1,14 +1,20 @@ class_name TileNavigationGetter extends Line2D + @export var astargrid_resource:AstarGridResource ## How close to be to a point to look up next one @export var reached_distance:float = 6.0 -var last_path:PackedVector2Array +var navigation_path:PackedVector2Array +var tile_path:Array[Vector2i] var index:int = 0 var closest_point:Vector2 -var is_finished:bool +var finish_reached:bool : set = set_finish_reached +var point_reached:bool + +func set_finish_reached(value:bool)->void: + finish_reached = value func _ready()->void: top_level = true @@ -17,49 +23,62 @@ func _ready()->void: func get_target_path(from:Vector2, to:Vector2)->PackedVector2Array: var _from_tile:Vector2i = astargrid_resource.tilemap_layer.local_to_map(from) var _to_tile:Vector2i = astargrid_resource.tilemap_layer.local_to_map(to) - last_path = astargrid_resource.value.get_point_path(_from_tile, _to_tile) - index = 0 - first_point_choice(from) + navigation_path = astargrid_resource.value.get_point_path(_from_tile, _to_tile) + tile_path = astargrid_resource.value.get_id_path(_from_tile, _to_tile) + + if navigation_path.size() < 2: + index = 0 + else: + index = 1 + assert(index < navigation_path.size()) - is_finished = false + finish_reached = false if visible: - points = last_path - return last_path + points = navigation_path + return navigation_path ## TODO: Don't use top_level to be able use position ## func get_next_path_position(from:Vector2)->Vector2: - if last_path.is_empty(): + if navigation_path.is_empty(): return closest_point ## TODO: add corner avoidance steering - closest_point = last_path[index] + closest_point = navigation_path[index] var _closest_dist:float = (closest_point - from).length_squared() var _treshold:float = reached_distance * reached_distance - var i:int = index +1 - while i < last_path.size(): - var _current_point = last_path[i] - var _current_dist = (_current_point - from).length_squared() - if _closest_dist < _current_dist: - break - closest_point = _current_point - _closest_dist = _current_dist - index = i - i += 1 # <- don't forget, or else... + var i:int = index + #if i < navigation_path.size() - 1: + #i += 1 + #assert(i < navigation_path.size()) + #while i < navigation_path.size(): + #var _current_point = navigation_path[i] + #var _current_dist = (_current_point - from).length_squared() + #if _closest_dist < _current_dist: + #i -= 1 + #assert(i < navigation_path.size()) + #break + #closest_point = _current_point + #_closest_dist = _current_dist + #i += 1 # <- don't forget, or else... + #i = min(i , navigation_path.size() - 1) - if _closest_dist < _treshold && index < last_path.size() - 1: - index += 1 - closest_point = last_path[index] - else: - is_finished = true + if _closest_dist < _treshold && i < navigation_path.size() - 1: + i += 1 + assert(i < navigation_path.size()) + closest_point = navigation_path[i] + + if i != index: + point_reached = true + if index == navigation_path.size() - 1: + finish_reached = true + elif !finish_reached: + point_reached = false + index = i + assert(i < navigation_path.size()) return closest_point -## Solution to not go backwards for a first point -func first_point_choice(_position:Vector2)->void: - if last_path.size() < 2: - return - var _dot_product:float = (last_path[0] - _position).normalized().dot((last_path[1] - _position).normalized()) - if _dot_product > 0.0: - return - index = 1 + +func _draw()->void: + pass diff --git a/addons/top_down/scenes/obstacles/hole_obstacle.tscn b/addons/top_down/scenes/obstacles/hole_obstacle.tscn index 94de891d..255753e5 100644 --- a/addons/top_down/scenes/obstacles/hole_obstacle.tscn +++ b/addons/top_down/scenes/obstacles/hole_obstacle.tscn @@ -11,7 +11,7 @@ collision_mask = 6 script = ExtResource("1_soon6") [node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="AreaTransmitter2D"] -polygon = PackedVector2Array(0, -5, -12, 0, 0, 5, 12, 0) +polygon = PackedVector2Array(0, -5, -11, 0, 0, 5, 11, 0) [node name="HoleTransmitter" type="Node" parent="AreaTransmitter2D" node_paths=PackedStringArray("area_transmitter")] script = ExtResource("2_otvmq") diff --git a/addons/top_down/scripts/actor/bots/TargetDirection.gd b/addons/top_down/scripts/actor/bots/TargetDirection.gd index 16855dd4..25671518 100644 --- a/addons/top_down/scripts/actor/bots/TargetDirection.gd +++ b/addons/top_down/scripts/actor/bots/TargetDirection.gd @@ -7,18 +7,19 @@ extends Node @export var tile_navigation:TileNavigationGetter ## Value used to change recalculation cooldown @export var retarget_distance:float = 16.0 +@export var straight_path_distance:float = 16.0 * 5.0 @export var debug:bool ## From bot to target -var local_direction:Vector2 +var target_direction:Vector2 ## Track targets position var last_target_position:Vector2 ## Time last navigation update happened var last_update_time:float var navigation_cooldown:float = 1.0 - - +## Used to control navigation around corners +var allow_straight_path:bool = false func _ready()->void: target_finder.target_update.connect(on_target_update) @@ -30,13 +31,13 @@ func on_target_update()->void: if target_finder.target_count < 1: set_direction(Vector2.ZERO) return - local_direction = target_finder.closest.global_position - bot_input.global_position - var local_dir_len:float = local_direction.length_squared() - var attack_dist_squared:float = bot_input.attack_distance * bot_input.attack_distance + target_direction = target_finder.closest.global_position - bot_input.global_position + #var local_dir_len:float = target_direction.length_squared() + #var attack_dist_squared:float = bot_input.attack_distance * bot_input.attack_distance - if line_of_sight(): - set_direction(local_direction) + if test_line_of_sight(): + set_direction(target_direction) return navigation_update() @@ -45,10 +46,33 @@ func on_target_update()->void: set_direction(direction) ## Raycast checks if anything from environment is in the way -func line_of_sight()->bool: - raycast.target_position = local_direction +func test_line_of_sight()->bool: + raycast.target_position = target_direction raycast.force_raycast_update() - return !raycast.is_colliding() + + var _is_line_of_sight:bool = !raycast.is_colliding() + if !_is_line_of_sight: + allow_straight_path = false + + if tile_navigation.navigation_path.is_empty(): + return _is_line_of_sight + if tile_navigation.finish_reached: + return _is_line_of_sight + if !(tile_navigation.index < tile_navigation.navigation_path.size() - 1): + return _is_line_of_sight + + #if target_direction.length_squared() > (straight_path_distance * straight_path_distance): + #return allow_straight_path + + if _is_line_of_sight && !allow_straight_path && tile_navigation.point_reached: + # use tile Vector2i positions for dot product to have straight angles + var _target_tile_direction:Vector2 = (target_direction / tile_navigation.astargrid_resource.value.cell_size).round() + var _point_direction:Vector2 = tile_navigation.tile_path[tile_navigation.index + 1] - tile_navigation.tile_path[tile_navigation.index] + var _dot_product:float = _target_tile_direction.normalized().dot(_point_direction.normalized()) + if _dot_product > 0.5: + allow_straight_path = true + + return allow_straight_path func navigation_update()->void: var time: = Time.get_ticks_msec() * 0.001