feat: car physics is now editor-configurable
This commit is contained in:
		
							parent
							
								
									bd9afa2403
								
							
						
					
					
						commit
						60e6640cdd
					
				|  | @ -11,6 +11,18 @@ void CarPhysics::_bind_methods() { | |||
|     GDPROPERTY(oversteer_curve_x_scale, Variant::FLOAT); | ||||
|     GDPROPERTY_HINTED(understeer_curve, Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "Curve"); | ||||
|     GDPROPERTY(understeer_curve_x_scale, Variant::FLOAT); | ||||
|     GDPROPERTY(acceleration, Variant::FLOAT); | ||||
|     GDPROPERTY(engine_brake_force, Variant::FLOAT); | ||||
|     GDPROPERTY(handbrake_force, Variant::FLOAT); | ||||
|     GDPROPERTY(handbrake_oversteer, Variant::FLOAT); | ||||
|     GDPROPERTY(traction_recovery_speed, Variant::FLOAT); | ||||
|     GDPROPERTY(max_slide_speed, Variant::FLOAT); | ||||
|     GDPROPERTY(slide_speed_acceleration, Variant::FLOAT); | ||||
|     GDPROPERTY(oversteer_speed_penalty, Variant::FLOAT); | ||||
|     GDPROPERTY(oversteer_brake_penalty, Variant::FLOAT); | ||||
|     GDPROPERTY(oversteer_steering_speed, Variant::FLOAT); | ||||
|     GDPROPERTY(slide_resistance, Variant::FLOAT); | ||||
|     GDPROPERTY(steering_inward_speed, Variant::FLOAT); | ||||
| } | ||||
| 
 | ||||
