0
\$\begingroup\$

I am working in Godot 3, where my player is a KinematicBody2D. When I collide with a block which is also a KinematicBody2D I'd like my player to push it without losing velocity.

My block is in a group called moveables, has no script, and has no other forces acting on it.

After I calculate the velocity of my player in _physics_process(), I have the following code.

# update position and handle collision

var collision = move_and_collide(vel * delta)
if collision:
    var collider = collision.collider
    var normal = collision.normal
    var remainder = collision.remainder
    var collision_angle = rad2deg(acos(normal.dot(Vector2(0,-1))))

    # floors
    if collision_angle == 0:

        # reset y vel so it doesn't keep accumulating
        vel.y = 0

        var horizontal_movement = Vector2(remainder.x, 0)
        move_and_collide(horizontal_movement)

    # moveables
    elif collision_angle == 90:
        if collider in get_tree().get_nodes_in_group("moveables"): 
                collider.move_and_collide(remainder) # move block by remainder
                move_and_collide(remainder) # move player by remainder

This code does allow the player to push the block, but only slowly. I can't figure out why. Ideally, the player would push the block without losing any velocity.

Even if I directly update only the horizontal position of my block, it still moves slower than expected, and my player sprite is blurred, presumably because of collision corrections.

        if collider in get_tree().get_nodes_in_group("moveables"): 
            collider.global_position.x += remainder.x
            move_and_collide(remainder)

The problem seems to be that when I move the player by the remainder, the player is still colliding with the block, even though I move the block itself in the previous line. This is confirmed by analyzing the collision object move_and_collide(remainder).

What's wrong and how can I achieve the desired movement?

I asked a variant of this question on a Godot forum, but am also asking it here for increased visibility.

\$\endgroup\$
  • 2
    \$\begingroup\$ Why did you decide to make the block a KinematicBody2D? From the Godot documentation: "Kinematic bodies are special types of bodies that are meant to be user-controlled. They are not affected by physics at all (to other types of bodies, such a character or a rigid body, these are the same as a static body)" - this seems ill-suited to an object you want to push around with physics. Is using a RigidBody2D for the block a viable option? \$\endgroup\$ – DMGregory Dec 16 '18 at 15:21
  • \$\begingroup\$ RigidBody2D uses Godot's in-built physics (it requires you to specify friction, mass, gravity scale). KinematicBody2D allows you to specify all movement yourself, and gives you more control. Because my player is a KinematicBody2D, the block should also be, I think. Especially because a KinematicBody2D cannot interact with a RigidBody2D, except by manually detecting collision between them, and then calling add_force() or apply_impulse() on the RigidBody2D (similar to what I'm doing already). There should be a simple way to do this with two KinematicBody2Ds, but I've yet to figure it out. \$\endgroup\$ – GoldenGremlin Dec 16 '18 at 15:30
  • 1
    \$\begingroup\$ KinematicBody2D is a good choice for when your physics are simple and you want to implement them yourself in code, like eg. the pieces on a chess board or the blocks of a Sokoban. If you want to rely on Godot to handle the physics, however, it's much easier to use a RigidBody2D and handle any adjustments to the default physics in the physics process callback. If you want to use a KinematicBody2D, you have to add collision areas to your blocks, check for the presence of the player character's body and inherit its horizontal movement. \$\endgroup\$ – flesk Dec 17 '18 at 7:44
  • \$\begingroup\$ Thanks for the suggestion. I will add RayCast2Ds to each side of the block and alter the block's position depending on the player's velocity (as long as certain other conditions are met). \$\endgroup\$ – GoldenGremlin Dec 17 '18 at 18:27

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.