Browse Source

improved kinematic motion, improved demos for kinematic motion

Juan Linietsky 10 years ago
parent
commit
e7aa37fe75

BIN
demos/2d/kinematic_char/circle.png


BIN
demos/2d/kinematic_char/colworld.scn


BIN
demos/2d/kinematic_char/long_obstacle.png


+ 24 - 9
demos/2d/kinematic_char/player.gd

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

+ 16 - 0
scene/2d/physics_body_2d.cpp

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

+ 5 - 0
scene/2d/physics_body_2d.h

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

+ 13 - 5
scene/resources/theme.cpp

@@ -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());
+	}
 	
 }
 

+ 37 - 30
servers/physics_2d/space_2d_sw.cpp

@@ -555,38 +555,10 @@ Physics2DDirectSpaceStateSW::Physics2DDirectSpaceStateSW() {
 
 
 
+int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body,const Rect2& p_aabb) {
 
-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 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++) {
 

+ 2 - 0
servers/physics_2d/space_2d_sw.h

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