0 votes

https://github.com/Drachenbauer/Sokoban

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 physicsprocess(delta).
How can i control, that the box executes the process first and than the player?

I added processpriority = 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 physicsprocess with a custom function (it includes moveandcollide(velocity)) and call it at the beginning of the player`s physicsprocess?

Godot version v3.4.3
in Engine by (74 points)
edited by

1 Answer

0 votes

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 mapupdate
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(“mapupdate”, 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.

by (302 points)

but how can i use moveandcollide in a custom function?

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

edit:

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.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.