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:
- Turn based actions
- Wolf pathfinding
- Loose condition
- Obstacles
- Door
- Opening the door with Wolf -> Loose as well
- Hunter kills wolf
- Transitions
- Menu
- Options
- Save
- 5 levels
- Win screen
- In game menu
- Better death animation
- Better indication that we need to kill the wolf before escaping
- Sounds
- Music
- Tutorial, Dialogs
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_positionsI’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()Some links
Before I let you go, here are some interesting links I came across this week:
- A nice threadorial on customizable transition shader
- A GDC talk on Growing Your Code Library with Each New Project including some advices I definitively plan on implementing as I build my games
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!