Add properties to CharacterBody for more move_and_slide options
This commit is contained in:
parent
50d5569ad4
commit
c6666cc051
3 changed files with 344 additions and 108 deletions
|
|
@ -69,7 +69,6 @@ Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_motion, bool p_i
|
|||
}
|
||||
|
||||
motion_cache->result = result;
|
||||
|
||||
return motion_cache;
|
||||
}
|
||||
|
||||
|
|
@ -1046,139 +1045,240 @@ void RigidBody2D::_reload_physics_characteristics() {
|
|||
|
||||
//////////////////////////
|
||||
|
||||
//so, if you pass 45 as limit, avoid numerical precision errors when angle is 45.
|
||||
// So, if you pass 45 as limit, avoid numerical precision errors when angle is 45.
|
||||
#define FLOOR_ANGLE_THRESHOLD 0.01
|
||||
|
||||
void CharacterBody2D::move_and_slide() {
|
||||
Vector2 body_velocity_normal = linear_velocity.normalized();
|
||||
bool was_on_floor = on_floor;
|
||||
|
||||
// Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky
|
||||
// Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky.
|
||||
float delta = Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time();
|
||||
|
||||
Vector2 current_floor_velocity = floor_velocity;
|
||||
Vector2 current_platform_velocity = platform_velocity;
|
||||
|
||||
if ((on_floor || on_wall) && on_floor_body.is_valid()) {
|
||||
//this approach makes sure there is less delay between the actual body velocity and the one we saved
|
||||
PhysicsDirectBodyState2D *bs = PhysicsServer2D::get_singleton()->body_get_direct_state(on_floor_body);
|
||||
if (bs) {
|
||||
Transform2D gt = get_global_transform();
|
||||
Vector2 local_position = gt.elements[2] - bs->get_transform().elements[2];
|
||||
current_floor_velocity = bs->get_velocity_at_local_position(local_position);
|
||||
if ((on_floor || on_wall) && platform_rid.is_valid()) {
|
||||
bool excluded = (exclude_body_layers & platform_layer) != 0;
|
||||
if (!excluded) {
|
||||
// This approach makes sure there is less delay between the actual body velocity and the one we saved.
|
||||
PhysicsDirectBodyState2D *bs = PhysicsServer2D::get_singleton()->body_get_direct_state(platform_rid);
|
||||
if (bs) {
|
||||
Transform2D gt = get_global_transform();
|
||||
Vector2 local_position = gt.elements[2] - bs->get_transform().elements[2];
|
||||
current_platform_velocity = bs->get_velocity_at_local_position(local_position);
|
||||
}
|
||||
} else {
|
||||
current_platform_velocity = Vector2();
|
||||
}
|
||||
}
|
||||
|
||||
motion_results.clear();
|
||||
|
||||
bool was_on_floor = on_floor;
|
||||
on_floor = false;
|
||||
on_ceiling = false;
|
||||
on_wall = false;
|
||||
floor_normal = Vector2();
|
||||
floor_velocity = Vector2();
|
||||
|
||||
if (current_floor_velocity != Vector2() && on_floor_body.is_valid()) {
|
||||
if (!current_platform_velocity.is_equal_approx(Vector2())) {
|
||||
PhysicsServer2D::MotionResult floor_result;
|
||||
Set<RID> exclude;
|
||||
exclude.insert(on_floor_body);
|
||||
if (move_and_collide(current_floor_velocity * delta, infinite_inertia, floor_result, true, false, false, false, exclude)) {
|
||||
exclude.insert(platform_rid);
|
||||
if (move_and_collide(current_platform_velocity * delta, infinite_inertia, floor_result, true, false, false, false, exclude)) {
|
||||
motion_results.push_back(floor_result);
|
||||
_set_collision_direction(floor_result);
|
||||
}
|
||||
}
|
||||
|
||||
on_floor_body = RID();
|
||||
Vector2 motion = linear_velocity * delta;
|
||||
Vector2 motion_slide_up = motion.slide(up_direction);
|
||||
|
||||
Vector2 prev_platform_velocity = current_platform_velocity;
|
||||
Vector2 prev_floor_normal = floor_normal;
|
||||
RID prev_platform_rid = platform_rid;
|
||||
int prev_platform_layer = platform_layer;
|
||||
|
||||
platform_rid = RID();
|
||||
floor_normal = Vector2();
|
||||
platform_velocity = Vector2();
|
||||
|
||||
// No sliding on first attempt to keep floor motion stable when possible,
|
||||
// when stop on slope is enabled.
|
||||
bool sliding_enabled = !stop_on_slope;
|
||||
// When stop on slope is enabled or when there is no up direction.
|
||||
bool sliding_enabled = !stop_on_slope || up_direction == Vector2();
|
||||
// Constant speed can be applied only the first time sliding is enabled.
|
||||
bool can_apply_constant_speed = sliding_enabled;
|
||||
bool first_slide = true;
|
||||
bool vel_dir_facing_up = linear_velocity.dot(up_direction) > 0;
|
||||
Vector2 last_travel;
|
||||
|
||||
for (int iteration = 0; iteration < max_slides; ++iteration) {
|
||||
PhysicsServer2D::MotionResult result;
|
||||
bool found_collision = false;
|
||||
|
||||
Vector2 prev_position = get_global_transform().elements[2];
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
bool collided;
|
||||
if (i == 0) { //collide
|
||||
if (i == 0) { // Collide.
|
||||
collided = move_and_collide(motion, infinite_inertia, result, margin, true, false, !sliding_enabled);
|
||||
if (!collided) {
|
||||
motion = Vector2(); //clear because no collision happened and motion completed
|
||||
}
|
||||
} else { //separate raycasts (if any)
|
||||
} else { // Separate raycasts (if any).
|
||||
collided = separate_raycast_shapes(result);
|
||||
if (collided) {
|
||||
result.remainder = motion; //keep
|
||||
result.remainder = motion; // Keep.
|
||||
result.motion = Vector2();
|
||||
}
|
||||
}
|
||||
|
||||
if (collided) {
|
||||
found_collision = true;
|
||||
|
||||
motion_results.push_back(result);
|
||||
_set_collision_direction(result);
|
||||
|
||||
if (on_floor && stop_on_slope) {
|
||||
if ((body_velocity_normal + up_direction).length() < 0.01) {
|
||||
Transform2D gt = get_global_transform();
|
||||
if (result.motion.length() > margin) {
|
||||
gt.elements[2] -= result.motion.slide(up_direction);
|
||||
} else {
|
||||
if (on_floor && stop_on_slope && (linear_velocity.normalized() + up_direction).length() < 0.01) {
|
||||
Transform2D gt = get_global_transform();
|
||||
if (result.motion.length() > margin) {
|
||||
gt.elements[2] -= result.motion.slide(up_direction);
|
||||
} else {
|
||||
gt.elements[2] -= result.motion;
|
||||
}
|
||||
set_global_transform(gt);
|
||||
linear_velocity = Vector2();
|
||||
motion = Vector2();
|
||||
break;
|
||||
}
|
||||
|
||||
if (result.remainder.is_equal_approx(Vector2())) {
|
||||
motion = Vector2();
|
||||
break;
|
||||
}
|
||||
|
||||
// Move on floor only checks.
|
||||
if (move_on_floor_only && on_wall && motion_slide_up.dot(result.collision_normal) <= 0) {
|
||||
// Avoid to move forward on a wall if move_on_floor_only is true.
|
||||
if (was_on_floor && !is_on_floor_only() && !vel_dir_facing_up) {
|
||||
// If the movement is large the body can be prevented from reaching the walls.
|
||||
if (result.motion.length() <= margin) {
|
||||
// Cancels the motion.
|
||||
Transform2D gt = get_global_transform();
|
||||
gt.elements[2] -= result.motion;
|
||||
set_global_transform(gt);
|
||||
}
|
||||
set_global_transform(gt);
|
||||
on_floor = true;
|
||||
platform_rid = prev_platform_rid;
|
||||
platform_layer = prev_platform_layer;
|
||||
|
||||
platform_velocity = prev_platform_velocity;
|
||||
floor_normal = prev_floor_normal;
|
||||
linear_velocity = Vector2();
|
||||
return;
|
||||
motion = Vector2();
|
||||
break;
|
||||
}
|
||||
// Prevents the body from being able to climb a slope when it moves forward against the wall.
|
||||
else if (!is_on_floor_only()) {
|
||||
motion = up_direction * up_direction.dot(result.remainder);
|
||||
motion = motion.slide(result.collision_normal);
|
||||
} else {
|
||||
motion = result.remainder;
|
||||
}
|
||||
}
|
||||
// Constant Speed when the slope is upward.
|
||||
else if (constant_speed_on_floor && is_on_floor_only() && can_apply_constant_speed && was_on_floor && motion.dot(result.collision_normal) < 0) {
|
||||
can_apply_constant_speed = false;
|
||||
Vector2 motion_slide_norm = result.remainder.slide(result.collision_normal).normalized();
|
||||
if (!motion_slide_norm.is_equal_approx(Vector2())) {
|
||||
motion = motion_slide_norm * (motion_slide_up.length() - result.motion.slide(up_direction).length() - last_travel.slide(up_direction).length());
|
||||
}
|
||||
}
|
||||
// Regular sliding, the last part of the test handle the case when you don't want to slide on the ceiling.
|
||||
else if ((sliding_enabled || !on_floor) && (!on_ceiling || slide_on_ceiling || !vel_dir_facing_up)) {
|
||||
Vector2 slide_motion = result.remainder.slide(result.collision_normal);
|
||||
if (slide_motion.dot(linear_velocity) > 0.0) {
|
||||
motion = slide_motion;
|
||||
} else {
|
||||
motion = Vector2();
|
||||
}
|
||||
if (slide_on_ceiling && on_ceiling) {
|
||||
// Apply slide only in the direction of the input motion, otherwise just stop to avoid jittering when moving against a wall.
|
||||
if (vel_dir_facing_up) {
|
||||
linear_velocity = linear_velocity.slide(result.collision_normal);
|
||||
} else {
|
||||
// Avoid acceleration in slope when falling.
|
||||
linear_velocity = up_direction * up_direction.dot(linear_velocity);
|
||||
}
|
||||
}
|
||||
}
|
||||
// No sliding on first attempt to keep floor motion stable when possible.
|
||||
else {
|
||||
motion = result.remainder;
|
||||
if (on_ceiling && !slide_on_ceiling && vel_dir_facing_up) {
|
||||
linear_velocity = linear_velocity.slide(up_direction);
|
||||
motion = motion.slide(up_direction);
|
||||
}
|
||||
}
|
||||
|
||||
if (sliding_enabled || !on_floor) {
|
||||
motion = result.remainder.slide(result.collision_normal);
|
||||
linear_velocity = linear_velocity.slide(result.collision_normal);
|
||||
} else {
|
||||
motion = result.remainder;
|
||||
last_travel = result.motion;
|
||||
}
|
||||
// When you move forward in a downward slope you don’t collide because you will be in the air.
|
||||
// This test ensures that constant speed is applied, only if the player is still on the ground after the snap is applied.
|
||||
else if (i == 0 && constant_speed_on_floor && first_slide && _on_floor_if_snapped(was_on_floor, vel_dir_facing_up)) {
|
||||
can_apply_constant_speed = false;
|
||||
sliding_enabled = true;
|
||||
Transform2D gt = get_global_transform();
|
||||
gt.elements[2] = prev_position;
|
||||
set_global_transform(gt);
|
||||
|
||||
Vector2 motion_slide_norm = motion.slide(prev_floor_normal).normalized();
|
||||
if (!motion_slide_norm.is_equal_approx(Vector2())) {
|
||||
motion = motion_slide_norm * (motion_slide_up.length());
|
||||
found_collision = true;
|
||||
}
|
||||
}
|
||||
|
||||
sliding_enabled = true;
|
||||
}
|
||||
can_apply_constant_speed = !can_apply_constant_speed && !sliding_enabled;
|
||||
sliding_enabled = true;
|
||||
first_slide = false;
|
||||
|
||||
if (!found_collision || motion == Vector2()) {
|
||||
if (!found_collision || motion.is_equal_approx(Vector2())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_snap_on_floor(was_on_floor, vel_dir_facing_up);
|
||||
|
||||
if (!on_floor && !on_wall) {
|
||||
// Add last platform velocity when just left a moving platform.
|
||||
linear_velocity += current_floor_velocity;
|
||||
linear_velocity += current_platform_velocity;
|
||||
}
|
||||
|
||||
if (!was_on_floor || snap == Vector2()) {
|
||||
// Reset the gravity accumulation when touching the ground.
|
||||
if (on_floor && !vel_dir_facing_up) {
|
||||
linear_velocity = linear_velocity.slide(up_direction);
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterBody2D::_snap_on_floor(bool was_on_floor, bool vel_dir_facing_up) {
|
||||
if (Math::is_equal_approx(floor_snap_length, 0) || up_direction == Vector2() || on_floor || !was_on_floor || vel_dir_facing_up) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply snap.
|
||||
Transform2D gt = get_global_transform();
|
||||
PhysicsServer2D::MotionResult result;
|
||||
if (move_and_collide(snap, infinite_inertia, result, margin, false, true, false)) {
|
||||
if (move_and_collide(up_direction * -floor_snap_length, infinite_inertia, result, margin, false, true, false)) {
|
||||
bool apply = true;
|
||||
if (up_direction != Vector2()) {
|
||||
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 (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.
|
||||
if (result.motion.length() > margin) {
|
||||
result.motion = up_direction * up_direction.dot(result.motion);
|
||||
} else {
|
||||
result.motion = Vector2();
|
||||
}
|
||||
float collision_angle = Math::acos(result.collision_normal.dot(up_direction));
|
||||
if (collision_angle <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
|
||||
on_floor = true;
|
||||
floor_normal = result.collision_normal;
|
||||
platform_velocity = result.collider_velocity;
|
||||
_set_platform_data(result);
|
||||
|
||||
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.
|
||||
if (result.motion.length() > margin) {
|
||||
result.motion = up_direction * up_direction.dot(result.motion);
|
||||
} else {
|
||||
result.motion = Vector2();
|
||||
}
|
||||
} else {
|
||||
apply = false;
|
||||
}
|
||||
} else {
|
||||
apply = false;
|
||||
}
|
||||
|
||||
if (apply) {
|
||||
|
|
@ -1188,23 +1288,46 @@ void CharacterBody2D::move_and_slide() {
|
|||
}
|
||||
}
|
||||
|
||||
bool CharacterBody2D::_on_floor_if_snapped(bool was_on_floor, bool vel_dir_facing_up) {
|
||||
if (Math::is_equal_approx(floor_snap_length, 0) || up_direction == Vector2() || on_floor || !was_on_floor || vel_dir_facing_up) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PhysicsServer2D::MotionResult result;
|
||||
if (move_and_collide(up_direction * -floor_snap_length, infinite_inertia, result, margin, false, true, false)) {
|
||||
if (Math::acos(result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CharacterBody2D::_set_collision_direction(const PhysicsServer2D::MotionResult &p_result) {
|
||||
if (up_direction == Vector2()) {
|
||||
//all is a wall
|
||||
on_wall = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Math::acos(p_result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
|
||||
on_floor = true;
|
||||
floor_normal = p_result.collision_normal;
|
||||
platform_velocity = p_result.collider_velocity;
|
||||
_set_platform_data(p_result);
|
||||
} else if (Math::acos(p_result.collision_normal.dot(-up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
|
||||
on_ceiling = true;
|
||||
} else {
|
||||
if (Math::acos(p_result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
|
||||
on_floor = true;
|
||||
floor_normal = p_result.collision_normal;
|
||||
on_floor_body = p_result.collider;
|
||||
floor_velocity = p_result.collider_velocity;
|
||||
} else if (Math::acos(p_result.collision_normal.dot(-up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
|
||||
on_ceiling = true;
|
||||
} else {
|
||||
on_wall = true;
|
||||
on_floor_body = p_result.collider;
|
||||
floor_velocity = p_result.collider_velocity;
|
||||
}
|
||||
on_wall = true;
|
||||
platform_velocity = p_result.collider_velocity;
|
||||
_set_platform_data(p_result);
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterBody2D::_set_platform_data(const PhysicsServer2D::MotionResult &p_result) {
|
||||
platform_rid = p_result.collider;
|
||||
platform_layer = 0;
|
||||
CollisionObject2D *collision_object = Object::cast_to<CollisionObject2D>(ObjectDB::get_instance(p_result.collider_id));
|
||||
if (collision_object) {
|
||||
platform_layer = collision_object->get_collision_layer();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1256,20 +1379,32 @@ bool CharacterBody2D::is_on_floor() const {
|
|||
return on_floor;
|
||||
}
|
||||
|
||||
bool CharacterBody2D::is_on_floor_only() const {
|
||||
return on_floor && !on_wall && !on_ceiling;
|
||||
}
|
||||
|
||||
bool CharacterBody2D::is_on_wall() const {
|
||||
return on_wall;
|
||||
}
|
||||
|
||||
bool CharacterBody2D::is_on_wall_only() const {
|
||||
return on_wall && !on_floor && !on_ceiling;
|
||||
}
|
||||
|
||||
bool CharacterBody2D::is_on_ceiling() const {
|
||||
return on_ceiling;
|
||||
}
|
||||
|
||||
bool CharacterBody2D::is_on_ceiling_only() const {
|
||||
return on_ceiling && !on_floor && !on_wall;
|
||||
}
|
||||
|
||||
Vector2 CharacterBody2D::get_floor_normal() const {
|
||||
return floor_normal;
|
||||
}
|
||||
|
||||
Vector2 CharacterBody2D::get_floor_velocity() const {
|
||||
return floor_velocity;
|
||||
Vector2 CharacterBody2D::get_platform_velocity() const {
|
||||
return platform_velocity;
|
||||
}
|
||||
|
||||
int CharacterBody2D::get_slide_count() const {
|
||||
|
|
@ -1319,6 +1454,35 @@ void CharacterBody2D::set_infinite_inertia_enabled(bool p_enabled) {
|
|||
infinite_inertia = p_enabled;
|
||||
}
|
||||
|
||||
bool CharacterBody2D::is_constant_speed_on_floor_enabled() const {
|
||||
return constant_speed_on_floor;
|
||||
}
|
||||
void CharacterBody2D::set_constant_speed_on_floor_enabled(bool p_enabled) {
|
||||
constant_speed_on_floor = p_enabled;
|
||||
}
|
||||
|
||||
bool CharacterBody2D::is_move_on_floor_only_enabled() const {
|
||||
return move_on_floor_only;
|
||||
}
|
||||
void CharacterBody2D::set_move_on_floor_only_enabled(bool p_enabled) {
|
||||
move_on_floor_only = p_enabled;
|
||||
}
|
||||
|
||||
bool CharacterBody2D::is_slide_on_ceiling_enabled() const {
|
||||
return slide_on_ceiling;
|
||||
}
|
||||
void CharacterBody2D::set_slide_on_ceiling_enabled(bool p_enabled) {
|
||||
slide_on_ceiling = p_enabled;
|
||||
}
|
||||
|
||||
uint32_t CharacterBody2D::get_exclude_body_layers() const {
|
||||
return exclude_body_layers;
|
||||
}
|
||||
|
||||
void CharacterBody2D::set_exclude_body_layers(uint32_t p_exclude_layers) {
|
||||
exclude_body_layers = p_exclude_layers;
|
||||
}
|
||||
|
||||
int CharacterBody2D::get_max_slides() const {
|
||||
return max_slides;
|
||||
}
|
||||
|
|
@ -1336,12 +1500,13 @@ void CharacterBody2D::set_floor_max_angle(real_t p_radians) {
|
|||
floor_max_angle = p_radians;
|
||||
}
|
||||
|
||||
const Vector2 &CharacterBody2D::get_snap() const {
|
||||
return snap;
|
||||
real_t CharacterBody2D::get_floor_snap_length() {
|
||||
return floor_snap_length;
|
||||
}
|
||||
|
||||
void CharacterBody2D::set_snap(const Vector2 &p_snap) {
|
||||
snap = p_snap;
|
||||
void CharacterBody2D::set_floor_snap_length(real_t p_floor_snap_length) {
|
||||
ERR_FAIL_COND(p_floor_snap_length < 0);
|
||||
floor_snap_length = p_floor_snap_length;
|
||||
}
|
||||
|
||||
const Vector2 &CharacterBody2D::get_up_direction() const {
|
||||
|
|
@ -1357,11 +1522,11 @@ void CharacterBody2D::_notification(int p_what) {
|
|||
case NOTIFICATION_ENTER_TREE: {
|
||||
// Reset move_and_slide() data.
|
||||
on_floor = false;
|
||||
on_floor_body = RID();
|
||||
platform_rid = RID();
|
||||
on_ceiling = false;
|
||||
on_wall = false;
|
||||
motion_results.clear();
|
||||
floor_velocity = Vector2();
|
||||
platform_velocity = Vector2();
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1377,31 +1542,48 @@ void CharacterBody2D::_bind_methods() {
|
|||
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_constant_speed_on_floor_enabled", "enabled"), &CharacterBody2D::set_constant_speed_on_floor_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_constant_speed_on_floor_enabled"), &CharacterBody2D::is_constant_speed_on_floor_enabled);
|
||||
ClassDB::bind_method(D_METHOD("set_move_on_floor_only_enabled", "enabled"), &CharacterBody2D::set_move_on_floor_only_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_move_on_floor_only_enabled"), &CharacterBody2D::is_move_on_floor_only_enabled);
|
||||
ClassDB::bind_method(D_METHOD("set_slide_on_ceiling_enabled", "enabled"), &CharacterBody2D::set_slide_on_ceiling_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_slide_on_ceiling_enabled"), &CharacterBody2D::is_slide_on_ceiling_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_exclude_body_layers", "exclude_layer"), &CharacterBody2D::set_exclude_body_layers);
|
||||
ClassDB::bind_method(D_METHOD("get_exclude_body_layers"), &CharacterBody2D::get_exclude_body_layers);
|
||||
|
||||
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", "radians"), &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_floor_snap_length"), &CharacterBody2D::get_floor_snap_length);
|
||||
ClassDB::bind_method(D_METHOD("set_floor_snap_length", "floor_snap_length"), &CharacterBody2D::set_floor_snap_length);
|
||||
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_floor_only"), &CharacterBody2D::is_on_floor_only);
|
||||
ClassDB::bind_method(D_METHOD("is_on_ceiling"), &CharacterBody2D::is_on_ceiling);
|
||||
ClassDB::bind_method(D_METHOD("is_on_ceiling_only"), &CharacterBody2D::is_on_ceiling_only);
|
||||
ClassDB::bind_method(D_METHOD("is_on_wall"), &CharacterBody2D::is_on_wall);
|
||||
ClassDB::bind_method(D_METHOD("is_on_wall_only"), &CharacterBody2D::is_on_wall_only);
|
||||
ClassDB::bind_method(D_METHOD("get_floor_normal"), &CharacterBody2D::get_floor_normal);
|
||||
ClassDB::bind_method(D_METHOD("get_floor_velocity"), &CharacterBody2D::get_floor_velocity);
|
||||
ClassDB::bind_method(D_METHOD("get_platform_velocity"), &CharacterBody2D::get_platform_velocity);
|
||||
ClassDB::bind_method(D_METHOD("get_slide_count"), &CharacterBody2D::get_slide_count);
|
||||
ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &CharacterBody2D::_get_slide_collision);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
|
||||
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::BOOL, "constant_speed_on_floor"), "set_constant_speed_on_floor_enabled", "is_constant_speed_on_floor_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "move_on_floor_only"), "set_move_on_floor_only_enabled", "is_move_on_floor_only_enabled");
|
||||
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_RANGE, "1,8,1,or_greater"), "set_max_slides", "get_max_slides");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_RANGE, "0,180,0.1"), "set_floor_max_angle", "get_floor_max_angle");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "snap"), "set_snap", "get_snap");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians"), "set_floor_max_angle", "get_floor_max_angle");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_snap_length", PROPERTY_HINT_RANGE, "0,1000,0.1"), "set_floor_snap_length", "get_floor_snap_length");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "up_direction"), "set_up_direction", "get_up_direction");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "exclude_body_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_exclude_body_layers", "get_exclude_body_layers");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -273,16 +273,20 @@ private:
|
|||
|
||||
bool stop_on_slope = false;
|
||||
bool infinite_inertia = true;
|
||||
bool constant_speed_on_floor = false;
|
||||
bool move_on_floor_only = true;
|
||||
bool slide_on_ceiling = true;
|
||||
int max_slides = 4;
|
||||
int platform_layer;
|
||||
real_t floor_max_angle = Math::deg2rad((real_t)45.0);
|
||||
Vector2 snap;
|
||||
float floor_snap_length = 0;
|
||||
Vector2 up_direction = Vector2(0.0, -1.0);
|
||||
|
||||
uint32_t exclude_body_layers = 0;
|
||||
Vector2 linear_velocity;
|
||||
|
||||
Vector2 floor_normal;
|
||||
Vector2 floor_velocity;
|
||||
RID on_floor_body;
|
||||
Vector2 platform_velocity;
|
||||
RID platform_rid;
|
||||
bool on_floor = false;
|
||||
bool on_ceiling = false;
|
||||
bool on_wall = false;
|
||||
|
|
@ -290,10 +294,6 @@ private:
|
|||
Vector<PhysicsServer2D::MotionResult> motion_results;
|
||||
Vector<Ref<KinematicCollision2D>> slide_colliders;
|
||||
|
||||
Ref<KinematicCollision2D> _get_slide_collision(int p_bounce);
|
||||
|
||||
void _set_collision_direction(const PhysicsServer2D::MotionResult &p_result);
|
||||
|
||||
bool separate_raycast_shapes(PhysicsServer2D::MotionResult &r_result);
|
||||
|
||||
void set_safe_margin(real_t p_margin);
|
||||
|
|
@ -305,17 +305,37 @@ private:
|
|||
bool is_infinite_inertia_enabled() const;
|
||||
void set_infinite_inertia_enabled(bool p_enabled);
|
||||
|
||||
bool is_constant_speed_on_floor_enabled() const;
|
||||
void set_constant_speed_on_floor_enabled(bool p_enabled);
|
||||
|
||||
bool is_move_on_floor_only_enabled() const;
|
||||
void set_move_on_floor_only_enabled(bool p_enabled);
|
||||
|
||||
bool is_slide_on_ceiling_enabled() const;
|
||||
void set_slide_on_ceiling_enabled(bool p_enabled);
|
||||
|
||||
int get_max_slides() const;
|
||||
void set_max_slides(int p_max_slides);
|
||||
|
||||
real_t get_move_max_angle() const;
|
||||
void set_move_max_angle(real_t p_radians);
|
||||
|
||||
real_t get_floor_max_angle() const;
|
||||
void set_floor_max_angle(real_t p_radians);
|
||||
|
||||
const Vector2 &get_snap() const;
|
||||
void set_snap(const Vector2 &p_snap);
|
||||
real_t get_floor_snap_length();
|
||||
void set_floor_snap_length(real_t p_floor_snap_length);
|
||||
|
||||
uint32_t get_exclude_body_layers() const;
|
||||
void set_exclude_body_layers(const uint32_t p_exclude_layer);
|
||||
|
||||
Ref<KinematicCollision2D> _get_slide_collision(int p_bounce);
|
||||
const Vector2 &get_up_direction() const;
|
||||
bool _on_floor_if_snapped(bool was_on_floor, bool vel_dir_facing_up);
|
||||
void set_up_direction(const Vector2 &p_up_direction);
|
||||
void _set_collision_direction(const PhysicsServer2D::MotionResult &p_result);
|
||||
void _set_platform_data(const PhysicsServer2D::MotionResult &p_result);
|
||||
void _snap_on_floor(bool was_on_floor, bool vel_dir_facing_up);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
|
|
@ -328,10 +348,13 @@ public:
|
|||
void set_linear_velocity(const Vector2 &p_velocity);
|
||||
|
||||
bool is_on_floor() const;
|
||||
bool is_on_floor_only() const;
|
||||
bool is_on_wall() const;
|
||||
bool is_on_wall_only() const;
|
||||
bool is_on_ceiling() const;
|
||||
bool is_on_ceiling_only() const;
|
||||
Vector2 get_floor_normal() const;
|
||||
Vector2 get_floor_velocity() const;
|
||||
Vector2 get_platform_velocity() const;
|
||||
|
||||
int get_slide_count() const;
|
||||
PhysicsServer2D::MotionResult get_slide_collision(int p_bounce) const;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue