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