improved kinematic motion, improved demos for kinematic motion
This commit is contained in:
parent
04fb3402c5
commit
e7aa37fe75
9 changed files with 97 additions and 44 deletions
BIN
demos/2d/kinematic_char/circle.png
Normal file
BIN
demos/2d/kinematic_char/circle.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6 KiB |
Binary file not shown.
BIN
demos/2d/kinematic_char/long_obstacle.png
Normal file
BIN
demos/2d/kinematic_char/long_obstacle.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 534 B |
|
@ -21,6 +21,8 @@ const STOP_FORCE = 1300
|
|||
const JUMP_SPEED = 200
|
||||
const JUMP_MAX_AIRBORNE_TIME=0.2
|
||||
|
||||
const SLIDE_STOP_VELOCITY=1.0 #one pixel per second
|
||||
const SLIDE_STOP_MIN_TRAVEL=1.0 #one pixel
|
||||
var velocity = Vector2()
|
||||
var on_air_time=100
|
||||
var jumping=false
|
||||
|
@ -86,16 +88,29 @@ func _fixed_process(delta):
|
|||
#char is on floor
|
||||
on_air_time=0
|
||||
floor_velocity=get_collider_velocity()
|
||||
#velocity.y=0
|
||||
|
||||
#But we were moving and our motion was interrupted,
|
||||
#so try to complete the motion by "sliding"
|
||||
#by the normal
|
||||
motion = n.slide(motion)
|
||||
velocity = n.slide(velocity)
|
||||
|
||||
#then move again
|
||||
move(motion)
|
||||
|
||||
if (on_air_time==0 and force.x==0 and get_travel().length() < SLIDE_STOP_MIN_TRAVEL and abs(velocity.x) < SLIDE_STOP_VELOCITY and get_collider_velocity()==Vector2()):
|
||||
#Since this formula will always slide the character around,
|
||||
#a special case must be considered to to stop it from moving
|
||||
#if standing on an inclined floor. Conditions are:
|
||||
# 1) Standin on floor (on_air_time==0)
|
||||
# 2) Did not move more than one pixel (get_travel().length() < SLIDE_STOP_MIN_TRAVEL)
|
||||
# 3) Not moving horizontally (abs(velocity.x) < SLIDE_STOP_VELOCITY)
|
||||
# 4) Collider is not moving
|
||||
|
||||
revert_motion()
|
||||
velocity.y=0.0
|
||||
|
||||
else:
|
||||
#For every other case of motion,our motion was interrupted.
|
||||
#Try to complete the motion by "sliding"
|
||||
#by the normal
|
||||
|
||||
motion = n.slide(motion)
|
||||
velocity = n.slide(velocity)
|
||||
#then move again
|
||||
move(motion)
|
||||
|
||||
if (floor_velocity!=Vector2()):
|
||||
#if floor moves, move with floor
|
||||
|
|
|
@ -925,6 +925,19 @@ Variant KinematicBody2D::_get_collider() const {
|
|||
return obj;
|
||||
}
|
||||
|
||||
void KinematicBody2D::revert_motion() {
|
||||
|
||||
Matrix32 gt = get_global_transform();
|
||||
gt.elements[2]-=travel;
|
||||
travel=Vector2();
|
||||
set_global_transform(gt);
|
||||
|
||||
}
|
||||
|
||||
Vector2 KinematicBody2D::get_travel() const {
|
||||
|
||||
return travel;
|
||||
}
|
||||
|
||||
Vector2 KinematicBody2D::move(const Vector2& p_motion) {
|
||||
|
||||
|
@ -942,6 +955,7 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) {
|
|||
Matrix32 gt = get_global_transform();
|
||||
gt.elements[2]+=result.motion;
|
||||
set_global_transform(gt);
|
||||
travel=result.motion;
|
||||
return result.remainder;
|
||||
|
||||
#else
|
||||
|
@ -1173,6 +1187,8 @@ void KinematicBody2D::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("move_to","position"),&KinematicBody2D::move_to);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("test_move","rel_vec"),&KinematicBody2D::test_move);
|
||||
ObjectTypeDB::bind_method(_MD("get_travel"),&KinematicBody2D::get_travel);
|
||||
ObjectTypeDB::bind_method(_MD("revert_motion"),&KinematicBody2D::revert_motion);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("is_colliding"),&KinematicBody2D::is_colliding);
|
||||
|
||||
|
|
|
@ -280,6 +280,7 @@ class KinematicBody2D : public PhysicsBody2D {
|
|||
ObjectID collider;
|
||||
int collider_shape;
|
||||
Variant collider_metadata;
|
||||
Vector2 travel;
|
||||
|
||||
Variant _get_collider() const;
|
||||
|
||||
|
@ -294,6 +295,10 @@ public:
|
|||
|
||||
bool test_move(const Vector2& p_motion);
|
||||
bool is_colliding() const;
|
||||
|
||||
Vector2 get_travel() const;
|
||||
void revert_motion();
|
||||
|
||||
Vector2 get_collision_pos() const;
|
||||
Vector2 get_collision_normal() const;
|
||||
Vector2 get_collider_velocity() const;
|
||||
|
|
|
@ -105,6 +105,9 @@ bool Theme::_get(const StringName& p_name,Variant &r_ret) const {
|
|||
|
||||
void Theme::_get_property_list( List<PropertyInfo> *p_list) const {
|
||||
|
||||
|
||||
List<PropertyInfo> list;
|
||||
|
||||
const StringName *key=NULL;
|
||||
|
||||
while((key=icon_map.next(key))) {
|
||||
|
@ -113,7 +116,7 @@ void Theme::_get_property_list( List<PropertyInfo> *p_list) const {
|
|||
|
||||
while((key2=icon_map[*key].next(key2))) {
|
||||
|
||||
p_list->push_back( PropertyInfo( Variant::OBJECT, String()+*key+"/icons/"+*key2, PROPERTY_HINT_RESOURCE_TYPE, "Texture" ) );
|
||||
list.push_back( PropertyInfo( Variant::OBJECT, String()+*key+"/icons/"+*key2, PROPERTY_HINT_RESOURCE_TYPE, "Texture" ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,7 +128,7 @@ void Theme::_get_property_list( List<PropertyInfo> *p_list) const {
|
|||
|
||||
while((key2=style_map[*key].next(key2))) {
|
||||
|
||||
p_list->push_back( PropertyInfo( Variant::OBJECT, String()+*key+"/styles/"+*key2, PROPERTY_HINT_RESOURCE_TYPE, "StyleBox" ) );
|
||||
list.push_back( PropertyInfo( Variant::OBJECT, String()+*key+"/styles/"+*key2, PROPERTY_HINT_RESOURCE_TYPE, "StyleBox" ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,7 +141,7 @@ void Theme::_get_property_list( List<PropertyInfo> *p_list) const {
|
|||
|
||||
while((key2=font_map[*key].next(key2))) {
|
||||
|
||||
p_list->push_back( PropertyInfo( Variant::OBJECT, String()+*key+"/fonts/"+*key2, PROPERTY_HINT_RESOURCE_TYPE, "Font" ) );
|
||||
list.push_back( PropertyInfo( Variant::OBJECT, String()+*key+"/fonts/"+*key2, PROPERTY_HINT_RESOURCE_TYPE, "Font" ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,7 +153,7 @@ void Theme::_get_property_list( List<PropertyInfo> *p_list) const {
|
|||
|
||||
while((key2=color_map[*key].next(key2))) {
|
||||
|
||||
p_list->push_back( PropertyInfo( Variant::COLOR, String()+*key+"/colors/"+*key2 ) );
|
||||
list.push_back( PropertyInfo( Variant::COLOR, String()+*key+"/colors/"+*key2 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,9 +165,14 @@ void Theme::_get_property_list( List<PropertyInfo> *p_list) const {
|
|||
|
||||
while((key2=constant_map[*key].next(key2))) {
|
||||
|
||||
p_list->push_back( PropertyInfo( Variant::INT, String()+*key+"/constants/"+*key2 ) );
|
||||
list.push_back( PropertyInfo( Variant::INT, String()+*key+"/constants/"+*key2 ) );
|
||||
}
|
||||
}
|
||||
|
||||
list.sort();
|
||||
for(List<PropertyInfo>::Element *E=list.front();E;E=E->next()) {
|
||||
p_list->push_back(E->get());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -555,38 +555,10 @@ Physics2DDirectSpaceStateSW::Physics2DDirectSpaceStateSW() {
|
|||
|
||||
|
||||
|
||||
|
||||
bool Space2DSW::test_body_motion(Body2DSW *p_body,const Vector2&p_motion,float p_margin,Physics2DServer::MotionResult *r_result) {
|
||||
|
||||
//give me back regular physics engine logic
|
||||
//this is madness
|
||||
//and most people using this function will think
|
||||
//what it does is simpler than using physics
|
||||
//this took about a week to get right..
|
||||
//but is it right? who knows at this point..
|
||||
|
||||
Rect2 body_aabb;
|
||||
|
||||
for(int i=0;i<p_body->get_shape_count();i++) {
|
||||
|
||||
if (i==0)
|
||||
body_aabb=p_body->get_shape_aabb(i);
|
||||
else
|
||||
body_aabb=body_aabb.merge(p_body->get_shape_aabb(i));
|
||||
}
|
||||
|
||||
body_aabb=body_aabb.grow(p_margin);
|
||||
|
||||
{
|
||||
//add motion
|
||||
|
||||
Rect2 motion_aabb=body_aabb;
|
||||
motion_aabb.pos+=p_motion;
|
||||
body_aabb=body_aabb.merge(motion_aabb);
|
||||
}
|
||||
int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body,const Rect2& p_aabb) {
|
||||
|
||||
|
||||
int amount = broadphase->cull_aabb(body_aabb,intersection_query_results,INTERSECTION_QUERY_MAX,intersection_query_subindex_results);
|
||||
int amount = broadphase->cull_aabb(p_aabb,intersection_query_results,INTERSECTION_QUERY_MAX,intersection_query_subindex_results);
|
||||
|
||||
for(int i=0;i<amount;i++) {
|
||||
|
||||
|
@ -617,6 +589,31 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body,const Vector2&p_motion,float p
|
|||
}
|
||||
}
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
bool Space2DSW::test_body_motion(Body2DSW *p_body,const Vector2&p_motion,float p_margin,Physics2DServer::MotionResult *r_result) {
|
||||
|
||||
//give me back regular physics engine logic
|
||||
//this is madness
|
||||
//and most people using this function will think
|
||||
//what it does is simpler than using physics
|
||||
//this took about a week to get right..
|
||||
//but is it right? who knows at this point..
|
||||
|
||||
Rect2 body_aabb;
|
||||
|
||||
for(int i=0;i<p_body->get_shape_count();i++) {
|
||||
|
||||
if (i==0)
|
||||
body_aabb=p_body->get_shape_aabb(i);
|
||||
else
|
||||
body_aabb=body_aabb.merge(p_body->get_shape_aabb(i));
|
||||
}
|
||||
|
||||
body_aabb=body_aabb.grow(p_margin);
|
||||
|
||||
|
||||
Matrix32 body_transform = p_body->get_transform();
|
||||
|
||||
{
|
||||
|
@ -642,6 +639,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body,const Vector2&p_motion,float p
|
|||
|
||||
bool collided=false;
|
||||
|
||||
int amount = _cull_aabb_for_body(p_body,body_aabb);
|
||||
|
||||
for(int j=0;j<p_body->get_shape_count();j++) {
|
||||
if (p_body->is_shape_set_as_trigger(j))
|
||||
|
@ -694,6 +692,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body,const Vector2&p_motion,float p
|
|||
}
|
||||
|
||||
body_transform.elements[2]+=recover_motion;
|
||||
body_aabb.pos+=recover_motion;
|
||||
|
||||
recover_attempts--;
|
||||
|
||||
|
@ -709,7 +708,11 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body,const Vector2&p_motion,float p
|
|||
{
|
||||
// STEP 2 ATTEMPT MOTION
|
||||
|
||||
Rect2 motion_aabb=body_aabb;
|
||||
motion_aabb.pos+=p_motion;
|
||||
motion_aabb=motion_aabb.merge(body_aabb);
|
||||
|
||||
int amount = _cull_aabb_for_body(p_body,motion_aabb);
|
||||
|
||||
for(int j=0;j<p_body->get_shape_count();j++) {
|
||||
|
||||
|
@ -847,6 +850,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body,const Vector2&p_motion,float p
|
|||
Matrix32 body_shape_xform = ugt * p_body->get_shape_transform(best_shape);
|
||||
Shape2DSW *body_shape = p_body->get_shape(best_shape);
|
||||
|
||||
body_aabb.pos+=p_motion*unsafe;
|
||||
|
||||
int amount = _cull_aabb_for_body(p_body,body_aabb);
|
||||
|
||||
|
||||
for(int i=0;i<amount;i++) {
|
||||
|
||||
|
|
|
@ -101,6 +101,8 @@ class Space2DSW {
|
|||
int active_objects;
|
||||
int collision_pairs;
|
||||
|
||||
int _cull_aabb_for_body(Body2DSW *p_body,const Rect2& p_aabb);
|
||||
|
||||
friend class Physics2DDirectSpaceStateSW;
|
||||
|
||||
public:
|
||||
|
|
Loading…
Reference in a new issue