Skip to content

Instantly share code, notes, and snippets.

@ryanmunger
Created September 9, 2020 15:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryanmunger/90ef9877d803075abf114080053481bd to your computer and use it in GitHub Desktop.
Save ryanmunger/90ef9877d803075abf114080053481bd to your computer and use it in GitHub Desktop.
astar walkable tiles issue
extends TileMap
# You can only create an AStar node from code, not from the Scene tab
onready var astar_node = AStar2D.new()
# The Tilemap node doesn't have clear bounds so we're defining the map's limits here
export(Vector2) var map_size = Vector2(16, 16)
# The path start and end variables use setter methods
# You can find them at the bottom of the script
var path_start_position = Vector2() setget _set_path_start_position
var path_end_position = Vector2() setget _set_path_end_position
var _point_path = []
var _current_steps = []
const BASE_LINE_WIDTH = 3.0
const DRAW_COLOR = Color('#fff')
# get_used_cells_by_id is a method from the TileMap node
# here the id 0 corresponds to the grey tile, the obstacles
onready var tiles = get_used_cells()
onready var obstacles = get_used_cells_by_id(0)
onready var _half_cell_size = cell_size / 2
func _ready():
var walkable_cells_list = show_walkable_cells(obstacles)
astar_connect_walkable_cells_diagonal(walkable_cells_list)
func show_walkable_cells(obstacles = []):
var points_array = []
var player_position = world_to_map(get_parent().get_node("Character").position)
for x in range(5):
for y in range(5):
var walkable_tile = player_position + Vector2(x - 2, y - 2)
if walkable_tile in obstacles:
continue
if is_outside_map_bounds(walkable_tile):
continue
points_array.append(walkable_tile)
# The AStar class references points with indices
# Using a function to calculate the index from a point's coordinates
# ensures we always get the same index with the same input point
var point_index = calculate_point_index(walkable_tile)
# AStar works for both 2d and 3d, so we have to convert the point
# coordinates from and to Vector3s
astar_node.add_point(point_index, Vector2(walkable_tile.x, walkable_tile.y))
return points_array
# This is a variation of the method above
# It connects cells horizontally, vertically AND diagonally
func astar_connect_walkable_cells_diagonal(points_array):
var point_paths = []
var player_index = calculate_point_index(world_to_map(get_parent().get_node("Character").position))
for point in points_array:
var point_index = calculate_point_index(point)
for local_y in range(3):
for local_x in range(3):
var point_relative = Vector2(point.x + local_x - 1, point.y + local_y - 1)
var point_relative_index = calculate_point_index(point_relative)
point_paths.append(astar_node.get_point_path(player_index, point_relative_index))
# print("player_index: " + str(player_index) + " " + "point_relative: " + str(point_relative) + " " + "point_relative_index: " + str(point_relative_index) + " " + "astar_paths: " + str(astar_node.get_point_path(player_index, point_relative_index)))
if point_relative == point or is_outside_map_bounds(point_relative):
continue
if not astar_node.has_point(point_relative_index):
continue
astar_node.connect_points(point_index, point_relative_index, true)
# print("point_paths: " + str(astar_node.get_point_path(player_index, point_relative_index)))
# print("point_relative: " + str(point_relative))
# print("point: " + str(point))
# print("player index: " + str(player_index))
if point_relative in astar_node.get_point_path(player_index, point_relative_index):
set_cell(point_relative.x, point_relative.y, 3)
print(point_paths)
func is_outside_map_bounds(point):
return point.x < 0 or point.y < 0 or point.x >= map_size.x or point.y >= map_size.y
func calculate_point_index(point):
return point.x + map_size.x * point.y
func find_path(world_start, world_end):
self.path_start_position = world_to_map(world_start)
self.path_end_position = world_to_map(world_end)
_recalculate_path()
var path_world = []
for point in _point_path:
var point_world = map_to_world(Vector2(point.x, point.y)) + _half_cell_size
path_world.append(point_world)
return path_world
func _recalculate_path():
var start_point_index = calculate_point_index(path_start_position)
var end_point_index = calculate_point_index(path_end_position)
# This method gives us an array of points. Note you need the start and end
# points' indices as input
_point_path = astar_node.get_point_path(start_point_index, end_point_index)
# Redraw the lines and circles from the start to the end point
update()
# Setters for the start and end path values.
func _set_path_start_position(value):
if value in obstacles:
return
if is_outside_map_bounds(value):
return
path_start_position = value
if path_end_position and path_end_position != path_start_position:
_recalculate_path()
func _set_path_end_position(value):
if value in obstacles:
return
if is_outside_map_bounds(value):
return
# set_cell(path_start_position.x, path_start_position.y, -1)
# set_cell(value.x, value.y, 2)
path_end_position = value
if path_start_position != value:
_recalculate_path()
@ryanmunger
Copy link
Author

The place where I am setting the "visiliby walkable tiles" is line 73.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment