Skip to content

Commit

Permalink
Further fixes to KinematicBody2D API, support for sync motion in movi…
Browse files Browse the repository at this point in the history
…ng objects
  • Loading branch information
reduz authored and malcolmhoward committed Jul 31, 2018
1 parent 0346fd3 commit 2eb475c
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 17 deletions.
50 changes: 36 additions & 14 deletions scene/2d/physics_body_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1136,11 +1136,11 @@ void RigidBody2D::_reload_physics_characteristics() {

//////////////////////////

Ref<KinematicCollision2D> KinematicBody2D::_move(const Vector2 &p_motion, bool p_infinite_inertia, bool p_exclude_raycast_shapes) {
Ref<KinematicCollision2D> KinematicBody2D::_move(const Vector2 &p_motion, bool p_infinite_inertia, bool p_exclude_raycast_shapes, bool p_test_only) {

Collision col;

if (move_and_collide(p_motion, p_infinite_inertia, col, p_exclude_raycast_shapes)) {
if (move_and_collide(p_motion, p_infinite_inertia, col, p_exclude_raycast_shapes, p_test_only)) {
if (motion_cache.is_null()) {
motion_cache.instance();
motion_cache->owner = this;
Expand Down Expand Up @@ -1191,7 +1191,7 @@ bool KinematicBody2D::separate_raycast_shapes(bool p_infinite_inertia, Collision
}
}

bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes) {
bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes, bool p_test_only) {

Transform2D gt = get_global_transform();
Physics2DServer::MotionResult result;
Expand All @@ -1210,14 +1210,25 @@ bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_
r_collision.local_shape = result.collision_local_shape;
}

gt.elements[2] += result.motion;
set_global_transform(gt);
if (!p_test_only) {
gt.elements[2] += result.motion;
set_global_transform(gt);
}

return colliding;
}

Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, bool p_infinite_inertia, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle) {

Vector2 floor_motion = floor_velocity;
if (on_floor && on_floor_body.is_valid()) {
//this approach makes sure there is less delay between the actual body velocity and the one we saved
Physics2DDirectBodyState *bs = Physics2DServer::get_singleton()->body_get_direct_state(on_floor_body);
if (bs) {
floor_motion = bs->get_linear_velocity();
}
}

Vector2 motion = (floor_motion + p_linear_velocity) * get_physics_process_delta_time();
Vector2 lv = p_linear_velocity;

Expand Down Expand Up @@ -1263,6 +1274,7 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
if (collision.normal.dot(p_floor_direction) >= Math::cos(p_floor_max_angle)) { //floor

on_floor = true;
on_floor_body = collision.collider_rid;
floor_velocity = collision.collider_vel;

Vector2 rel_v = lv - floor_velocity;
Expand Down Expand Up @@ -1300,20 +1312,29 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
return lv;
}

bool KinematicBody2D::snap_to_floor(const Vector2 &p_direction, float p_floor_max_angle) {
Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_floor_direction, bool p_infinite_inertia, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle) {

bool was_on_floor = on_floor;

Vector2 ret = move_and_slide(p_linear_velocity, p_floor_direction, p_infinite_inertia, p_slope_stop_min_velocity, p_max_slides, p_floor_max_angle);
if (!was_on_floor || p_snap == Vector2()) {
return ret;
}

Collision col;
Transform2D gt = get_global_transform();
Physics2DServer::MotionResult result;
bool colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(), gt, p_direction, false, margin, &result, false);
if (colliding) {
gt.elements[2] += result.motion;
if (Math::acos(p_direction.normalized().dot(-result.collision_normal)) < p_floor_max_angle) {

if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) {
gt.elements[2] += col.travel;
if (p_floor_direction != Vector2() && Math::acos(p_floor_direction.normalized().dot(col.normal)) < p_floor_max_angle) {
on_floor = true;
on_floor_body = col.collider_rid;
floor_velocity = col.collider_vel;
}
set_global_transform(gt);
}

return colliding;
return ret;
}

Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_floor_direction, bool p_infinite_inertia, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle) {
Expand Down Expand Up @@ -1453,9 +1474,9 @@ void KinematicBody2D::_notification(int p_what) {
}
void KinematicBody2D::_bind_methods() {

ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes"), &KinematicBody2D::_move, DEFVAL(true), DEFVAL(true));
ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only"), &KinematicBody2D::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false));
ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "infinite_inertia", "slope_stop_min_velocity", "max_bounces", "floor_max_angle"), &KinematicBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(true), DEFVAL(5), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)));
ClassDB::bind_method(D_METHOD("snap_to_floor", "motion", "max_floor_angle"), &KinematicBody2D::snap_to_floor, DEFVAL(Math::deg2rad(45.0)));
ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "floor_normal", "infinite_inertia", "slope_stop_min_velocity", "max_bounces", "floor_max_angle"), &KinematicBody2D::move_and_slide_with_snap, DEFVAL(Vector2(0, 0)), DEFVAL(true), DEFVAL(5), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)));

ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody2D::test_move);

Expand Down Expand Up @@ -1487,6 +1508,7 @@ KinematicBody2D::KinematicBody2D() :
on_floor = false;
on_ceiling = false;
on_wall = false;
sync_to_physics = false;
}
KinematicBody2D::~KinematicBody2D() {
if (motion_cache.is_valid()) {
Expand Down
8 changes: 5 additions & 3 deletions scene/2d/physics_body_2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,14 +310,15 @@ class KinematicBody2D : public PhysicsBody2D {
bool on_floor;
bool on_ceiling;
bool on_wall;
bool sync_to_physics;

Vector<Collision> colliders;
Vector<Ref<KinematicCollision2D> > slide_colliders;
Ref<KinematicCollision2D> motion_cache;

_FORCE_INLINE_ bool _ignores_mode(Physics2DServer::BodyMode) const;

Ref<KinematicCollision2D> _move(const Vector2 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true);
Ref<KinematicCollision2D> _move(const Vector2 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, bool p_test_only = false);
Ref<KinematicCollision2D> _get_slide_collision(int p_bounce);

Transform2D last_valid_transform;
Expand All @@ -328,8 +329,8 @@ class KinematicBody2D : public PhysicsBody2D {
static void _bind_methods();

public:
bool move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes = true);
bool snap_to_floor(const Vector2 &p_direction, float p_floor_max_angle = Math::deg2rad((float)45));
bool move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes = true, bool p_test_only = false);

bool test_move(const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia);

bool separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision);
Expand All @@ -338,6 +339,7 @@ class KinematicBody2D : public PhysicsBody2D {
float get_safe_margin() const;

Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction = Vector2(0, 0), bool p_infinite_inertia = true, float p_slope_stop_min_velocity = 5, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45));
Vector2 move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_floor_direction = Vector2(0, 0), bool p_infinite_inertia = true, float p_slope_stop_min_velocity = 5, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45));
bool is_on_floor() const;
bool is_on_wall() const;
bool is_on_ceiling() const;
Expand Down

0 comments on commit 2eb475c

Please sign in to comment.