| void CarPhysics::_enter_tree() { | ||||
|  | @ -25,7 +37,7 @@ void CarPhysics::_enter_tree() { | |||
|     this->connect("body_shape_exited", callable_mp(this, &CarPhysics::on_body_shape_exited)); | ||||
| } | ||||
| 
 | ||||
| void CarPhysics::_physics_process(double delta_time) { | ||||
| void CarPhysics::_physics_process(double delta_time) { GDGAMEONLY(); | ||||
|     this->process_oversteer(delta_time); | ||||
|     this->process_understeer(delta_time); | ||||
|     UtilityFunctions::print("true target speed: ", this->get_true_target_speed()); | ||||
|  | @ -39,11 +51,11 @@ void CarPhysics::_physics_process(double delta_time) { | |||
| void CarPhysics::process_oversteer(double delta_time) { | ||||
|     float const target = this->current_steering == 0.f | ||||
|         ? 0.f | ||||
|         : (this->evaluate_oversteer_curve(this->local_velocity.z) + (this->brake ? 1.f : 0.f)) * Math::sign(this->current_steering); | ||||
|         : (this->evaluate_oversteer_curve(this->local_velocity.z) + (this->brake ? this->handbrake_oversteer : 0.f)) * Math::sign(this->current_steering); | ||||
|     if(Math::abs(target) >=  Math::abs(this->current_oversteer) && Math::sign(target) == Math::sign(this->current_oversteer)) | ||||
|         this->current_oversteer = target; | ||||
|     else | ||||
|         this->current_oversteer = Math::move_toward(this->current_oversteer, target, float(delta_time * 100.0)); | ||||
|         this->current_oversteer = Math::move_toward(this->current_oversteer, target, float(delta_time * this->traction_recovery_speed)); | ||||
|     UtilityFunctions::print("current oversteer: ", this->current_oversteer, " target: ", target); | ||||
| } | ||||
| 
 | ||||
|  | @ -52,7 +64,7 @@ void CarPhysics::process_understeer(double delta_time) { | |||
|     if(target >= this->current_understeer) | ||||
|         this->current_understeer = target; | ||||
|     else | ||||
|         this->current_understeer = Math::move_toward(this->current_understeer, target, (float)delta_time); | ||||
|         this->current_understeer = Math::move_toward(this->current_understeer, target, float(delta_time * this->traction_recovery_speed)); | ||||
|     UtilityFunctions::print("current understeer: ", this->current_understeer, " target: ", target); | ||||
| } | ||||
| 
 | ||||
|  | @ -73,20 +85,22 @@ void CarPhysics::integrate_steering(PhysicsDirectBodyState3D *state) { | |||
|     float target_x_velocity = 0.f; | ||||
|     if(this->local_velocity.z != 0.f) { | ||||
|         Vector3 const steering_angle_vel = this->get_global_basis().get_column(1) * ( | ||||
|                 this->current_steering * Math::sign(this->local_velocity.z + this->current_oversteer * 2.f)); | ||||
|                 this->current_steering * Math::sign(this->local_velocity.z + this->current_oversteer * this->oversteer_steering_speed)); | ||||
|         state->set_angular_velocity(steering_angle_vel * (1.0f-this->current_understeer)); | ||||
|         target_x_velocity = this->current_steering * 0.1f; | ||||
|         target_x_velocity = this->current_steering * this->steering_inward_speed; | ||||
|     } else { | ||||
|         state->set_angular_velocity(Vector3(0,0,0)); | ||||
|     } | ||||
|     this->local_velocity.x = Math::move_toward(this->local_velocity.x, target_x_velocity, float(20.f * (1.f-this->current_oversteer) * state->get_step())); | ||||
|     this->local_velocity.x = Math::move_toward(this->local_velocity.x, | ||||
|                                                target_x_velocity, | ||||
|                                                float(this->slide_resistance * (1.f-this->current_oversteer) * state->get_step())); | ||||
| } | ||||
| 
 | ||||
| void CarPhysics::integrate_engine_acceleration(PhysicsDirectBodyState3D *state) { | ||||
|     Vector3 const jolt = state->get_linear_velocity() - this->last_velocity; | ||||
|     float const z_jolt = jolt.dot(this->get_global_basis().get_column(2)); | ||||
| 
 | ||||
|     if(Math::abs(this->local_velocity.z) > 1.f && Math::abs(z_jolt) >= Math::abs(this->local_velocity.z) / 2.f && Math::sign(z_jolt) != Math::sign(this->local_velocity.z)) { | ||||
|     if(Math::abs(z_jolt) >= Math::abs(this->local_velocity.z) / 2.f && Math::sign(z_jolt) != Math::sign(this->local_velocity.z)) { | ||||
|         this->local_velocity.z = 0.f; | ||||
|     } | ||||
| 
 | ||||
|  | @ -98,10 +112,9 @@ void CarPhysics::integrate_engine_acceleration(PhysicsDirectBodyState3D *state) | |||
| 
 | ||||
| void CarPhysics::integrate_oversteer(PhysicsDirectBodyState3D *state) { | ||||
|     this->local_velocity.x = Math::clamp( | ||||
|         this->local_velocity.x - this->local_velocity.z * this->current_oversteer * 0.05f, | ||||
|         -20.f, | ||||
|         +20.f | ||||
|     ); | ||||
|         this->local_velocity.x - this->local_velocity.z * this->current_oversteer * this->slide_speed_acceleration, | ||||
|         -this->max_slide_speed, | ||||
|         this->max_slide_speed); | ||||
| } | ||||
| 
 | ||||
| void CarPhysics::on_body_shape_entered(RID body_rid, Node *body, int body_shape_index, int local_shape_index) { | ||||
|  | @ -154,7 +167,8 @@ float CarPhysics::evaluate_understeer_curve(float speed) const { | |||
| float CarPhysics::get_true_target_speed() const { | ||||
|         return (this->brake ? 0.f | ||||
|                 : (this->target_speed > 0 | ||||
|                     ? this->target_speed - (Math::abs(this->current_oversteer) * 5.f + this->current_understeer * 3.f) | ||||
|                     ? this->target_speed - (Math::abs(this->current_oversteer) * this->oversteer_speed_penalty | ||||
|                         + this->current_understeer * this->understeer_speed_penalty) | ||||
|                     : this->target_speed)); | ||||
| } | ||||
| 
 | ||||
|  | @ -164,10 +178,10 @@ bool CarPhysics::is_grounded() const { | |||
| 
 | ||||
| float CarPhysics::get_current_acceleration() const { | ||||
|  return Math::abs(this->brake | ||||
|          ? HANDBRAKE | ||||
|          ? this->handbrake_force | ||||
|          : ((Math::abs(this->get_true_target_speed()) >= Math::abs(this->local_velocity.z)) | ||||
|             ? (ACCELERATION * (1.f-Math::abs(this->current_oversteer))) | ||||
|             : (CarPhysics::ENGINE_BRAKING * (1.f-Math::abs(this->current_oversteer * 0.25f))))); | ||||
|             ? (this->acceleration * (1.f-Math::abs(this->current_oversteer))) | ||||
|             : (this->engine_brake_force * (1.f-Math::abs(this->current_oversteer * this->oversteer_brake_penalty))))); | ||||
| } | ||||
| 
 | ||||
| void CarPhysics::set_target_speed(float target) { | ||||
|  | @ -226,9 +240,99 @@ float CarPhysics::get_understeer_curve_x_scale() const { | |||
|     return this->understeer_curve_x_scale; | ||||
| } | ||||
| 
 | ||||
| const float CarPhysics::ACCELERATION{20.f}; | ||||
| const float CarPhysics::ENGINE_BRAKING{30.f}; | ||||
| const float CarPhysics::HANDBRAKE{40.f}; | ||||
| const float CarPhysics::UNDERSTEER_SPEED_MUL{0.f}; | ||||
| const float CarPhysics::OVERSTEER_SPEED_MUL{0.f}; | ||||
| void CarPhysics::set_acceleration(float value) { | ||||
|     this->acceleration = value; | ||||
| } | ||||
| 
 | ||||
| float CarPhysics::get_acceleration() const { | ||||
|     return this->acceleration; | ||||
| } | ||||
| 
 | ||||
| void CarPhysics::set_engine_brake_force(float value) { | ||||
|     this->engine_brake_force = value; | ||||
| } | ||||
| 
 | ||||
| float CarPhysics::get_engine_brake_force() const { | ||||
|     return this->engine_brake_force; | ||||
| } | ||||
| 
 | ||||
| void CarPhysics::set_handbrake_force(float value) { | ||||
|     this->handbrake_force = value; | ||||
| } | ||||
| 
 | ||||
| float CarPhysics::get_handbrake_force() const { | ||||
|     return this->handbrake_force; | ||||
| } | ||||
| 
 | ||||
| void CarPhysics::set_handbrake_oversteer(float value) { | ||||
|     this->handbrake_oversteer = value; | ||||
| } | ||||
| 
 | ||||
| float CarPhysics::get_handbrake_oversteer() const { | ||||
|     return this->handbrake_oversteer; | ||||
| } | ||||
| 
 | ||||
| void CarPhysics::set_traction_recovery_speed(float value) { | ||||
|     this->traction_recovery_speed = value; | ||||
| } | ||||
| 
 | ||||
| float CarPhysics::get_traction_recovery_speed() const { | ||||
|     return this->traction_recovery_speed; | ||||
| } | ||||
| 
 | ||||
| void CarPhysics::set_max_slide_speed(float value) { | ||||
|     this->max_slide_speed = value; | ||||
| } | ||||
| 
 | ||||
| float CarPhysics::get_max_slide_speed() const { | ||||
|     return this->max_slide_speed; | ||||
| } | ||||
| 
 | ||||
| void CarPhysics::set_slide_speed_acceleration(float value) { | ||||
|     this->slide_speed_acceleration = value; | ||||
| } | ||||
| 
 | ||||
| float CarPhysics::get_slide_speed_acceleration() const { | ||||
|     return this->slide_speed_acceleration; | ||||
| } | ||||
| 
 | ||||
| void CarPhysics::set_oversteer_speed_penalty(float value) { | ||||
|     this->oversteer_speed_penalty = value; | ||||
| } | ||||
| 
 | ||||
| float CarPhysics::get_oversteer_speed_penalty() const { | ||||
|     return this->oversteer_speed_penalty; | ||||
| } | ||||
| 
 | ||||
| void CarPhysics::set_oversteer_brake_penalty(float value) { | ||||
|     this->oversteer_brake_penalty = value; | ||||
| } | ||||
| 
 | ||||
| float CarPhysics::get_oversteer_brake_penalty() const { | ||||
|     return this->oversteer_brake_penalty; | ||||
| } | ||||
| 
 | ||||
| void CarPhysics::set_oversteer_steering_speed(float value) { | ||||
|     this->oversteer_steering_speed = value; | ||||
| } | ||||
| 
 | ||||
| float CarPhysics::get_oversteer_steering_speed() const { | ||||
|     return this->oversteer_steering_speed; | ||||
| } | ||||
| 
 | ||||
| void CarPhysics::set_slide_resistance(float value) { | ||||
|     this->slide_resistance = value; | ||||
| } | ||||
| 
 | ||||
| float CarPhysics::get_slide_resistance() const { | ||||
|     return this->slide_resistance; | ||||
| } | ||||
| 
 | ||||
| void CarPhysics::set_steering_inward_speed(float value) { | ||||
|     this->steering_inward_speed = value; | ||||
| } | ||||
| 
 | ||||
| float CarPhysics::get_steering_inward_speed() const { | ||||
|     return this->steering_inward_speed; | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -54,31 +54,62 @@ public: | |||
|     Ref<Curve> get_understeer_curve() const; | ||||
|     void set_understeer_curve_x_scale(float scale); | ||||
|     float get_understeer_curve_x_scale() const; | ||||
|     void set_acceleration(float value); | ||||
|     float get_acceleration() const; | ||||
|     void set_engine_brake_force(float value); | ||||
|     float get_engine_brake_force() const; | ||||
|     void set_handbrake_force(float value); | ||||
|     float get_handbrake_force() const; | ||||
|     void set_handbrake_oversteer(float value); | ||||
|     float get_handbrake_oversteer() const; | ||||
|     void set_traction_recovery_speed(float value); | ||||
|     float get_traction_recovery_speed() const; | ||||
|     void set_max_slide_speed(float value); | ||||
|     float get_max_slide_speed() const; | ||||
|     void set_slide_speed_acceleration(float value); | ||||
|     float get_slide_speed_acceleration() const; | ||||
|     void set_oversteer_speed_penalty(float value); | ||||
|     float get_oversteer_speed_penalty() const; | ||||
|     void set_oversteer_brake_penalty(float value); | ||||
|     float get_oversteer_brake_penalty() const; | ||||
|     void set_oversteer_steering_speed(float value); | ||||
|     float get_oversteer_steering_speed() const; | ||||
|     void set_slide_resistance(float value); | ||||
|     float get_slide_resistance() const; | ||||
|     void set_steering_inward_speed(float value); | ||||
|     float get_steering_inward_speed() const; | ||||
| private: | ||||
|     Vector3 last_velocity{0.f, 0.f, 0.f}; | ||||
|     Vector3 local_velocity{0.f, 0.f, 0.f}; | ||||
| 
 | ||||
|     HashSet<Node*> grounded_objects{}; | ||||
| 
 | ||||
|     float target_speed{0.f}; | ||||
|     float current_steering{0.f}; | ||||
|     bool brake{false}; | ||||
| 
 | ||||
|     Ref<Curve> oversteer_curve{}; | ||||
|     float oversteer_curve_x_scale{50.f}; | ||||
|     Ref<Curve> understeer_curve{}; | ||||
|     float understeer_curve_x_scale{50.f}; | ||||
|     float acceleration{20.f}; | ||||
|     float engine_brake_force{30.f}; | ||||
|     float handbrake_force{40.f}; | ||||
|     float handbrake_oversteer{1.f}; | ||||
|     float traction_recovery_speed{100.f}; | ||||
|     float max_slide_speed{20.f}; | ||||
|     float slide_speed_acceleration{0.05f}; | ||||
|     float oversteer_speed_penalty{5.f}; | ||||
|     float oversteer_brake_penalty{0.25f}; | ||||
|     float oversteer_steering_speed{2.f}; | ||||
|     float understeer_speed_penalty{3.f}; | ||||
|     float slide_resistance{20.f}; | ||||
|     float steering_inward_speed{0.1f}; | ||||
| 
 | ||||
|     HashSet<Node*> grounded_objects{}; | ||||
| 
 | ||||
|     CollisionShape3D *front_wheels{nullptr}; | ||||
|     CollisionShape3D *back_wheels{nullptr}; | ||||
| 
 | ||||
|     float current_understeer{0.f}; | ||||
|     float current_oversteer{0.f}; | ||||
| 
 | ||||
|     static const float ACCELERATION; | ||||
|     static const float ENGINE_BRAKING; | ||||
|     static const float HANDBRAKE; | ||||
|     static const float UNDERSTEER_SPEED_MUL; | ||||
|     static const float OVERSTEER_SPEED_MUL; | ||||
| }; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Sara
						Sara