how do i change the order, wich node calls the function first?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Drachenbauer

This is a Sokoban-geme, that I create on Godot.

Now the player can push a box once, but than nomore reactions on the input-keys.

The player and the box both call this function from the level:

func update_child_pos(child_node):
    var grid_pos = world_to_map(child_node.position)
    grid[grid_pos.x][grid_pos.y] = null
    var new_grid_pos = grid_pos + child_node.direction
    grid[new_grid_pos.x][new_grid_pos.y] = child_node.type
    var target_pos = map_to_world(new_grid_pos)
    return target_pos

the grid-array stores empty values or the type of wall, player or box in it´s cells

I think, the bug comes, because the player calls the function a tiny little bit earlyer, than the box.

the player overwrites the box on it´s new position.

and while the box calls the function, it overwrites the player on it´s now reached position with null.

The result: no more cell of the grid-araay is marked with the type of the player, who now has no more reference-position to calculate it´s movement

both call the function in _physics_process(delta).
How can i control, that the box executes the process first and than the player?

I added process_priority = 9 in _ready() of the box and
process_priority = 10 at the player.

But it makes no difference

Now i surrounded the line, that empties a cell in the array with an if:

    var is_player_already_on_box_pos = child_node.type == BOX && grid[grid_pos.x][grid_pos.y] == PLAYER
        if !is_player_already_on_box_pos:
            grid[grid_pos.x][grid_pos.y] = null

this works in the game, put the

func has_pusher(pos, direction):
    var pusher_pos = world_to_map(pos)
    return grid[pusher_pos.x][pusher_pos.y] == PLAYER

still looks wrong, because the grid-cell, where the box actually is, is already marked with the player, when this function is called.

so i really want all boxes execute their physics-process before the player.

or can i somehow replace the box´s _physics_process with a custom function (it includes move_and_collide(velocity)) and call it at the beginning of the player`s _physics_process?

:bust_in_silhouette: Reply From: SnapCracklins

I am not sure if yield works here, but you could use a signal between steps and have the object listen for it before it executes the next step. I used this solution to chain different animations on a project i am building.

It could be as easy as declaring a signal at top of script:
Signal map_update
And then placing the next part of the code that needs to execute in a separate function that triggers when the step you need done first is completed. That way, the second half will trigger only when the first is done.
So you could put your first function:
Then emit_signal(“map_update”, self)
Then on that func on_emit_signal, write the next piece of code.
Just make sure if you save the scene and then instance it, that you also run a signal connect in code if the second function goes outside the object.

but how can i use move_and_collide in a custom function?

Or how can i be sure, that a custom function does the calculation and updates a value before move_and_collide in _physics_process uses it?


now i used the position of node2D for movement.
i don´t need collision-shapes at all here, because it´s gridbased movement and i have my own check for valid moves.
if it detects a wall on the next cell it returns false, if there is a box, it checks, what is behind the box and otherwhise it returns true.
so i replaced kinematic body with simple node2D for player and box.

so i could call the movement-function for the boxes as the first thing at the player, if it´s a valid move and everything happens in correct order, that there are no more issues about updating the positions on the grid.

Drachenbauer | 2022-03-22 17:55