improved kinematic motion, improved demos for kinematic motion

This commit is contained in:
Juan Linietsky 2015-05-03 22:37:10 -03:00
parent 04fb3402c5
commit e7aa37fe75
9 changed files with 97 additions and 44 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 B

View File

@ -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,14 +88,27 @@ 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"
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)

View File

@ -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);

View File

@ -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;

View File

@ -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,10 +165,15 @@ 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());
}
}
Ref<Theme> Theme::get_default() {

View File

@ -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++) {

View File

@ -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: