Skip to content

Commit 193e3ed

Browse files
committed
Add Navigation AStar Hexagonal demo
1 parent 98e9176 commit 193e3ed

19 files changed

+771
-0
lines changed
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Tile-based navigation on hexagonal Tilemap (2D)
2+
3+
Example of using 2D navigation (tile based) on a hexagonal map, using :
4+
- [`TileMap`](https://docs.godotengine.org/en/stable/classes/class_tilemap.html)
5+
- [`AStar2D`](https://docs.godotengine.org/en/stable/classes/class_astar2d.html)
6+
7+
Language: GDScript
8+
9+
Renderer: Compatibility
10+
11+
Use mouse left click to interact.
12+
13+
## Screenshots
14+
15+
![Screenshot](screenshots/Hexagon_Navigation_2D.png)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
class_name AStarHex2D
2+
extends AStar2D
3+
4+
var map: TileMap
5+
6+
# Final cost used for pathfinding would be weight * cost
7+
# See https://docs.godotengine.org/fr/4.x/classes/class_astar3d.html#class-astar3d
8+
func _compute_cost( from_id:int, to_id:int ):
9+
return 1
10+
11+
func _estimate_cost( from_id:int, to_id:int ):
12+
return 1
13+
14+
# Euclidian distance heuristic would not work on hexagonal map with global position because
15+
# we are not using regular hexagon
16+
# https://github.com/godotengine/godot/issues/92338
17+
18+
#func _compute_cost( from_id:int, to_id:int ):
19+
#var position_from = get_point_position(from_id)
20+
#var position_to = get_point_position(to_id)
21+
#return (position_to - position_from).length_squared()
22+
23+
#func _estimate_cost( from_id:int, to_id:int ):
24+
#var position_from = get_point_position(from_id)
25+
#var position_to = get_point_position(to_id)
26+
#return (position_to - position_from).length_squared()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
extends Node2D
2+
3+
@export var map: Map
4+
5+
@onready var font:Font = ThemeDB.fallback_font
6+
7+
const BASE_LINE_WIDTH = 3.0
8+
const DRAW_COLOR:Color = Color.WHITE
9+
const OFFSET_POSITIONS = Vector2(10,30)
10+
const OFFSET_WEIGHT = Vector2(10,-10)
11+
12+
var _debug_connections = false
13+
var _debug_position = false
14+
var _debug_weights = false
15+
var _debug_costs = false
16+
var _debug_path = true
17+
18+
19+
func _process(delta):
20+
queue_redraw()
21+
pass
22+
23+
24+
func draw_arrow(src, dst, color, width, aa = true):
25+
var angle = 0.6
26+
var size_head = 20
27+
var head : Vector2 = (dst - src).normalized() * size_head
28+
draw_line(src, dst-head/2, color, width, aa)
29+
draw_polygon([dst, dst - head.rotated(angle), dst - head.rotated(-angle) ], [color,color,color ])
30+
31+
32+
func _draw():
33+
if _debug_connections :
34+
_draw_connections()
35+
if _debug_position :
36+
_draw_positions()
37+
if _debug_weights :
38+
_draw_weights()
39+
if _debug_costs :
40+
_draw_costs()
41+
if _debug_path :
42+
_draw_path()
43+
44+
45+
func _draw_path():
46+
if not map._point_path:
47+
return
48+
var point_start: Vector2i = map._point_path[0]
49+
var point_end: Vector2i = map._point_path[len(map._point_path) - 1]
50+
51+
var last_point = point_start
52+
for index in range(1, len(map._point_path)):
53+
var current_point = map._point_path[index]
54+
draw_line(last_point, current_point, DRAW_COLOR, BASE_LINE_WIDTH, true)
55+
draw_circle(current_point, BASE_LINE_WIDTH * 2.0, DRAW_COLOR)
56+
last_point = current_point
57+
58+
59+
func _draw_weights():
60+
for id in map.astar_node.get_point_ids():
61+
var position_weight = map.astar_node.get_point_position(id)
62+
var cost = map.astar_node.get_point_weight_scale(id)
63+
draw_string(
64+
font,
65+
position_weight + OFFSET_WEIGHT,
66+
str(cost),
67+
HORIZONTAL_ALIGNMENT_FILL,
68+
-1,
69+
16,
70+
Color.RED
71+
)
72+
73+
74+
func _draw_positions():
75+
for id in map.astar_node.get_point_ids():
76+
var position_label = map.astar_node.get_point_position(id)
77+
var position_map = map.local_to_map(map.to_local(map.astar_node.get_point_position(id)))
78+
draw_string(
79+
font,
80+
position_label + OFFSET_POSITIONS,
81+
str(position_map),
82+
HORIZONTAL_ALIGNMENT_FILL,
83+
-1,
84+
16,
85+
Color.RED
86+
)
87+
88+
89+
func _draw_connections():
90+
for id in map.astar_node.get_point_ids():
91+
for id_con in map.astar_node.get_point_connections(id):
92+
var position_start = map.astar_node.get_point_position(id)
93+
var position_end = map.astar_node.get_point_position(id_con)
94+
var direction = (position_end - position_start)
95+
draw_arrow(position_start, position_end - direction/4.0, Color(0.0, 1.0, 1.0, 1.0), BASE_LINE_WIDTH*2, true)
96+
97+
98+
func _draw_costs():
99+
for id in map.astar_node.get_point_ids():
100+
for id_con in map.astar_node.get_point_connections(id):
101+
var position_cost_start = map.astar_node.get_point_position(id)
102+
var position_cost_end = map.astar_node.get_point_position(id_con)
103+
var cost = map.astar_node._compute_cost(id, id_con)
104+
draw_string(
105+
font,
106+
(position_cost_start+position_cost_end)/2.0,
107+
str("%.2f"%cost),
108+
HORIZONTAL_ALIGNMENT_CENTER,
109+
-1,
110+
16,
111+
Color.PINK
112+
)
113+
114+
115+
func _on_d_path_toggled(toggled_on):
116+
_debug_path = toggled_on
117+
118+
119+
func _on_d_costs_toggled(toggled_on):
120+
_debug_costs = toggled_on
121+
122+
123+
func _on_d_positions_toggled(toggled_on):
124+
_debug_position = toggled_on
125+
126+
127+
func _on_d_connections_toggled(toggled_on):
128+
_debug_connections = toggled_on
129+
130+
131+
func _on_d_weights_toggled(toggled_on):
132+
_debug_weights = toggled_on
133+
+121
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
[remap]
2+
3+
importer="texture"
4+
type="CompressedTexture2D"
5+
uid="uid://brh8t0d5w2mkc"
6+
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
7+
metadata={
8+
"vram_texture": false
9+
}
10+
11+
[deps]
12+
13+
source_file="res://icon.svg"
14+
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
15+
16+
[params]
17+
18+
compress/mode=0
19+
compress/high_quality=false
20+
compress/lossy_quality=0.7
21+
compress/hdr_compression=1
22+
compress/normal_map=0
23+
compress/channel_pack=0
24+
mipmaps/generate=false
25+
mipmaps/limit=-1
26+
roughness/mode=0
27+
roughness/src_normal=""
28+
process/fix_alpha_border=true
29+
process/premult_alpha=false
30+
process/normal_map_invert_y=false
31+
process/hdr_as_srgb=false
32+
process/hdr_clamp_exposure=false
33+
process/size_limit=0
34+
detect_3d/compress_to=1
35+
svg/scale=1.0
36+
editor/scale_with_editor_scale=false
37+
editor/convert_colors_with_editor_theme=false
5.76 KB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
[remap]
2+
3+
importer="texture"
4+
type="CompressedTexture2D"
5+
uid="uid://bnujvgksdtkex"
6+
path="res://.godot/imported/icon.webp-e94f9a68b0f625a567a797079e4d325f.ctex"
7+
metadata={
8+
"vram_texture": false
9+
}
10+
11+
[deps]
12+
13+
source_file="res://icon.webp"
14+
dest_files=["res://.godot/imported/icon.webp-e94f9a68b0f625a567a797079e4d325f.ctex"]
15+
16+
[params]
17+
18+
compress/mode=0
19+
compress/high_quality=false
20+
compress/lossy_quality=0.7
21+
compress/hdr_compression=1
22+
compress/normal_map=0
23+
compress/channel_pack=0
24+
mipmaps/generate=false
25+
mipmaps/limit=-1
26+
roughness/mode=0
27+
roughness/src_normal=""
28+
process/fix_alpha_border=true
29+
process/premult_alpha=false
30+
process/normal_map_invert_y=false
31+
process/hdr_as_srgb=false
32+
process/hdr_clamp_exposure=false
33+
process/size_limit=0
34+
detect_3d/compress_to=1

0 commit comments

Comments
 (0)