gai-godot-games/pathfinding-algorithms/scenes/mario-party/MarioPartyManagement.gd

126 lines
4.9 KiB
GDScript

extends Node2D
@onready var ground_layer: TileMapLayer = $GroundLayer
@onready var path_layer: TileMapLayer = $PathLayer
@onready var data_layer: TileMapLayer = $TestDataLayer
@onready var navigation_graph: MPNavigationGraph = $NavigationGraph
const DIRECTIONS: Dictionary = {
"up": Vector2(0, -1),
"down": Vector2(0, 1),
"left": Vector2(-1, 0),
"right": Vector2(1, 0)
}
var node_positions: Dictionary = {}
func _ready() -> void:
build_graph()
func build_graph() -> void:
print("Identifying nodes")
# Step 1: Place nodes at positions where is_tile is true
for position in data_layer.get_used_cells():
var tile_data: TileData = data_layer.get_cell_tile_data(position)
var is_tile: bool = tile_data.get_custom_data("is_tile")
if is_tile:
var node: NavigationNode = navigation_graph.add_node(position.x, position.y)
node_positions[position] = node
print(Vector2(position))
# Step 2: Connect nodes using flood-fill based on walkable tiles
print("Connecting nodes")
for position in node_positions.keys():
connect_node(position)
func connect_node(start_position: Vector2) -> void:
var start_node = node_positions.get(Vector2i(start_position))
var visited: Dictionary = {}
visited[start_position] = true
print("Connecting node at ", start_position)
# For each direction, perform flood-fill
for dir_name in DIRECTIONS.keys():
var direction = DIRECTIONS[dir_name]
var next_position = start_position + direction
print("Checking direction ", dir_name, " from ", start_position, " to ", next_position)
# Ensure the first tile respects the direction
if not is_valid_direction(next_position, dir_name):
continue
print("Flood-fill in direction ", dir_name, " from ", next_position)
# Perform flood-fill from the valid tile
var connected_nodes: Array = flood_fill(next_position, visited)
# Add connections between the start node and found nodes
for target_position in connected_nodes:
if target_position != start_position:
if node_positions.has(Vector2i(target_position)):
var target_node = node_positions.get(Vector2i(target_position))
navigation_graph.add_connection(start_node, target_node)
print(start_position, " --> ", target_position)
func flood_fill(start_position: Vector2, visited: Dictionary) -> Array:
var stack: Array[Vector2] = [start_position]
var connected_nodes: Array[Vector2] = []
while stack.size() > 0:
var current_position = stack.pop_back()
print(" - Visiting ", current_position)
# Skip if already visited
if visited.has(current_position):
continue
visited[current_position] = true
# Skip if not walkable
var tile_data: TileData = data_layer.get_cell_tile_data(current_position)
if tile_data == null:
continue
var is_walkable: bool = tile_data.get_custom_data("is_walkable")
var is_tile: bool = tile_data.get_custom_data("is_tile")
if (not is_walkable) and (not is_tile):
continue
# If this position is a node, add it to the result
if is_tile:
print(" - Found node tile at ", current_position)
connected_nodes.append(current_position)
else:
print(" - Found walkable tile at ", current_position)
# Add neighboring tiles to the stack if they respect the direction
for dir_name in DIRECTIONS.keys():
var direction = DIRECTIONS[dir_name]
var neighbor_position = current_position + direction
if not visited.has(neighbor_position):
if is_valid_direction(current_position, dir_name):
stack.append(neighbor_position)
return connected_nodes
func is_valid_direction(position: Vector2, required_dir: String) -> bool:
var tile_data: TileData = data_layer.get_cell_tile_data(position)
if tile_data == null:
print(" L Cancelled due to null tile data")
return false
var is_walkable: bool = tile_data.get_custom_data("is_walkable")
var walk_dir: String = tile_data.get_custom_data("walk_dir")
# If walk_dir is empty, treat it as "any" direction
if walk_dir == "":
walk_dir = "any"
print(" L ", position, " ", is_walkable, " ", walk_dir, " ", required_dir)
# Check if the tile is walkable and allows movement in the required direction
return is_walkable and (walk_dir == required_dir or walk_dir == "any")