ball.gd 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. class_name Ball
  2. extends CharacterBody2D
  3. ## A ball that bounces off everything, speeds up slightly on each bounce and falls under
  4. ## light gravity.
  5. ## Emitted for every contact, so the game can react to what the ball touched.
  6. signal hit(ball: Ball, other: Node)
  7. ## A superball destroys one indestructible block, then turns back into a normal ball.
  8. var superball := false:
  9. set(value):
  10. superball = value
  11. queue_redraw()
  12. func throw() -> void:
  13. var angle := deg_to_rad(randf_range(-Params.THROW_ANGLE, Params.THROW_ANGLE))
  14. velocity = Vector2(sin(angle), -cos(angle)) * Params.INITIAL_SPEED
  15. func _physics_process(delta: float) -> void:
  16. velocity.y += Params.BALL_GRAVITY * delta
  17. var motion := velocity * delta
  18. for i in 4:
  19. var collision := move_and_collide(motion)
  20. if collision == null:
  21. break
  22. var other := collision.get_collider() as Node
  23. var normal := collision.get_normal()
  24. var bounce: float = other.get_meta("bounce", 1.0)
  25. velocity = velocity.bounce(normal) * Params.BALL_BOUNCE * bounce
  26. motion = collision.get_remainder().bounce(normal)
  27. hit.emit(self, other)
  28. if is_queued_for_deletion():
  29. return
  30. _kick_power_ups()
  31. ## Power-ups are 1/1000 of a ball's mass: they get knocked away and the ball doesn't notice.
  32. func _kick_power_ups() -> void:
  33. for power_up: PowerUp in get_tree().get_nodes_in_group("power_ups"):
  34. var offset := power_up.global_position - global_position
  35. var dist := offset.length()
  36. if dist == 0.0 or dist > Params.BALL_RADIUS + PowerUp.RADIUS:
  37. continue
  38. var normal := offset / dist
  39. var approach := (power_up.linear_velocity - velocity).dot(normal)
  40. if approach < 0.0:
  41. power_up.linear_velocity -= 2.0 * approach * normal
  42. hit.emit(self, power_up)
  43. func _draw() -> void:
  44. draw_circle(Vector2.ZERO, Params.BALL_RADIUS, Params.COLOR_ORANGE if superball else Params.COLOR_GREY, true, -1.0, true)