11extends TileMap
22
3- # You can only create an AStar node from code, not from the Scene tab
4- onready var astar_node = AStar .new ()
5- # The Tilemap node doesn't have clear bounds so we're defining the map's limits here
3+ const BASE_LINE_WIDTH = 3.0
4+ const DRAW_COLOR = Color .white
5+
6+ # The Tilemap node doesn't have clear bounds so we're defining the map's limits here.
67export (Vector2 ) var map_size = Vector2 (16 , 16 )
78
8- # The path start and end variables use setter methods
9- # You can find them at the bottom of the script
9+ # The path start and end variables use setter methods.
10+ # You can find them at the bottom of the script.
1011var path_start_position = Vector2 () setget _set_path_start_position
1112var path_end_position = Vector2 () setget _set_path_end_position
1213
1314var _point_path = []
1415
15- const BASE_LINE_WIDTH = 3.0
16- const DRAW_COLOR = Color ('#fff' )
17-
18- # get_used_cells_by_id is a method from the TileMap node
19- # here the id 0 corresponds to the grey tile, the obstacles
16+ # You can only create an AStar node from code, not from the Scene tab.
17+ onready var astar_node = AStar .new ()
18+ # get_used_cells_by_id is a method from the TileMap node.
19+ # Here the id 0 corresponds to the grey tile, the obstacles.
2020onready var obstacles = get_used_cells_by_id (0 )
2121onready var _half_cell_size = cell_size / 2
2222
@@ -25,8 +25,25 @@ func _ready():
2525 astar_connect_walkable_cells (walkable_cells_list )
2626
2727
28- # Click and Shift force the start and end position of the path to update
29- # and the node to redraw everything
28+ func _draw ():
29+ if not _point_path :
30+ return
31+ var point_start = _point_path [0 ]
32+ var point_end = _point_path [len (_point_path ) - 1 ]
33+
34+ set_cell (point_start .x , point_start .y , 1 )
35+ set_cell (point_end .x , point_end .y , 2 )
36+
37+ var last_point = map_to_world (Vector2 (point_start .x , point_start .y )) + _half_cell_size
38+ for index in range (1 , len (_point_path )):
39+ var current_point = map_to_world (Vector2 (_point_path [index ].x , _point_path [index ].y )) + _half_cell_size
40+ draw_line (last_point , current_point , DRAW_COLOR , BASE_LINE_WIDTH , true )
41+ draw_circle (current_point , BASE_LINE_WIDTH * 2.0 , DRAW_COLOR )
42+ last_point = current_point
43+
44+
45+ # Click and Shift force the start and end position of the path to update,
46+ # and the node to redraw everything.
3047# func _input(event):
3148# if event.is_action_pressed('click') and Input.is_key_pressed(KEY_SHIFT):
3249# # To call the setter method from this script we have to use the explicit self.
@@ -36,81 +53,88 @@ func _ready():
3653
3754
3855# Loops through all cells within the map's bounds and
39- # adds all points to the astar_node, except the obstacles
40- func astar_add_walkable_cells (obstacles = []):
56+ # adds all points to the astar_node, except the obstacles.
57+ func astar_add_walkable_cells (obstacle_list = []):
4158 var points_array = []
4259 for y in range (map_size .y ):
4360 for x in range (map_size .x ):
4461 var point = Vector2 (x , y )
45- if point in obstacles :
62+ if point in obstacle_list :
4663 continue
4764
4865 points_array .append (point )
49- # The AStar class references points with indices
66+ # The AStar class references points with indices.
5067 # Using a function to calculate the index from a point's coordinates
51- # ensures we always get the same index with the same input point
68+ # ensures we always get the same index with the same input point.
5269 var point_index = calculate_point_index (point )
5370 # AStar works for both 2d and 3d, so we have to convert the point
54- # coordinates from and to Vector3s
71+ # coordinates from and to Vector3s.
5572 astar_node .add_point (point_index , Vector3 (point .x , point .y , 0.0 ))
5673 return points_array
5774
5875
59- # Once you added all points to the AStar node, you've got to connect them
76+ # Once you added all points to the AStar node, you've got to connect them.
6077# The points don't have to be on a grid: you can use this class
61- # to create walkable graphs however you'd like
78+ # to create walkable graphs however you'd like.
6279# It's a little harder to code at first, but works for 2d, 3d,
6380# orthogonal grids, hex grids, tower defense games...
6481func astar_connect_walkable_cells (points_array ):
6582 for point in points_array :
6683 var point_index = calculate_point_index (point )
6784 # For every cell in the map, we check the one to the top, right.
68- # left and bottom of it. If it's in the map and not an obstalce,
69- # We connect the current point with it
85+ # left and bottom of it. If it's in the map and not an obstalce.
86+ # We connect the current point with it.
7087 var points_relative = PoolVector2Array ([
7188 Vector2 (point .x + 1 , point .y ),
7289 Vector2 (point .x - 1 , point .y ),
7390 Vector2 (point .x , point .y + 1 ),
7491 Vector2 (point .x , point .y - 1 )])
7592 for point_relative in points_relative :
7693 var point_relative_index = calculate_point_index (point_relative )
77-
7894 if is_outside_map_bounds (point_relative ):
7995 continue
8096 if not astar_node .has_point (point_relative_index ):
8197 continue
8298 # Note the 3rd argument. It tells the astar_node that we want the
83- # connection to be bilateral: from point A to B and B to A
84- # If you set this value to false, it becomes a one-way path
85- # As we loop through all points we can set it to false
99+ # connection to be bilateral: from point A to B and B to A.
100+ # If you set this value to false, it becomes a one-way path.
101+ # As we loop through all points we can set it to false.
86102 astar_node .connect_points (point_index , point_relative_index , false )
87103
88104
89- # This is a variation of the method above
90- # It connects cells horizontally, vertically AND diagonally
105+ # This is a variation of the method above.
106+ # It connects cells horizontally, vertically AND diagonally.
91107func astar_connect_walkable_cells_diagonal (points_array ):
92108 for point in points_array :
93109 var point_index = calculate_point_index (point )
94110 for local_y in range (3 ):
95111 for local_x in range (3 ):
96112 var point_relative = Vector2 (point .x + local_x - 1 , point .y + local_y - 1 )
97113 var point_relative_index = calculate_point_index (point_relative )
98-
99114 if point_relative == point or is_outside_map_bounds (point_relative ):
100115 continue
101116 if not astar_node .has_point (point_relative_index ):
102117 continue
103118 astar_node .connect_points (point_index , point_relative_index , true )
104119
105120
106- func is_outside_map_bounds (point ):
107- return point .x < 0 or point .y < 0 or point .x >= map_size .x or point .y >= map_size .y
108-
109-
110121func calculate_point_index (point ):
111122 return point .x + map_size .x * point .y
112123
113124
125+ func clear_previous_path_drawing ():
126+ if not _point_path :
127+ return
128+ var point_start = _point_path [0 ]
129+ var point_end = _point_path [len (_point_path ) - 1 ]
130+ set_cell (point_start .x , point_start .y , - 1 )
131+ set_cell (point_end .x , point_end .y , - 1 )
132+
133+
134+ func is_outside_map_bounds (point ):
135+ return point .x < 0 or point .y < 0 or point .x >= map_size .x or point .y >= map_size .y
136+
137+
114138func _get_path (world_start , world_end ):
115139 self .path_start_position = world_to_map (world_start )
116140 self .path_end_position = world_to_map (world_end )
@@ -126,39 +150,13 @@ func _recalculate_path():
126150 clear_previous_path_drawing ()
127151 var start_point_index = calculate_point_index (path_start_position )
128152 var end_point_index = calculate_point_index (path_end_position )
129- # This method gives us an array of points. Note you need the start and end
130- # points' indices as input
153+ # This method gives us an array of points. Note you need the start and
154+ # end points' indices as input.
131155 _point_path = astar_node .get_point_path (start_point_index , end_point_index )
132- # Redraw the lines and circles from the start to the end point
156+ # Redraw the lines and circles from the start to the end point.
133157 update ()
134158
135159
136- func clear_previous_path_drawing ():
137- if not _point_path :
138- return
139- var point_start = _point_path [0 ]
140- var point_end = _point_path [len (_point_path ) - 1 ]
141- set_cell (point_start .x , point_start .y , - 1 )
142- set_cell (point_end .x , point_end .y , - 1 )
143-
144-
145- func _draw ():
146- if not _point_path :
147- return
148- var point_start = _point_path [0 ]
149- var point_end = _point_path [len (_point_path ) - 1 ]
150-
151- set_cell (point_start .x , point_start .y , 1 )
152- set_cell (point_end .x , point_end .y , 2 )
153-
154- var last_point = map_to_world (Vector2 (point_start .x , point_start .y )) + _half_cell_size
155- for index in range (1 , len (_point_path )):
156- var current_point = map_to_world (Vector2 (_point_path [index ].x , _point_path [index ].y )) + _half_cell_size
157- draw_line (last_point , current_point , DRAW_COLOR , BASE_LINE_WIDTH , true )
158- draw_circle (current_point , BASE_LINE_WIDTH * 2.0 , DRAW_COLOR )
159- last_point = current_point
160-
161-
162160# Setters for the start and end path values.
163161func _set_path_start_position (value ):
164162 if value in obstacles :
0 commit comments