test_collision_pairs.gd 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. extends Test
  2. const OPTION_TYPE_RECTANGLE = "Collision type/Rectangle (1)"
  3. const OPTION_TYPE_SPHERE = "Collision type/Sphere (2)"
  4. const OPTION_TYPE_CAPSULE = "Collision type/Capsule (3)"
  5. const OPTION_TYPE_CONVEX_POLYGON = "Collision type/Convex Polygon (4)"
  6. const OPTION_TYPE_CONCAVE_SEGMENTS = "Collision type/Concave Segments (5)"
  7. const OPTION_SHAPE_RECTANGLE = "Shape type/Rectangle"
  8. const OPTION_SHAPE_SPHERE = "Shape type/Sphere"
  9. const OPTION_SHAPE_CAPSULE = "Shape type/Capsule"
  10. const OPTION_SHAPE_CONVEX_POLYGON = "Shape type/Convex Polygon"
  11. const OPTION_SHAPE_CONCAVE_POLYGON = "Shape type/Concave Polygon"
  12. const OPTION_SHAPE_CONCAVE_SEGMENTS = "Shape type/Concave Segments"
  13. const OFFSET_RANGE = 120.0
  14. @export var offset = Vector2.ZERO
  15. @onready var options = $Options
  16. var _update_collision = false
  17. var _collision_test_index = 0
  18. var _current_offset = Vector2.ZERO
  19. var _collision_shapes = []
  20. func _ready():
  21. _initialize_collision_shapes()
  22. options.add_menu_item(OPTION_TYPE_RECTANGLE)
  23. options.add_menu_item(OPTION_TYPE_SPHERE)
  24. options.add_menu_item(OPTION_TYPE_CAPSULE)
  25. options.add_menu_item(OPTION_TYPE_CONVEX_POLYGON)
  26. options.add_menu_item(OPTION_TYPE_CONCAVE_SEGMENTS)
  27. options.add_menu_item(OPTION_SHAPE_RECTANGLE, true, true)
  28. options.add_menu_item(OPTION_SHAPE_SPHERE, true, true)
  29. options.add_menu_item(OPTION_SHAPE_CAPSULE, true, true)
  30. options.add_menu_item(OPTION_SHAPE_CONVEX_POLYGON, true, true)
  31. options.add_menu_item(OPTION_SHAPE_CONCAVE_POLYGON, true, true)
  32. options.add_menu_item(OPTION_SHAPE_CONCAVE_SEGMENTS, true, true)
  33. options.option_selected.connect(self._on_option_selected)
  34. options.option_changed.connect(self._on_option_changed)
  35. await start_timer(0.5).timeout
  36. if is_timer_canceled():
  37. return
  38. _update_collision = true
  39. func _input(event):
  40. var key_event = event as InputEventKey
  41. if key_event and not key_event.pressed:
  42. if key_event.keycode == KEY_1:
  43. _on_option_selected(OPTION_TYPE_RECTANGLE)
  44. elif key_event.keycode == KEY_2:
  45. _on_option_selected(OPTION_TYPE_SPHERE)
  46. elif key_event.keycode == KEY_3:
  47. _on_option_selected(OPTION_TYPE_CAPSULE)
  48. elif key_event.keycode == KEY_4:
  49. _on_option_selected(OPTION_TYPE_CONVEX_POLYGON)
  50. elif key_event.keycode == KEY_5:
  51. _on_option_selected(OPTION_TYPE_CONCAVE_SEGMENTS)
  52. func _physics_process(delta):
  53. super._physics_process(delta)
  54. if not _update_collision:
  55. return
  56. _update_collision = false
  57. _do_collision_test()
  58. func set_h_offset(value):
  59. offset.x = value * OFFSET_RANGE
  60. _update_collision = true
  61. func set_v_offset(value):
  62. offset.y = -value * OFFSET_RANGE
  63. _update_collision = true
  64. func _initialize_collision_shapes():
  65. _collision_shapes.clear()
  66. for node in $Shapes.get_children():
  67. var body = node as PhysicsBody2D
  68. var shape = body.shape_owner_get_shape(0, 0)
  69. shape.resource_name = String(node.name).substr("RigidBody".length())
  70. _collision_shapes.push_back(shape)
  71. func _do_collision_test():
  72. clear_drawn_nodes()
  73. var shape = _collision_shapes[_collision_test_index]
  74. Log.print_log("* Start %s collision tests..." % shape.resource_name)
  75. var shape_query = PhysicsShapeQueryParameters2D.new()
  76. shape_query.set_shape(shape)
  77. var shape_scale = Vector2(0.5, 0.5)
  78. shape_query.transform = Transform2D.IDENTITY.scaled(shape_scale)
  79. for node in $Shapes.get_children():
  80. if not node.visible:
  81. continue
  82. var body = node as PhysicsBody2D
  83. var space_state = body.get_world_2d().direct_space_state
  84. Log.print_log("* Testing: %s" % String(body.name))
  85. var center = body.position
  86. # Collision at the center inside.
  87. var res = _add_collision(space_state, center, shape, shape_query)
  88. Log.print_log("Collision center inside: %s" % ("NO HIT" if res.is_empty() else "HIT"))
  89. Log.print_log("* Done.")
  90. func _add_collision(space_state, pos, shape, shape_query):
  91. shape_query.transform.origin = pos + offset
  92. var results = space_state.collide_shape(shape_query)
  93. var color
  94. if results.is_empty():
  95. color = Color.WHITE.darkened(0.5)
  96. else:
  97. color = Color.GREEN
  98. # Draw collision query shape.
  99. add_shape(shape, shape_query.transform, color)
  100. # Draw contact positions.
  101. for contact_pos in results:
  102. add_circle(contact_pos, 1.0, Color.RED)
  103. return results
  104. func _on_option_selected(option):
  105. match option:
  106. OPTION_TYPE_RECTANGLE:
  107. _collision_test_index = _find_type_index("Rectangle")
  108. _update_collision = true
  109. OPTION_TYPE_SPHERE:
  110. _collision_test_index = _find_type_index("Sphere")
  111. _update_collision = true
  112. OPTION_TYPE_CAPSULE:
  113. _collision_test_index = _find_type_index("Capsule")
  114. _update_collision = true
  115. OPTION_TYPE_CONVEX_POLYGON:
  116. _collision_test_index = _find_type_index("ConvexPolygon")
  117. _update_collision = true
  118. OPTION_TYPE_CONCAVE_SEGMENTS:
  119. _collision_test_index = _find_type_index("ConcaveSegments")
  120. _update_collision = true
  121. func _find_type_index(type_name):
  122. for type_index in range(_collision_shapes.size()):
  123. var type_shape = _collision_shapes[type_index]
  124. if type_shape.resource_name.find(type_name) > -1:
  125. return type_index
  126. Log.print_error("Invalid collision type: " + type_name)
  127. return -1
  128. func _on_option_changed(option, checked):
  129. var node
  130. match option:
  131. OPTION_SHAPE_RECTANGLE:
  132. node = _find_shape_node("Rectangle")
  133. OPTION_SHAPE_SPHERE:
  134. node = _find_shape_node("Sphere")
  135. OPTION_SHAPE_CAPSULE:
  136. node = _find_shape_node("Capsule")
  137. OPTION_SHAPE_CONVEX_POLYGON:
  138. node = _find_shape_node("ConvexPolygon")
  139. OPTION_SHAPE_CONCAVE_POLYGON:
  140. node = _find_shape_node("ConcavePolygon")
  141. OPTION_SHAPE_CONCAVE_SEGMENTS:
  142. node = _find_shape_node("ConcaveSegments")
  143. if node:
  144. node.visible = checked
  145. node.get_child(0).disabled = not checked
  146. _update_collision = true
  147. func _find_shape_node(type_name):
  148. var node = $Shapes.find_child("RigidBody%s" % type_name)
  149. if not node:
  150. Log.print_error("Invalid shape type: " + type_name)
  151. return node