Properties for move_and_slide and remove move_and_slide_with_snap
- snap property to replace move_and_slide_with_snap() - floor_max_angle, stop_on_slope, infinite_inertia, max_slides, up_direction properties to replace arguments from move_and_slide() - up direction now defaults to Vector3.UP and Vector2.UP
This commit is contained in:
@@ -856,10 +856,11 @@ void RigidBody2D::_reload_physics_characteristics() {
|
||||
//so, if you pass 45 as limit, avoid numerical precision errors when angle is 45.
|
||||
#define FLOOR_ANGLE_THRESHOLD 0.01
|
||||
|
||||
Vector2 CharacterBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_up_direction, bool p_stop_on_slope, int p_max_slides, real_t p_floor_max_angle, bool p_infinite_inertia) {
|
||||
Vector2 CharacterBody2D::move_and_slide(const Vector2 &p_linear_velocity) {
|
||||
Vector2 body_velocity = p_linear_velocity;
|
||||
Vector2 body_velocity_normal = body_velocity.normalized();
|
||||
Vector2 up_direction = p_up_direction.normalized();
|
||||
|
||||
bool was_on_floor = on_floor;
|
||||
|
||||
Vector2 current_floor_velocity = floor_velocity;
|
||||
if (on_floor && on_floor_body.is_valid()) {
|
||||
@@ -881,19 +882,20 @@ Vector2 CharacterBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
|
||||
floor_normal = Vector2();
|
||||
floor_velocity = Vector2();
|
||||
|
||||
while (p_max_slides) {
|
||||
int slide_count = max_slides;
|
||||
while (slide_count) {
|
||||
PhysicsServer2D::MotionResult result;
|
||||
bool found_collision = false;
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
bool collided;
|
||||
if (i == 0) { //collide
|
||||
collided = move_and_collide(motion, p_infinite_inertia, result);
|
||||
collided = move_and_collide(motion, infinite_inertia, result);
|
||||
if (!collided) {
|
||||
motion = Vector2(); //clear because no collision happened and motion completed
|
||||
}
|
||||
} else { //separate raycasts (if any)
|
||||
collided = separate_raycast_shapes(p_infinite_inertia, result);
|
||||
collided = separate_raycast_shapes(result);
|
||||
if (collided) {
|
||||
result.remainder = motion; //keep
|
||||
result.motion = Vector2();
|
||||
@@ -910,14 +912,14 @@ Vector2 CharacterBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
|
||||
//all is a wall
|
||||
on_wall = true;
|
||||
} else {
|
||||
if (Math::acos(result.collision_normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
|
||||
if (Math::acos(result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
|
||||
|
||||
on_floor = true;
|
||||
floor_normal = result.collision_normal;
|
||||
on_floor_body = result.collider;
|
||||
floor_velocity = result.collider_velocity;
|
||||
|
||||
if (p_stop_on_slope) {
|
||||
if (stop_on_slope) {
|
||||
if ((body_velocity_normal + up_direction).length() < 0.01 && result.motion.length() < 1) {
|
||||
Transform2D gt = get_global_transform();
|
||||
gt.elements[2] -= result.motion.slide(up_direction);
|
||||
@@ -925,7 +927,7 @@ Vector2 CharacterBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
|
||||
return Vector2();
|
||||
}
|
||||
}
|
||||
} else if (Math::acos(result.collision_normal.dot(-up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
|
||||
} else if (Math::acos(result.collision_normal.dot(-up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
|
||||
on_ceiling = true;
|
||||
} else {
|
||||
on_wall = true;
|
||||
@@ -941,33 +943,25 @@ Vector2 CharacterBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
|
||||
break;
|
||||
}
|
||||
|
||||
--p_max_slides;
|
||||
--slide_count;
|
||||
}
|
||||
|
||||
return body_velocity;
|
||||
}
|
||||
|
||||
Vector2 CharacterBody2D::move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_up_direction, bool p_stop_on_slope, int p_max_slides, real_t p_floor_max_angle, bool p_infinite_inertia) {
|
||||
Vector2 up_direction = p_up_direction.normalized();
|
||||
bool was_on_floor = on_floor;
|
||||
|
||||
Vector2 ret = move_and_slide(p_linear_velocity, up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia);
|
||||
if (!was_on_floor || p_snap == Vector2()) {
|
||||
return ret;
|
||||
if (!was_on_floor || snap == Vector2()) {
|
||||
return body_velocity;
|
||||
}
|
||||
|
||||
PhysicsServer2D::MotionResult result;
|
||||
// Apply snap.
|
||||
Transform2D gt = get_global_transform();
|
||||
|
||||
if (move_and_collide(p_snap, p_infinite_inertia, result, false, true)) {
|
||||
PhysicsServer2D::MotionResult result;
|
||||
if (move_and_collide(snap, infinite_inertia, result, false, true)) {
|
||||
bool apply = true;
|
||||
if (up_direction != Vector2()) {
|
||||
if (Math::acos(result.collision_normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
|
||||
if (Math::acos(result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
|
||||
on_floor = true;
|
||||
floor_normal = result.collision_normal;
|
||||
on_floor_body = result.collider;
|
||||
floor_velocity = result.collider_velocity;
|
||||
if (p_stop_on_slope) {
|
||||
if (stop_on_slope) {
|
||||
// move and collide may stray the object a bit because of pre un-stucking,
|
||||
// so only ensure that motion happens on floor direction in this case.
|
||||
result.motion = up_direction * up_direction.dot(result.motion);
|
||||
@@ -984,7 +978,7 @@ Vector2 CharacterBody2D::move_and_slide_with_snap(const Vector2 &p_linear_veloci
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return body_velocity;
|
||||
}
|
||||
|
||||
bool CharacterBody2D::separate_raycast_shapes(PhysicsServer2D::MotionResult &r_result) {
|
||||
@@ -1106,6 +1100,54 @@ void CharacterBody2D::_direct_state_changed(Object *p_state) {
|
||||
set_notify_local_transform(true);
|
||||
}
|
||||
|
||||
bool CharacterBody2D::is_stop_on_slope_enabled() const {
|
||||
return stop_on_slope;
|
||||
}
|
||||
|
||||
void CharacterBody2D::set_stop_on_slope_enabled(bool p_enabled) {
|
||||
stop_on_slope = p_enabled;
|
||||
}
|
||||
|
||||
bool CharacterBody2D::is_infinite_inertia_enabled() const {
|
||||
return infinite_inertia;
|
||||
}
|
||||
void CharacterBody2D::set_infinite_inertia_enabled(bool p_enabled) {
|
||||
infinite_inertia = p_enabled;
|
||||
}
|
||||
|
||||
int CharacterBody2D::get_max_slides() const {
|
||||
return max_slides;
|
||||
}
|
||||
|
||||
void CharacterBody2D::set_max_slides(int p_max_slides) {
|
||||
ERR_FAIL_COND(p_max_slides > 0);
|
||||
max_slides = p_max_slides;
|
||||
}
|
||||
|
||||
real_t CharacterBody2D::get_floor_max_angle() const {
|
||||
return floor_max_angle;
|
||||
}
|
||||
|
||||
void CharacterBody2D::set_floor_max_angle(real_t p_floor_max_angle) {
|
||||
floor_max_angle = p_floor_max_angle;
|
||||
}
|
||||
|
||||
const Vector2 &CharacterBody2D::get_snap() const {
|
||||
return snap;
|
||||
}
|
||||
|
||||
void CharacterBody2D::set_snap(const Vector2 &p_snap) {
|
||||
snap = p_snap;
|
||||
}
|
||||
|
||||
const Vector2 &CharacterBody2D::get_up_direction() const {
|
||||
return up_direction;
|
||||
}
|
||||
|
||||
void CharacterBody2D::set_up_direction(const Vector2 &p_up_direction) {
|
||||
up_direction = p_up_direction.normalized();
|
||||
}
|
||||
|
||||
void CharacterBody2D::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_ENTER_TREE) {
|
||||
last_valid_transform = get_global_transform();
|
||||
@@ -1131,8 +1173,20 @@ void CharacterBody2D::_notification(int p_what) {
|
||||
}
|
||||
|
||||
void CharacterBody2D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &CharacterBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((real_t)45.0)), DEFVAL(true));
|
||||
ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &CharacterBody2D::move_and_slide_with_snap, DEFVAL(Vector2(0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((real_t)45.0)), DEFVAL(true));
|
||||
ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity"), &CharacterBody2D::move_and_slide);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("is_stop_on_slope_enabled"), &CharacterBody2D::is_stop_on_slope_enabled);
|
||||
ClassDB::bind_method(D_METHOD("set_stop_on_slope_enabled", "enabled"), &CharacterBody2D::set_stop_on_slope_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_infinite_inertia_enabled"), &CharacterBody2D::is_infinite_inertia_enabled);
|
||||
ClassDB::bind_method(D_METHOD("set_infinite_inertia_enabled", "enabled"), &CharacterBody2D::set_infinite_inertia_enabled);
|
||||
ClassDB::bind_method(D_METHOD("get_max_slides"), &CharacterBody2D::get_max_slides);
|
||||
ClassDB::bind_method(D_METHOD("set_max_slides", "max_slides"), &CharacterBody2D::set_max_slides);
|
||||
ClassDB::bind_method(D_METHOD("get_floor_max_angle"), &CharacterBody2D::get_floor_max_angle);
|
||||
ClassDB::bind_method(D_METHOD("set_floor_max_angle", "floor_max_angle"), &CharacterBody2D::set_floor_max_angle);
|
||||
ClassDB::bind_method(D_METHOD("get_snap"), &CharacterBody2D::get_snap);
|
||||
ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CharacterBody2D::set_snap);
|
||||
ClassDB::bind_method(D_METHOD("get_up_direction"), &CharacterBody2D::get_up_direction);
|
||||
ClassDB::bind_method(D_METHOD("set_up_direction", "up_direction"), &CharacterBody2D::set_up_direction);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("is_on_floor"), &CharacterBody2D::is_on_floor);
|
||||
ClassDB::bind_method(D_METHOD("is_on_ceiling"), &CharacterBody2D::is_on_ceiling);
|
||||
@@ -1145,6 +1199,13 @@ void CharacterBody2D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &CharacterBody2D::set_sync_to_physics);
|
||||
ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &CharacterBody2D::is_sync_to_physics_enabled);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stop_on_slope"), "set_stop_on_slope_enabled", "is_stop_on_slope_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "infinite_inertia"), "set_infinite_inertia_enabled", "is_infinite_inertia_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides"), "set_max_slides", "get_max_slides");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle"), "set_floor_max_angle", "get_floor_max_angle");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "snap"), "set_snap", "get_snap");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "up_direction"), "set_up_direction", "get_up_direction");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "motion/sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user