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 “on_body_entered(PhysicsBody2D)” but “on_body_entered(Node body)” doesn’t seem to work this way…
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
thanks ichster, I’ll look into it this weekend !
nonomiyo | 2019-08-28 20:16
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()