Walking the path

Hi friends, I hope you all had a great week and weekend!

This week I’ve made some progress on my Little Red Riding Hood puzzle game, it’s now a fully functioning game, with 2 levels. I still have a lot to do before I can call that a finished product though:

Building on Heartbeast A* pathfinding

To implement my wolf pathfinding, I used HeartBeast’s Astar Implementation Script for TileMap Nodes in Godot. The debug is view is really neat, and the script easy to build from. I had to modify it slightly for my use case:

Indexing cells by their grid position

In the original script, all the cells, units and obstacle are indexed using their real world position.
Let’s focus on the cells:

func create_pathfinding_points() -> void:
	astar.clear()
	var used_cell_positions = get_used_cell_global_positions()
	for cell_position in used_cell_positions:
		astar.add_point(get_point(cell_position), cell_position)

func get_used_cell_global_positions() -> Array:
	var cells = get_used_cells()
	var cell_positions := []
	for cell in cells:
		var cell_position := global_position + map_to_world(cell)
		cell_positions.append(cell_position)
	return cell_positions

I’m now indexing only based on the cell position in the grid:

func create_pathfinding_points() -> void:
	astar.clear()
	#var used_cell_positions = get_used_cell_global_positions()
	var used_cell_positions = get_used_cells()
	for cell_position in used_cell_positions:
		var cell_world_position = global_position + map_to_world(cell_position) + cell_size/2
		astar.add_point(get_point(cell_position), cell_world_position)

I also took the opportunity to register the center of the cell directly, as it’s what I found myself needing the most.

Movement

The movement is heavily inspired by this tutorial by GDQuest, but instead of directly checking if the point is walkable, I’m using the paths built with astar:

func _process(delta):
	var input_direction = get_input_direction()
	if not input_direction:
		return
		
	var cell_start = Grid.world_to_map(position)
	var cell_target = cell_start + input_direction
	var path_points = Grid.get_astar_path_avoiding_obstacles(cell_start, cell_target)
	if len(path_points) > 1:
		move_to(path_points[1])
	else:
		bump()

Objects

I also needed to have interactable objects on the grid, so I’m registering them exactly like the obstacles:

func add_object(object: Object) -> void:
	objects[get_point(world_to_map(object.position))] = object
	if not object.is_connected("tree_exiting", self, "remove_object"):
		object.connect("tree_exiting", self, "remove_object", [object])
				
func remove_object(object: Object) -> void:
	objects.erase(object)

And then in the movement script above I’m adding:

	var path_points = Grid.get_astar_path_avoiding_obstacles(cell_start, cell_target)
	if len(path_points) > 1:
		move_to(path_points[1])
		var object = Grid.get_object_on_cell(position)
		if object:
			object.interact()

Before I let you go, here are some interesting links I came across this week:

 

All right, that’s all for this week.
It has a bit heavier on the code side than usual, I hope it was your cup of tea!

Thanks for reading and see you next week!