Hey, I have a little 2D grid based project which I intend to behave like Advance Wars or Fire Emblem and I'm currently working on how to determine possible movement for a selected unit. I'm pretty new to this type of programming and when trying to optimize my function it seems I stumbled upon a bug I could not get an explanation for that I could use some help figuring out! I'm doing this project to learn how it is to create games so if there are some general feedback or questions on how I structured this I'll be grateful for that too!
[The background]
What I'm working on currently is calculating the movement for a unit, for example when selecting a unit the movement grid will be displayed. From what I've read most people recommend using Flood Filling for this which seems simple; It's filling an area like a flood, like how water in Minecraft does.
[The code explained]
I have a recursive algorithm that does following 4 things:
1) It makes sure it doesn't overlap on a previously done tile by checking if it has an already drawn image. The "0" is the index of the tile image.
2) It draws/sets the tile at its cell position(The input at originPos is not aligned to the tilemaps cell grid itself, so I'm using world_to_map() to fix that issue, so far). The "0" is the index of the tile image to draw.
3) It decreases the movement and returns the function when no more movement is possible.
4) It recurs itself, expanding itself in each cardinal direction.
Summary: The flood fill expands itself from the original position, in every 4 directions, which in turn expands itself in all 4 directions until all movement "points" are spent
Parameters to the function:
originPos: The original position of the Unit. Note the Unit is a Node2D so its position coords is not the same as the Tilemaps cell coords. I use world_to_map() to solve this. I feel it's kinda bad practice on my part but hopefully that's a different issue.
movement: The movement stat of the unit, in this example I use movement=12
Here's my code:
# Draw the tiles using flood fill, indicating possible movement for a unit
func draw_movement(originPos, movement):
# Make sure the current iteration doesn't cover already painted tiles
if get_cellv(world_to_map(originPos)) == 0:
return
else:
set_cellv(world_to_map(originPos), 0);
movement -= 1
# No more movement possible, do not call recursions for next step
if movement < 0:
return
else:
draw_movement(originPos+Vector2(-16,0), movement)
draw_movement(originPos+Vector2(16,0), movement)
draw_movement(originPos+Vector2(0,16), movement)
draw_movement(originPos+Vector2(0,-16), movement)
[The problem]
What happens when I run this function is that I get a malformed grid:

However, when debugging it draws the movement properly, and if I would add yield(get_tree().create_timer(0.1), "timeout"), in other words a delay right after set_cellv() it will draw the movement properly when running:
# Draw the tiles using flood fill, indicating possible movement for a unit
func draw_movement(originPos, movement):
# Make sure the current iteration doesn't cover already painted tiles
if get_cellv(world_to_map(originPos)) == 0:
return
else:
set_cellv(world_to_map(originPos), 0);
yield(get_tree().create_timer(0.1), "timeout")
movement -= 1
# No more movement possible, do not call recursions for next step
if movement < 0:
return
else:
draw_movement(originPos+Vector2(-16,0), movement)
draw_movement(originPos+Vector2(16,0), movement)
draw_movement(originPos+Vector2(0,16), movement)
draw_movement(originPos+Vector2(0,-16), movement)

My theory was that I'm trying to draw every tile too quickly, (and perhaps too messy since it draws all 4 directions when it should only need max 3 at any time), which is something the game cannot handle well and as a result I'm losing tiles. However I found that a simple for-loop will not solve the issue like the yield() would, so clearly I'm doing something very bad which I'm oblivious to... Since neither debugging or running works for me I'm grateful for anyone who has an idea to what I'm doing wrong!
PS. I previously used an array to keep tab on which position had already been filled instead of checking the tile index with get_cellv(). That seems to be the normal way to do it and that worked without flaw, other than some freezing with larger grids due to processing. Why I'm posting this is because I'm interested in knowing why the code I showed here doesn't work.