test_raycasting.gd 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. extends Test
  2. const OPTION_TEST_CASE_HIT_FROM_INSIDE = "Test case/Hit from inside"
  3. var _hit_from_inside := false
  4. var _do_raycasts := false
  5. func _ready() -> void:
  6. var options: OptionMenu = $Options
  7. options.add_menu_item(OPTION_TEST_CASE_HIT_FROM_INSIDE, true, false)
  8. options.option_changed.connect(_on_option_changed)
  9. await start_timer(0.5).timeout
  10. if is_timer_canceled():
  11. return
  12. _do_raycasts = true
  13. func _physics_process(delta: float) -> void:
  14. super._physics_process(delta)
  15. if not _do_raycasts:
  16. return
  17. _do_raycasts = false
  18. Log.print_log("* Start Raycasting...")
  19. clear_drawn_nodes()
  20. for node in $Shapes.get_children():
  21. var body: PhysicsBody2D = node
  22. var space_state := body.get_world_2d().direct_space_state
  23. var body_name := String(body.name).substr("RigidBody".length())
  24. Log.print_log("* Testing: %s" % body_name)
  25. var center := body.position
  26. # Raycast entering from the top.
  27. var res: Dictionary = _add_raycast(space_state, center - Vector2(0, 100), center)
  28. Log.print_log("Raycast in: %s" % ("HIT" if res else "NO HIT"))
  29. # Raycast exiting from inside.
  30. center.x -= 20
  31. res = _add_raycast(space_state, center, center + Vector2(0, 200))
  32. Log.print_log("Raycast out: %s" % ("HIT" if res else "NO HIT"))
  33. # Raycast all inside.
  34. center.x += 40
  35. res = _add_raycast(space_state, center, center + Vector2(0, 40))
  36. Log.print_log("Raycast inside: %s" % ("HIT" if res else "NO HIT"))
  37. if body_name.begins_with("Concave"):
  38. # Raycast inside an internal face.
  39. center.x += 20
  40. res = _add_raycast(space_state, center, center + Vector2(0, 40))
  41. Log.print_log("Raycast inside face: %s" % ("HIT" if res else "NO HIT"))
  42. func _on_option_changed(option: String, checked: bool) -> void:
  43. match option:
  44. OPTION_TEST_CASE_HIT_FROM_INSIDE:
  45. _hit_from_inside = checked
  46. _do_raycasts = true
  47. func _add_raycast(space_state: PhysicsDirectSpaceState2D, pos_start: Vector2, pos_end: Vector2) -> Dictionary:
  48. var params := PhysicsRayQueryParameters2D.new()
  49. params.from = pos_start
  50. params.to = pos_end
  51. params.hit_from_inside = _hit_from_inside
  52. var result: Dictionary = space_state.intersect_ray(params)
  53. var color := Color.RED.darkened(0.5)
  54. if result:
  55. color = Color.GREEN.darkened(0.2)
  56. # Draw raycast line.
  57. add_line(pos_start, pos_end, color)
  58. # Draw raycast arrow.
  59. add_line(pos_end, pos_end + Vector2(-5, -10), color)
  60. add_line(pos_end, pos_end + Vector2(5, -10), color)
  61. if result:
  62. # Draw raycast hit position.
  63. var hit_pos: Vector2 = result.position
  64. add_circle(hit_pos, 4.0, Color.YELLOW)
  65. # Draw raycast hit normal.
  66. add_line(hit_pos, hit_pos + result.normal * 16.0, Color.YELLOW)
  67. return result