-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add One Way Collision for 2D Physics tests
- Loading branch information
1 parent
289d658
commit b4cae9e
Showing
6 changed files
with
557 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
277 changes: 277 additions & 0 deletions
277
2d/physics_tests/tests/functional/test_one_way_collision.gd
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,277 @@ | ||
extends Test | ||
tool | ||
|
||
const OPTION_OBJECT_TYPE_RIGIDBODY = "Object type/Rigid body (1)" | ||
const OPTION_OBJECT_TYPE_KINEMATIC = "Object type/Kinematic body (2)" | ||
|
||
const OPTION_TEST_CASE_ALL_ANGLES = "Test case/Around the clock (0)" | ||
|
||
const TEST_ALL_ANGLES_STEP = 15.0 | ||
const TEST_ALL_ANGLES_MAX = 344.0 | ||
|
||
export(float, 32, 128, 0.1) var _platform_size = 64.0 setget _set_platform_size | ||
export(float, 0, 360, 0.1) var _platform_angle = 0.0 setget _set_platform_angle | ||
export(float, 0, 360, 0.1) var _body_angle = 0.0 setget _set_rigidbody_angle | ||
export(Vector2) var _body_velocity = Vector2(400.0, 0.0) | ||
export(bool) var _use_kinematic_body = false | ||
|
||
var _rigid_body_template = null | ||
var _kinematic_body_template = null | ||
var _moving_body = null | ||
|
||
var _contact_detected = false | ||
var _target_entered = false | ||
var _test_passed = false | ||
var _test_step = 0 | ||
|
||
var _test_all_angles = false | ||
var _lock_controls = false | ||
|
||
|
||
func _ready(): | ||
if not Engine.editor_hint: | ||
$Options.add_menu_item(OPTION_OBJECT_TYPE_RIGIDBODY, true, not _use_kinematic_body, true) | ||
$Options.add_menu_item(OPTION_OBJECT_TYPE_KINEMATIC, true, _use_kinematic_body, true) | ||
|
||
$Options.add_menu_item(OPTION_TEST_CASE_ALL_ANGLES) | ||
|
||
$Options.connect("option_selected", self, "_on_option_selected") | ||
|
||
$Controls/PlatformSize/HSlider.value = _platform_size | ||
$Controls/PlatformAngle/HSlider.value = _platform_angle | ||
$Controls/BodyAngle/HSlider.value = _body_angle | ||
|
||
$TargetArea2D.connect("body_entered", self, "_on_target_entered") | ||
$Timer.connect("timeout", self, "_on_timeout") | ||
|
||
_rigid_body_template = $RigidBody2D | ||
remove_child(_rigid_body_template) | ||
|
||
_kinematic_body_template = $KinematicBody2D | ||
remove_child(_kinematic_body_template) | ||
|
||
_start_test() | ||
|
||
|
||
func _process(_delta): | ||
if not Engine.editor_hint: | ||
if Input.is_action_just_pressed("ui_accept"): | ||
_reset_test(false) | ||
|
||
|
||
func _physics_process(_delta): | ||
if not Engine.editor_hint: | ||
if _moving_body and _use_kinematic_body: | ||
_moving_body.move_and_slide(_body_velocity) | ||
if _moving_body.get_slide_count() > 0: | ||
var colliding_body = _moving_body.get_slide_collision(0).collider | ||
_on_contact_detected(colliding_body) | ||
|
||
|
||
func _input(event): | ||
var key_event = event as InputEventKey | ||
if key_event and not key_event.pressed: | ||
if key_event.scancode == KEY_0: | ||
_on_option_selected(OPTION_TEST_CASE_ALL_ANGLES) | ||
if key_event.scancode == KEY_1: | ||
_on_option_selected(OPTION_OBJECT_TYPE_RIGIDBODY) | ||
elif key_event.scancode == KEY_2: | ||
_on_option_selected(OPTION_OBJECT_TYPE_KINEMATIC) | ||
|
||
|
||
func _exit_tree(): | ||
if not Engine.editor_hint: | ||
_rigid_body_template.free() | ||
_kinematic_body_template.free() | ||
|
||
|
||
func _set_platform_size(value): | ||
if _lock_controls: | ||
return | ||
if value == _platform_size: | ||
return | ||
_platform_size = value | ||
if is_inside_tree(): | ||
$OneWayRigidBody2D/CollisionShape2D.shape.extents.x = value | ||
|
||
if not Engine.editor_hint: | ||
# Bug: need to re-add when changing shape. | ||
var platform = $OneWayRigidBody2D | ||
var child_index = platform.get_index() | ||
remove_child(platform) | ||
add_child(platform) | ||
move_child(platform, child_index) | ||
|
||
_reset_test() | ||
|
||
|
||
func _set_platform_angle(value): | ||
if _lock_controls: | ||
return | ||
if value == _platform_angle: | ||
return | ||
_platform_angle = value | ||
if is_inside_tree(): | ||
$OneWayRigidBody2D.rotation = deg2rad(value) | ||
if not Engine.editor_hint: | ||
_reset_test() | ||
|
||
|
||
func _set_rigidbody_angle(value): | ||
if _lock_controls: | ||
return | ||
if value == _body_angle: | ||
return | ||
_body_angle = value | ||
if is_inside_tree(): | ||
if Engine.editor_hint: | ||
$RigidBody2D.rotation = deg2rad(value) | ||
$KinematicBody2D.rotation = deg2rad(value) | ||
else: | ||
if _moving_body: | ||
_moving_body.rotation = deg2rad(value) | ||
_rigid_body_template.rotation = deg2rad(value) | ||
_kinematic_body_template.rotation = deg2rad(value) | ||
_reset_test() | ||
|
||
|
||
func _on_option_selected(option): | ||
match option: | ||
OPTION_OBJECT_TYPE_KINEMATIC: | ||
_use_kinematic_body = true | ||
_reset_test() | ||
OPTION_OBJECT_TYPE_RIGIDBODY: | ||
_use_kinematic_body = false | ||
_reset_test() | ||
OPTION_TEST_CASE_ALL_ANGLES: | ||
_test_all_angles = true | ||
_reset_test(false) | ||
|
||
|
||
func _start_test(): | ||
var test_label = "Testing: " | ||
|
||
if _use_kinematic_body: | ||
test_label += _kinematic_body_template.name | ||
_moving_body = _kinematic_body_template.duplicate() | ||
else: | ||
test_label += _rigid_body_template.name | ||
_moving_body = _rigid_body_template.duplicate() | ||
_moving_body.linear_velocity = _body_velocity | ||
_moving_body.connect("body_entered", self, "_on_contact_detected") | ||
add_child(_moving_body) | ||
|
||
if _test_all_angles: | ||
test_label += " - All angles" | ||
|
||
$LabelTestType.text = test_label | ||
|
||
_contact_detected = false | ||
_target_entered = false | ||
_test_passed = false | ||
_test_step += 1 | ||
|
||
$Timer.start() | ||
|
||
$LabelResult.text = "..." | ||
$LabelResult.self_modulate = Color.white | ||
|
||
|
||
func _reset_test(cancel_test = true): | ||
$Timer.stop() | ||
|
||
_test_step = 0 | ||
|
||
if _test_all_angles: | ||
if cancel_test: | ||
Log.print_log("*** Stop around the clock tests") | ||
_test_all_angles = false | ||
else: | ||
Log.print_log("*** Start around the clock tests") | ||
$OneWayRigidBody2D.rotation = deg2rad(_platform_angle) | ||
_lock_controls = true | ||
$Controls/PlatformAngle/HSlider.value = _platform_angle | ||
_lock_controls = false | ||
|
||
_next_test(true) | ||
|
||
|
||
func _next_test(force_start = false): | ||
if _moving_body: | ||
remove_child(_moving_body) | ||
_moving_body.queue_free() | ||
_moving_body = null | ||
|
||
if _test_all_angles: | ||
var angle = rad2deg($OneWayRigidBody2D.rotation) | ||
if angle >= _platform_angle + TEST_ALL_ANGLES_MAX: | ||
$OneWayRigidBody2D.rotation = deg2rad(_platform_angle) | ||
_lock_controls = true | ||
$Controls/PlatformAngle/HSlider.value = _platform_angle | ||
_lock_controls = false | ||
Log.print_log("*** Done all angles") | ||
else: | ||
angle = _platform_angle + _test_step * TEST_ALL_ANGLES_STEP | ||
$OneWayRigidBody2D.rotation = deg2rad(angle) | ||
_lock_controls = true | ||
$Controls/PlatformAngle/HSlider.value = angle | ||
_lock_controls = false | ||
_start_test() | ||
elif force_start: | ||
_start_test() | ||
|
||
|
||
func _on_contact_detected(_body): | ||
if _contact_detected or _target_entered: | ||
return | ||
|
||
_contact_detected = true | ||
_test_passed = _should_collide() | ||
_set_result() | ||
_on_timeout() | ||
|
||
|
||
func _on_target_entered(_body): | ||
if _contact_detected or _target_entered: | ||
return | ||
|
||
_target_entered = true | ||
_test_passed = not _should_collide() | ||
_set_result() | ||
_on_timeout() | ||
|
||
|
||
func _should_collide(): | ||
var platform_rotation = round(rad2deg($OneWayRigidBody2D.rotation)) | ||
|
||
var angle = fposmod(platform_rotation, 360) | ||
return angle > 180 | ||
|
||
|
||
func _on_timeout(): | ||
if not _contact_detected and not _target_entered: | ||
Log.print_log("Test TIMEOUT") | ||
_set_result() | ||
|
||
$Timer.stop() | ||
|
||
yield(get_tree().create_timer(0.5), "timeout") | ||
|
||
_next_test() | ||
|
||
|
||
func _set_result(): | ||
var result = "" | ||
if _test_passed: | ||
result = "PASSED" | ||
$LabelResult.self_modulate = Color.green | ||
else: | ||
result = "FAILED" | ||
$LabelResult.self_modulate = Color.red | ||
|
||
$LabelResult.text = result | ||
|
||
var platform_angle = rad2deg($OneWayRigidBody2D.rotation) | ||
|
||
result += ": size=%.1f, angle=%.1f, body angle=%.1f" % [_platform_size, platform_angle, _body_angle] | ||
Log.print_log("Test %s" % result) |
Oops, something went wrong.