0 votes

Hi ! I'm making a 2D platformer in which there are some balls bouncing around, which you have to avoid touching.

here is a PANG gameplay video, for a better understanding

My character is a KinematicBody2D and the balls are RigidBody2D instances. I have 2 issues :

1/ The balls are boucing thx to the integrated gravity system. I'd like them to keep bouncing at the same height forever. But even with the "Friction" setting set to 0 and the "Bounce" set to 5000, they bounce lower and lower on each rebound. Is there a way to do this ? Does it make sense for the balls to be RigidBody2Ds ?

2/ the character is physically colliding with the balls properly but how should I detect collisions to trigger a code ?
I'm looking for a signal like the one for Area2Ds called "onbodyentered(PhysicsBody2D)" but "onbodyentered(Node body)" doesn't seem to work this way...

-Any help is welcome, Thank you !
(godot 3.1.1)

in Engine by (245 points)
edited by

1 Answer

+1 vote
Best answer

KinematicBodies2D don't have those helpful collision signals probably because they are meant to be user-controlled and not use the advanced physics that the physics engine provides. They can detect collisions, but only when asked to (using functions like move_and_collide() and move_and_slide()). If you want to emit_signals or do some other processing upon collision with another physics body it might look something like this:

signal hit_ball

func _test_if_bouncy_ball(object):
    # could also do something like: object.is_type("RigidBody2d")
    if object.get_meta() == "i set all bouncy balls to have this exact meta data string using set_meta()":
        return true
    else:
        return false

func _react_to_hit_bouncy_ball():
    emit_signal("hit_ball")

func _physics_process(delta):
    # test the collisions created after calling move_and_slide() or similiar
    var slide_count = get_slide_count()
    if slide_count > 0:
        for idx in get_slide_count():
            var collision = get_slide_collision(idx)
            if _test_if_bouncy_ball(collision.get_collider()):
                _react_to_hit_bouncy_ball()

If you want to make same-height-every-bounce bouncy balls I would suggest using a KinematicBody2D (since it sounds like you don't want to use the physics engine features like "Bounce" at all), and then just move in the direction of the mirrored normal of the collisions. To get this normal you would do something like this:

func reflect():
    # THIS WON'T WORK I'M JUST SHOWING THE FUNCTIONS YOU MIGHT USE
    var collision = get_slide_collision(0)
    var normal = collision.get_normal()
    velocity = normal * SPEED
by (169 points)
selected by

thanks ichster, I'll look into it this weekend ! :)

With your help, I ended up solving it this way :
I made the balls kinematicbodies2D then put this code in them :

func _physics_process(delta):
    velocity.y += gravity * delta

    var collision = move_and_collide(velocity * delta)
    if collision : 
        if collision.collider.name == "walls":
            velocity = velocity.bounce(collision.normal)
        else : 
            $ball_anim.play("ballcrash")
            if collision.collider.has_method("hit"):
                collision.collider.hit()

It's working now, thanks ! ;)

Glad to see it, good job!

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.