From 193e3ed300d040b2e1c0fb760706025bd759b72f Mon Sep 17 00:00:00 2001 From: mcerutti Date: Wed, 10 Jul 2024 00:24:12 +0200 Subject: [PATCH] Add Navigation AStar Hexagonal demo --- 2d/navigation_astar_hexagonal/README.md | 15 ++ 2d/navigation_astar_hexagonal/astar_hex_2d.gd | 26 ++++ .../debug/debug_astar.gd | 133 ++++++++++++++++++ 2d/navigation_astar_hexagonal/icon.svg | 121 ++++++++++++++++ 2d/navigation_astar_hexagonal/icon.svg.import | 37 +++++ 2d/navigation_astar_hexagonal/icon.webp | Bin 0 -> 5894 bytes .../icon.webp.import | 34 +++++ 2d/navigation_astar_hexagonal/map.gd | 76 ++++++++++ 2d/navigation_astar_hexagonal/map.tscn | 81 +++++++++++ 2d/navigation_astar_hexagonal/player.gd | 27 ++++ 2d/navigation_astar_hexagonal/player.png | Bin 0 -> 5016 bytes .../player.png.import | 34 +++++ 2d/navigation_astar_hexagonal/player.tscn | 23 +++ 2d/navigation_astar_hexagonal/project.godot | 37 +++++ .../screenshots/.gdignore | 0 .../screenshots/Hexagon_Navigation_2D.png | Bin 0 -> 46117 bytes .../tiles/hexagonal_tiles_albedo.png | Bin 0 -> 11254 bytes .../tiles/hexagonal_tiles_albedo.png.import | 34 +++++ .../tiles/tile_set.tres | 93 ++++++++++++ 19 files changed, 771 insertions(+) create mode 100644 2d/navigation_astar_hexagonal/README.md create mode 100644 2d/navigation_astar_hexagonal/astar_hex_2d.gd create mode 100644 2d/navigation_astar_hexagonal/debug/debug_astar.gd create mode 100644 2d/navigation_astar_hexagonal/icon.svg create mode 100644 2d/navigation_astar_hexagonal/icon.svg.import create mode 100644 2d/navigation_astar_hexagonal/icon.webp create mode 100644 2d/navigation_astar_hexagonal/icon.webp.import create mode 100644 2d/navigation_astar_hexagonal/map.gd create mode 100644 2d/navigation_astar_hexagonal/map.tscn create mode 100644 2d/navigation_astar_hexagonal/player.gd create mode 100644 2d/navigation_astar_hexagonal/player.png create mode 100644 2d/navigation_astar_hexagonal/player.png.import create mode 100644 2d/navigation_astar_hexagonal/player.tscn create mode 100644 2d/navigation_astar_hexagonal/project.godot create mode 100644 2d/navigation_astar_hexagonal/screenshots/.gdignore create mode 100644 2d/navigation_astar_hexagonal/screenshots/Hexagon_Navigation_2D.png create mode 100644 2d/navigation_astar_hexagonal/tiles/hexagonal_tiles_albedo.png create mode 100644 2d/navigation_astar_hexagonal/tiles/hexagonal_tiles_albedo.png.import create mode 100644 2d/navigation_astar_hexagonal/tiles/tile_set.tres diff --git a/2d/navigation_astar_hexagonal/README.md b/2d/navigation_astar_hexagonal/README.md new file mode 100644 index 00000000000..30531e749f5 --- /dev/null +++ b/2d/navigation_astar_hexagonal/README.md @@ -0,0 +1,15 @@ +# Tile-based navigation on hexagonal Tilemap (2D) + +Example of using 2D navigation (tile based) on a hexagonal map, using : +- [`TileMap`](https://docs.godotengine.org/en/stable/classes/class_tilemap.html) +- [`AStar2D`](https://docs.godotengine.org/en/stable/classes/class_astar2d.html) + +Language: GDScript + +Renderer: Compatibility + +Use mouse left click to interact. + +## Screenshots + +![Screenshot](screenshots/Hexagon_Navigation_2D.png) diff --git a/2d/navigation_astar_hexagonal/astar_hex_2d.gd b/2d/navigation_astar_hexagonal/astar_hex_2d.gd new file mode 100644 index 00000000000..69a6b4359d6 --- /dev/null +++ b/2d/navigation_astar_hexagonal/astar_hex_2d.gd @@ -0,0 +1,26 @@ +class_name AStarHex2D +extends AStar2D + +var map: TileMap + +# Final cost used for pathfinding would be weight * cost +# See https://docs.godotengine.org/fr/4.x/classes/class_astar3d.html#class-astar3d +func _compute_cost( from_id:int, to_id:int ): + return 1 + +func _estimate_cost( from_id:int, to_id:int ): + return 1 + +# Euclidian distance heuristic would not work on hexagonal map with global position because +# we are not using regular hexagon +# https://github.com/godotengine/godot/issues/92338 + +#func _compute_cost( from_id:int, to_id:int ): + #var position_from = get_point_position(from_id) + #var position_to = get_point_position(to_id) + #return (position_to - position_from).length_squared() + +#func _estimate_cost( from_id:int, to_id:int ): + #var position_from = get_point_position(from_id) + #var position_to = get_point_position(to_id) + #return (position_to - position_from).length_squared() diff --git a/2d/navigation_astar_hexagonal/debug/debug_astar.gd b/2d/navigation_astar_hexagonal/debug/debug_astar.gd new file mode 100644 index 00000000000..a6af0bdc0b3 --- /dev/null +++ b/2d/navigation_astar_hexagonal/debug/debug_astar.gd @@ -0,0 +1,133 @@ +extends Node2D + +@export var map: Map + +@onready var font:Font = ThemeDB.fallback_font + +const BASE_LINE_WIDTH = 3.0 +const DRAW_COLOR:Color = Color.WHITE +const OFFSET_POSITIONS = Vector2(10,30) +const OFFSET_WEIGHT = Vector2(10,-10) + +var _debug_connections = false +var _debug_position = false +var _debug_weights = false +var _debug_costs = false +var _debug_path = true + + +func _process(delta): + queue_redraw() + pass + + +func draw_arrow(src, dst, color, width, aa = true): + var angle = 0.6 + var size_head = 20 + var head : Vector2 = (dst - src).normalized() * size_head + draw_line(src, dst-head/2, color, width, aa) + draw_polygon([dst, dst - head.rotated(angle), dst - head.rotated(-angle) ], [color,color,color ]) + + +func _draw(): + if _debug_connections : + _draw_connections() + if _debug_position : + _draw_positions() + if _debug_weights : + _draw_weights() + if _debug_costs : + _draw_costs() + if _debug_path : + _draw_path() + + +func _draw_path(): + if not map._point_path: + return + var point_start: Vector2i = map._point_path[0] + var point_end: Vector2i = map._point_path[len(map._point_path) - 1] + + var last_point = point_start + for index in range(1, len(map._point_path)): + var current_point = map._point_path[index] + draw_line(last_point, current_point, DRAW_COLOR, BASE_LINE_WIDTH, true) + draw_circle(current_point, BASE_LINE_WIDTH * 2.0, DRAW_COLOR) + last_point = current_point + + +func _draw_weights(): + for id in map.astar_node.get_point_ids(): + var position_weight = map.astar_node.get_point_position(id) + var cost = map.astar_node.get_point_weight_scale(id) + draw_string( + font, + position_weight + OFFSET_WEIGHT, + str(cost), + HORIZONTAL_ALIGNMENT_FILL, + -1, + 16, + Color.RED + ) + + +func _draw_positions(): + for id in map.astar_node.get_point_ids(): + var position_label = map.astar_node.get_point_position(id) + var position_map = map.local_to_map(map.to_local(map.astar_node.get_point_position(id))) + draw_string( + font, + position_label + OFFSET_POSITIONS, + str(position_map), + HORIZONTAL_ALIGNMENT_FILL, + -1, + 16, + Color.RED + ) + + +func _draw_connections(): + for id in map.astar_node.get_point_ids(): + for id_con in map.astar_node.get_point_connections(id): + var position_start = map.astar_node.get_point_position(id) + var position_end = map.astar_node.get_point_position(id_con) + var direction = (position_end - position_start) + draw_arrow(position_start, position_end - direction/4.0, Color(0.0, 1.0, 1.0, 1.0), BASE_LINE_WIDTH*2, true) + + +func _draw_costs(): + for id in map.astar_node.get_point_ids(): + for id_con in map.astar_node.get_point_connections(id): + var position_cost_start = map.astar_node.get_point_position(id) + var position_cost_end = map.astar_node.get_point_position(id_con) + var cost = map.astar_node._compute_cost(id, id_con) + draw_string( + font, + (position_cost_start+position_cost_end)/2.0, + str("%.2f"%cost), + HORIZONTAL_ALIGNMENT_CENTER, + -1, + 16, + Color.PINK + ) + + +func _on_d_path_toggled(toggled_on): + _debug_path = toggled_on + + +func _on_d_costs_toggled(toggled_on): + _debug_costs = toggled_on + + +func _on_d_positions_toggled(toggled_on): + _debug_position = toggled_on + + +func _on_d_connections_toggled(toggled_on): + _debug_connections = toggled_on + + +func _on_d_weights_toggled(toggled_on): + _debug_weights = toggled_on + diff --git a/2d/navigation_astar_hexagonal/icon.svg b/2d/navigation_astar_hexagonal/icon.svg new file mode 100644 index 00000000000..503523078b6 --- /dev/null +++ b/2d/navigation_astar_hexagonal/icon.svg @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + 2D + diff --git a/2d/navigation_astar_hexagonal/icon.svg.import b/2d/navigation_astar_hexagonal/icon.svg.import new file mode 100644 index 00000000000..f789e6d656c --- /dev/null +++ b/2d/navigation_astar_hexagonal/icon.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://brh8t0d5w2mkc" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/2d/navigation_astar_hexagonal/icon.webp b/2d/navigation_astar_hexagonal/icon.webp new file mode 100644 index 0000000000000000000000000000000000000000..c36f9d6b18793222f0d335a93dbef8b560819d45 GIT binary patch literal 5894 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 LdW$vJCj$H*Y5Q&n literal 0 HcmV?d00001 diff --git a/2d/navigation_astar_hexagonal/icon.webp.import b/2d/navigation_astar_hexagonal/icon.webp.import new file mode 100644 index 00000000000..1a5d65535ce --- /dev/null +++ b/2d/navigation_astar_hexagonal/icon.webp.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bnujvgksdtkex" +path="res://.godot/imported/icon.webp-e94f9a68b0f625a567a797079e4d325f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.webp" +dest_files=["res://.godot/imported/icon.webp-e94f9a68b0f625a567a797079e4d325f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/2d/navigation_astar_hexagonal/map.gd b/2d/navigation_astar_hexagonal/map.gd new file mode 100644 index 00000000000..683472bf6da --- /dev/null +++ b/2d/navigation_astar_hexagonal/map.gd @@ -0,0 +1,76 @@ +class_name Map +extends TileMap + +# In order to have cost function control +@onready var astar_node = AStarHex2D.new() + +# Private variable to not trigger on same previous paths request +var _path_start_coords: Vector2i = Vector2i() +var _path_end_coords: Vector2i = Vector2i() +# Used for debug +var _point_path = [] + + +func _ready(): + astar_node.map = self + var walkable_cells_list = astar_add_walkable_cells() + astar_connect_walkable_cells(walkable_cells_list) + +# Need to create first astar nodes, otherwise would need to handle connections on not yet created nodes +# here use tilemap as source of truth (with IsObstacle and Cost custom data) +func astar_add_walkable_cells(): + var cell_array = [] + for coords in get_used_cells(0): + # Be careful about hash collision, you could use a custom indexing function depending on your needs + # (example coords.x + map_size.x * coords.y) + var id = hash(coords) + + # Be carefull about what convention you used in the position parameter (here global) + var point = to_global(map_to_local(coords)) + + var tile_data:TileData = get_cell_tile_data(0, coords) + + # We could also disable point after having created it (for runtime modification for extent) + if(not tile_data or tile_data.get_custom_data("IsObstacle")): + continue + + astar_node.add_point(id, point, tile_data.get_custom_data("Cost")) + cell_array.append(id) + + return cell_array + +# Create connections by using Tilemap get_surrounding_cells +# would work even when changing coordinate system +func astar_connect_walkable_cells(cell_array): + for id in cell_array: + var point = astar_node.get_point_position(id) + var coords = local_to_map(to_local(point)) + for neighbor_coords in get_surrounding_cells(coords): + var neighbor_id = hash(neighbor_coords) + if astar_node.has_point(neighbor_id): + astar_node.connect_points(id, neighbor_id, false) + +# Getter of astar result in world coordinates +func get_astar_path(world_start, world_end): + var path_world = [] + var start_coords = local_to_map(to_local(world_start)) + var end_coords = local_to_map(to_local(world_end)) + + if _path_start_coords != start_coords or _path_end_coords != end_coords: + _path_start_coords = start_coords + _path_end_coords = end_coords + for point in _recalculate_path(): + var point_world = point + path_world.append(point_world) + + return path_world + + +func _recalculate_path(): + _point_path = [] + var start_point_index = hash(_path_start_coords) + var end_point_index = hash(_path_end_coords) + if(astar_node.has_point(start_point_index) and astar_node.has_point(end_point_index)): + _point_path = astar_node.get_point_path(start_point_index, end_point_index) + return _point_path + diff --git a/2d/navigation_astar_hexagonal/map.tscn b/2d/navigation_astar_hexagonal/map.tscn new file mode 100644 index 00000000000..bb2db6020b6 --- /dev/null +++ b/2d/navigation_astar_hexagonal/map.tscn @@ -0,0 +1,81 @@ +[gd_scene load_steps=5 format=3 uid="uid://b0qjuoqdfotei"] + +[ext_resource type="TileSet" uid="uid://sf8jvf8i1m31" path="res://tiles/tile_set.tres" id="1_44xps"] +[ext_resource type="Script" path="res://map.gd" id="2_bpqum"] +[ext_resource type="PackedScene" uid="uid://do0vop2jrn06u" path="res://player.tscn" id="2_mgwiw"] +[ext_resource type="Script" path="res://debug_astar.gd" id="4_vuylu"] + +[node name="Map" type="Node2D"] + +[node name="DebugAStar" type="Node2D" parent="." node_paths=PackedStringArray("map")] +z_index = 1 +script = ExtResource("4_vuylu") +map = NodePath("../TileMap") + +[node name="Camera2D" type="Camera2D" parent="."] +position = Vector2(506, 379) +limit_left = 0 +limit_top = 0 +limit_right = 2000 +limit_bottom = 2000 +editor_draw_limits = true + +[node name="Player" parent="." node_paths=PackedStringArray("map") instance=ExtResource("2_mgwiw")] +position = Vector2(639, 339) +map = NodePath("../TileMap") + +[node name="TileMap" type="TileMap" parent="."] +z_index = -1 +tile_set = ExtResource("1_44xps") +format = 2 +layer_0/tile_data = PackedInt32Array(65536, 65539, 2, 131072, 196611, 2, 196608, 196611, 2, 1, 196611, 2, 65537, 196611, 2, 131073, 131075, 2, 196609, 131075, 2, 2, 3, 2, 65538, 3, 2, 131074, 3, 2, 196610, 262147, 2, 262144, 196611, 2, 327680, 65539, 2, 393216, 196611, 2, 262145, 131075, 2, 327681, 196611, 2, 262146, 131075, 2, 327682, 3, 2, 3, 3, 2, 65539, 458755, 2, 131075, 131075, 2, 196611, 131075, 2, 262147, 65539, 2, 327683, 458755, 2, 4, 458755, 2, 65540, 131075, 2, 131076, 131075, 2, 196612, 131075, 2, 262148, 65539, 2, 327684, 458755, 2, 5, 458755, 2, 65541, 458755, 2, 131077, 458755, 2, 196613, 131075, 2, 262149, 458755, 2, 327685, 3, 2, 6, 3, 2, 65542, 3, 2, 131078, 458755, 2, 196614, 458755, 2, 262150, 458755, 2, 327686, 3, 2, 131079, 3, 2, 262151, 3, 2, 393219, 65539, 2, 393218, 65539, 2, 393217, 65539, 2, 0, 65539, 2, 7, 65539, 2, 65543, 65539, 2, 131080, 65539, 2, 196616, 65539, 2, 262152, 65539, 2, 327687, 3, 2, 393223, 458755, 2, 393222, 458755, 2, 393221, 458755, 2, 393220, 458755, 2, 393224, 3, 2, 196615, 3, 2, 458759, 131075, 2, 458760, 131075, 2, 393225, 131075, 2, 327688, 131075, 2, 131071, 131075, 2, 196607, 131075, 2, 262143, 131075, 2, 327679, 131075, 2, 393215, 131075, 2) +script = ExtResource("2_bpqum") + +[node name="CanvasLayer" type="CanvasLayer" parent="."] + +[node name="Control" type="Control" parent="CanvasLayer"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="PanelContainer" type="PanelContainer" parent="CanvasLayer/Control"] +layout_mode = 1 +anchors_preset = 10 +anchor_right = 1.0 +offset_bottom = 31.0 +grow_horizontal = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="CanvasLayer/Control/PanelContainer"] +layout_mode = 2 + +[node name="DPath" type="CheckBox" parent="CanvasLayer/Control/PanelContainer/HBoxContainer"] +layout_mode = 2 +button_pressed = true +text = "Debug Path" + +[node name="DCosts" type="CheckBox" parent="CanvasLayer/Control/PanelContainer/HBoxContainer"] +layout_mode = 2 +text = "Debug Costs" + +[node name="DWeights" type="CheckBox" parent="CanvasLayer/Control/PanelContainer/HBoxContainer"] +layout_mode = 2 +text = "Debug Weigths" + +[node name="DPositions" type="CheckBox" parent="CanvasLayer/Control/PanelContainer/HBoxContainer"] +layout_mode = 2 +text = "Debug Positions" + +[node name="DConnections" type="CheckBox" parent="CanvasLayer/Control/PanelContainer/HBoxContainer"] +layout_mode = 2 +text = "Debug Connections" + +[connection signal="toggled" from="CanvasLayer/Control/PanelContainer/HBoxContainer/DPath" to="DebugAStar" method="_on_d_path_toggled"] +[connection signal="toggled" from="CanvasLayer/Control/PanelContainer/HBoxContainer/DCosts" to="DebugAStar" method="_on_d_costs_toggled"] +[connection signal="toggled" from="CanvasLayer/Control/PanelContainer/HBoxContainer/DWeights" to="DebugAStar" method="_on_d_weights_toggled"] +[connection signal="toggled" from="CanvasLayer/Control/PanelContainer/HBoxContainer/DPositions" to="DebugAStar" method="_on_d_positions_toggled"] +[connection signal="toggled" from="CanvasLayer/Control/PanelContainer/HBoxContainer/DConnections" to="DebugAStar" method="_on_d_connections_toggled"] diff --git a/2d/navigation_astar_hexagonal/player.gd b/2d/navigation_astar_hexagonal/player.gd new file mode 100644 index 00000000000..0297637f91c --- /dev/null +++ b/2d/navigation_astar_hexagonal/player.gd @@ -0,0 +1,27 @@ +extends CharacterBody2D + +@export var map: Map +@export var speed = 400 # move speed in pixels/sec + +var _path_to_target:Array +var _target = null + + +func _input(event): + if event.is_action_pressed("click"): + _path_to_target = map.get_astar_path( global_position, get_global_mouse_position()) + if(not _path_to_target.is_empty()): + global_position = _path_to_target.pop_front() + _target = null + + +func _physics_process(delta): + if _target and position.distance_to(_target) > 10.0: + velocity = position.direction_to(_target) * speed + elif not _path_to_target.is_empty(): + _target = _path_to_target.pop_front() + else: + _target = null + velocity = Vector2.ZERO + + move_and_slide() diff --git a/2d/navigation_astar_hexagonal/player.png b/2d/navigation_astar_hexagonal/player.png new file mode 100644 index 0000000000000000000000000000000000000000..088335da8b8e33676eb35ef46fbd7b12760a8d44 GIT binary patch literal 5016 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 literal 0 HcmV?d00001 diff --git a/2d/navigation_astar_hexagonal/tiles/hexagonal_tiles_albedo.png b/2d/navigation_astar_hexagonal/tiles/hexagonal_tiles_albedo.png new file mode 100644 index 0000000000000000000000000000000000000000..f48fed5a348a9757f3d3fd277cd6e824e9b3a92b GIT binary patch literal 11254 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 eod4zuv=K@M>@KaCF%%E8T({QiqkKld(f