summaryrefslogtreecommitdiff
path: root/scene/2d/physics_body_2d.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/2d/physics_body_2d.cpp')
-rw-r--r--scene/2d/physics_body_2d.cpp157
1 files changed, 110 insertions, 47 deletions
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 41288d646f..b2cc8164b6 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -133,9 +133,12 @@ bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_linear
ERR_FAIL_COND_V(!is_inside_tree(), false);
PhysicsServer2D::MotionResult *r = nullptr;
+ PhysicsServer2D::MotionResult temp_result;
if (r_collision.is_valid()) {
// Needs const_cast because method bindings don't support non-const Ref.
r = const_cast<PhysicsServer2D::MotionResult *>(&r_collision->result);
+ } else {
+ r = &temp_result;
}
// Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky.
@@ -143,7 +146,14 @@ bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_linear
PhysicsServer2D::MotionParameters parameters(p_from, p_linear_velocity * delta, p_margin);
- return PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), parameters, r);
+ bool colliding = PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), parameters, r);
+
+ if (colliding) {
+ // Don't report collision when the whole motion is done.
+ return (r->collision_safe_fraction < 1.0);
+ } else {
+ return false;
+ }
}
TypedArray<PhysicsBody2D> PhysicsBody2D::get_collision_exceptions() {
@@ -684,6 +694,24 @@ real_t RigidDynamicBody2D::get_gravity_scale() const {
return gravity_scale;
}
+void RigidDynamicBody2D::set_linear_damp_mode(DampMode p_mode) {
+ linear_damp_mode = p_mode;
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_LINEAR_DAMP_MODE, linear_damp_mode);
+}
+
+RigidDynamicBody2D::DampMode RigidDynamicBody2D::get_linear_damp_mode() const {
+ return linear_damp_mode;
+}
+
+void RigidDynamicBody2D::set_angular_damp_mode(DampMode p_mode) {
+ angular_damp_mode = p_mode;
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP_MODE, angular_damp_mode);
+}
+
+RigidDynamicBody2D::DampMode RigidDynamicBody2D::get_angular_damp_mode() const {
+ return angular_damp_mode;
+}
+
void RigidDynamicBody2D::set_linear_damp(real_t p_linear_damp) {
ERR_FAIL_COND(p_linear_damp < -1);
linear_damp = p_linear_damp;
@@ -781,32 +809,44 @@ void RigidDynamicBody2D::apply_torque_impulse(real_t p_torque) {
PhysicsServer2D::get_singleton()->body_apply_torque_impulse(get_rid(), p_torque);
}
-void RigidDynamicBody2D::set_applied_force(const Vector2 &p_force) {
- PhysicsServer2D::get_singleton()->body_set_applied_force(get_rid(), p_force);
-};
+void RigidDynamicBody2D::apply_central_force(const Vector2 &p_force) {
+ PhysicsServer2D::get_singleton()->body_apply_central_force(get_rid(), p_force);
+}
-Vector2 RigidDynamicBody2D::get_applied_force() const {
- return PhysicsServer2D::get_singleton()->body_get_applied_force(get_rid());
-};
+void RigidDynamicBody2D::apply_force(const Vector2 &p_force, const Vector2 &p_position) {
+ PhysicsServer2D::get_singleton()->body_apply_force(get_rid(), p_force, p_position);
+}
-void RigidDynamicBody2D::set_applied_torque(const real_t p_torque) {
- PhysicsServer2D::get_singleton()->body_set_applied_torque(get_rid(), p_torque);
-};
+void RigidDynamicBody2D::apply_torque(real_t p_torque) {
+ PhysicsServer2D::get_singleton()->body_apply_torque(get_rid(), p_torque);
+}
-real_t RigidDynamicBody2D::get_applied_torque() const {
- return PhysicsServer2D::get_singleton()->body_get_applied_torque(get_rid());
-};
+void RigidDynamicBody2D::add_constant_central_force(const Vector2 &p_force) {
+ PhysicsServer2D::get_singleton()->body_add_constant_central_force(get_rid(), p_force);
+}
+
+void RigidDynamicBody2D::add_constant_force(const Vector2 &p_force, const Vector2 &p_position) {
+ PhysicsServer2D::get_singleton()->body_add_constant_force(get_rid(), p_force, p_position);
+}
+
+void RigidDynamicBody2D::add_constant_torque(const real_t p_torque) {
+ PhysicsServer2D::get_singleton()->body_add_constant_torque(get_rid(), p_torque);
+}
+
+void RigidDynamicBody2D::set_constant_force(const Vector2 &p_force) {
+ PhysicsServer2D::get_singleton()->body_set_constant_force(get_rid(), p_force);
+}
-void RigidDynamicBody2D::add_central_force(const Vector2 &p_force) {
- PhysicsServer2D::get_singleton()->body_add_central_force(get_rid(), p_force);
+Vector2 RigidDynamicBody2D::get_constant_force() const {
+ return PhysicsServer2D::get_singleton()->body_get_constant_force(get_rid());
}
-void RigidDynamicBody2D::add_force(const Vector2 &p_force, const Vector2 &p_position) {
- PhysicsServer2D::get_singleton()->body_add_force(get_rid(), p_force, p_position);
+void RigidDynamicBody2D::set_constant_torque(real_t p_torque) {
+ PhysicsServer2D::get_singleton()->body_set_constant_torque(get_rid(), p_torque);
}
-void RigidDynamicBody2D::add_torque(const real_t p_torque) {
- PhysicsServer2D::get_singleton()->body_add_torque(get_rid(), p_torque);
+real_t RigidDynamicBody2D::get_constant_torque() const {
+ return PhysicsServer2D::get_singleton()->body_get_constant_torque(get_rid());
}
void RigidDynamicBody2D::set_continuous_collision_detection_mode(CCDMode p_mode) {
@@ -916,6 +956,12 @@ void RigidDynamicBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidDynamicBody2D::set_gravity_scale);
ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidDynamicBody2D::get_gravity_scale);
+ ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &RigidDynamicBody2D::set_linear_damp_mode);
+ ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &RigidDynamicBody2D::get_linear_damp_mode);
+
+ ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &RigidDynamicBody2D::set_angular_damp_mode);
+ ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &RigidDynamicBody2D::get_angular_damp_mode);
+
ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &RigidDynamicBody2D::set_linear_damp);
ClassDB::bind_method(D_METHOD("get_linear_damp"), &RigidDynamicBody2D::get_linear_damp);
@@ -945,15 +991,19 @@ void RigidDynamicBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidDynamicBody2D::apply_impulse, Vector2());
ClassDB::bind_method(D_METHOD("apply_torque_impulse", "torque"), &RigidDynamicBody2D::apply_torque_impulse);
- ClassDB::bind_method(D_METHOD("set_applied_force", "force"), &RigidDynamicBody2D::set_applied_force);
- ClassDB::bind_method(D_METHOD("get_applied_force"), &RigidDynamicBody2D::get_applied_force);
+ ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &RigidDynamicBody2D::apply_central_force);
+ ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &RigidDynamicBody2D::apply_force, Vector2());
+ ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &RigidDynamicBody2D::apply_torque);
+
+ ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &RigidDynamicBody2D::add_constant_central_force);
+ ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &RigidDynamicBody2D::add_constant_force, Vector2());
+ ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &RigidDynamicBody2D::add_constant_torque);
- ClassDB::bind_method(D_METHOD("set_applied_torque", "torque"), &RigidDynamicBody2D::set_applied_torque);
- ClassDB::bind_method(D_METHOD("get_applied_torque"), &RigidDynamicBody2D::get_applied_torque);
+ ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &RigidDynamicBody2D::set_constant_force);
+ ClassDB::bind_method(D_METHOD("get_constant_force"), &RigidDynamicBody2D::get_constant_force);
- ClassDB::bind_method(D_METHOD("add_central_force", "force"), &RigidDynamicBody2D::add_central_force);
- ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &RigidDynamicBody2D::add_force, Vector2());
- ClassDB::bind_method(D_METHOD("add_torque", "torque"), &RigidDynamicBody2D::add_torque);
+ ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &RigidDynamicBody2D::set_constant_torque);
+ ClassDB::bind_method(D_METHOD("get_constant_torque"), &RigidDynamicBody2D::get_constant_torque);
ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidDynamicBody2D::set_sleeping);
ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidDynamicBody2D::is_sleeping);
@@ -992,13 +1042,15 @@ void RigidDynamicBody2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "freeze_mode", PROPERTY_HINT_ENUM, "Static,Kinematic"), "set_freeze_mode", "get_freeze_mode");
ADD_GROUP("Linear", "linear_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_linear_damp_mode", "get_linear_damp_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
ADD_GROUP("Angular", "angular_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_velocity"), "set_angular_velocity", "get_angular_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_angular_damp_mode", "get_angular_damp_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
- ADD_GROUP("Applied Forces", "applied_");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "applied_force"), "set_applied_force", "get_applied_force");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "applied_torque"), "set_applied_torque", "get_applied_torque");
+ ADD_GROUP("Constant Forces", "constant_");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_force"), "set_constant_force", "get_constant_force");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant_torque"), "set_constant_torque", "get_constant_torque");
ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
@@ -1012,6 +1064,9 @@ void RigidDynamicBody2D::_bind_methods() {
BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_AUTO);
BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_CUSTOM);
+ BIND_ENUM_CONSTANT(DAMP_MODE_COMBINE);
+ BIND_ENUM_CONSTANT(DAMP_MODE_REPLACE);
+
BIND_ENUM_CONSTANT(CCD_MODE_DISABLED);
BIND_ENUM_CONSTANT(CCD_MODE_CAST_RAY);
BIND_ENUM_CONSTANT(CCD_MODE_CAST_SHAPE);
@@ -1020,7 +1075,7 @@ void RigidDynamicBody2D::_bind_methods() {
void RigidDynamicBody2D::_validate_property(PropertyInfo &property) const {
if (center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM) {
if (property.name == "center_of_mass") {
- property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
+ property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
}
}
}
@@ -1072,6 +1127,10 @@ bool CharacterBody2D::move_and_slide() {
if (bs) {
Vector2 local_position = gt.elements[2] - bs->get_transform().elements[2];
current_platform_velocity = bs->get_velocity_at_local_position(local_position);
+ } else {
+ // Body is removed or destroyed, invalidate floor.
+ current_platform_velocity = Vector2();
+ platform_rid = RID();
}
} else {
current_platform_velocity = Vector2();
@@ -1101,7 +1160,7 @@ bool CharacterBody2D::move_and_slide() {
}
if (motion_mode == MOTION_MODE_GROUNDED) {
- _move_and_slide_grounded(delta, was_on_floor, current_platform_velocity);
+ _move_and_slide_grounded(delta, was_on_floor);
} else {
_move_and_slide_free(delta);
}
@@ -1122,14 +1181,11 @@ bool CharacterBody2D::move_and_slide() {
return motion_results.size() > 0;
}
-void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_floor, const Vector2 &p_prev_platform_velocity) {
+void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_floor) {
Vector2 motion = motion_velocity * p_delta;
Vector2 motion_slide_up = motion.slide(up_direction);
Vector2 prev_floor_normal = floor_normal;
- RID prev_platform_rid = platform_rid;
- ObjectID prev_platform_object_id = platform_object_id;
- int prev_platform_layer = platform_layer;
platform_rid = RID();
platform_object_id = ObjectID();
@@ -1202,12 +1258,8 @@ void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
gt.elements[2] -= result.travel;
set_global_transform(gt);
}
- on_floor = true;
- platform_rid = prev_platform_rid;
- platform_object_id = prev_platform_object_id;
- platform_layer = prev_platform_layer;
- platform_velocity = p_prev_platform_velocity;
- floor_normal = prev_floor_normal;
+ // Determines if you are on the ground.
+ _snap_on_floor(true, false);
motion_velocity = Vector2();
last_motion = Vector2();
motion = Vector2();
@@ -1281,6 +1333,17 @@ void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
_snap_on_floor(p_was_on_floor, vel_dir_facing_up);
+ // Scales the horizontal velocity according to the wall slope.
+ if (is_on_wall_only() && motion_slide_up.dot(motion_results.get(0).collision_normal) < 0) {
+ Vector2 slide_motion = motion_velocity.slide(motion_results.get(0).collision_normal);
+ if (motion_slide_up.dot(slide_motion) < 0) {
+ motion_velocity = up_direction * up_direction.dot(motion_velocity);
+ } else {
+ // Keeps the vertical motion from motion_velocity and add the horizontal motion of the projection.
+ motion_velocity = up_direction * up_direction.dot(motion_velocity) + slide_motion.slide(up_direction);
+ }
+ }
+
// Reset the gravity accumulation when touching the ground.
if (on_floor && !vel_dir_facing_up) {
motion_velocity = motion_velocity.slide(up_direction);
@@ -1693,9 +1756,9 @@ void CharacterBody2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_mode", PROPERTY_HINT_ENUM, "Grounded,Free", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_motion_mode", "get_motion_mode");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "up_direction"), "set_up_direction", "get_up_direction");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion_velocity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_motion_velocity", "get_motion_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion_velocity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_motion_velocity", "get_motion_velocity");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_ceiling"), "set_slide_on_ceiling_enabled", "is_slide_on_ceiling_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_max_slides", "get_max_slides");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_slides", "get_max_slides");
ADD_GROUP("Free Mode", "free_mode_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "free_mode_min_slide_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians", PROPERTY_USAGE_DEFAULT), "set_free_mode_min_slide_angle", "get_free_mode_min_slide_angle");
@@ -1722,11 +1785,11 @@ void CharacterBody2D::_bind_methods() {
void CharacterBody2D::_validate_property(PropertyInfo &property) const {
if (motion_mode == MOTION_MODE_FREE) {
if (property.name.begins_with("floor_") || property.name == "up_direction" || property.name == "slide_on_ceiling") {
- property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
+ property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
}
} else {
if (property.name == "free_mode_min_slide_angle") {
- property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
+ property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
}
}
}