prerelease
This commit is contained in:
55
Code/Car/VeloXCar.Aerodinamics.cs
Normal file
55
Code/Car/VeloXCar.Aerodinamics.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using Sandbox;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace VeloX;
|
||||
|
||||
public partial class VeloXCar
|
||||
{
|
||||
|
||||
private class DownforcePoint
|
||||
{
|
||||
[KeyProperty] public float MaxForce { get; set; }
|
||||
[KeyProperty] public Vector3 Position { get; set; }
|
||||
}
|
||||
public const float RHO = 10.225f;
|
||||
[Property, Feature( "Aerodinamics" )] public Vector3 Dimensions = new( 2f, 4.5f, 1.5f );
|
||||
[Property, Feature( "Aerodinamics" )] public float FrontalCd { get; set; } = 0.35f;
|
||||
[Property, Feature( "Aerodinamics" )] public float SideCd { get; set; } = 1.05f;
|
||||
[Property, Feature( "Aerodinamics" )] public float MaxDownforceSpeed { get; set; } = 80f;
|
||||
[Property, Feature( "Aerodinamics" )] private List<DownforcePoint> DownforcePoints { get; set; } = [];
|
||||
|
||||
private float _forwardSpeed;
|
||||
private float _frontalArea;
|
||||
|
||||
private float _sideArea;
|
||||
private float _sideSpeed;
|
||||
private float lateralDragForce;
|
||||
private float longitudinalDragForce;
|
||||
|
||||
private void SimulateAerodinamics( float dt )
|
||||
{
|
||||
if ( TotalSpeed < 1f )
|
||||
{
|
||||
longitudinalDragForce = 0;
|
||||
lateralDragForce = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
_frontalArea = Dimensions.x * Dimensions.z * 0.85f;
|
||||
_sideArea = Dimensions.y * Dimensions.z * 0.8f;
|
||||
_forwardSpeed = LocalVelocity.x.InchToMeter();
|
||||
_sideSpeed = LocalVelocity.y.InchToMeter();
|
||||
longitudinalDragForce = 0.5f * RHO * _frontalArea * FrontalCd * (_forwardSpeed * _forwardSpeed) * (_forwardSpeed > 0 ? -1f : 1f);
|
||||
lateralDragForce = 0.5f * RHO * _sideArea * SideCd * (_sideSpeed * _sideSpeed) * (_sideSpeed > 0 ? -1f : 1f);
|
||||
var force = new Vector3( longitudinalDragForce.MeterToInch(), lateralDragForce.MeterToInch(), 0 ).RotateAround( Vector3.Zero, WorldRotation );
|
||||
Body.ApplyForce( force );
|
||||
//DebugOverlay.Normal( WorldPosition, force );
|
||||
|
||||
float speedPercent = TotalSpeed / MaxDownforceSpeed;
|
||||
float forceCoeff = 1f - (1f - MathF.Pow( speedPercent, 2f ));
|
||||
|
||||
foreach ( DownforcePoint dp in DownforcePoints )
|
||||
Body.ApplyForceAt( Transform.World.PointToWorld( dp.Position ), forceCoeff.MeterToInch() * dp.MaxForce.MeterToInch() * -WorldRotation.Up );
|
||||
}
|
||||
}
|
||||
70
Code/Car/VeloXCar.Drift.cs
Normal file
70
Code/Car/VeloXCar.Drift.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
|
||||
|
||||
using Sandbox;
|
||||
using System;
|
||||
|
||||
namespace VeloX;
|
||||
|
||||
|
||||
public partial class VeloXCar
|
||||
{
|
||||
public const float MIN_DRIFT_ANGLE = 10f;
|
||||
public const float MIN_DRIFT_SPEED = 10f;
|
||||
public const float MAX_DRIFT_ANGLE = 110f;
|
||||
|
||||
public static readonly SoundFile SkidSound = SoundFile.Load( "sounds/tire/skid.wav" );
|
||||
|
||||
private SoundHandle _skidHandle;
|
||||
private float targetPitch;
|
||||
private float targetVolume;
|
||||
public float GetDriftAngle()
|
||||
{
|
||||
if ( !IsOnGround )
|
||||
return 0;
|
||||
|
||||
var velocity = Body.Velocity;
|
||||
var forward = WorldRotation.Forward;
|
||||
|
||||
// Early exit if speed is too low
|
||||
if ( TotalSpeed < MIN_DRIFT_SPEED )
|
||||
return 0f;
|
||||
|
||||
// Normalize the dot product calculation
|
||||
float dotProduct = velocity.Normal.Dot( forward );
|
||||
// Handle potential floating point precision issues
|
||||
float cosAngle = dotProduct;
|
||||
cosAngle = MathX.Clamp( cosAngle, -1f, 1f );
|
||||
|
||||
// Calculate angle in degrees
|
||||
float angle = MathF.Abs( MathX.RadianToDegree( MathF.Acos( cosAngle ) ) );
|
||||
|
||||
|
||||
// Check if angle is within drift range
|
||||
if ( angle >= MIN_DRIFT_ANGLE && angle <= MAX_DRIFT_ANGLE )
|
||||
return angle;
|
||||
|
||||
return 0f;
|
||||
}
|
||||
|
||||
protected virtual void UpdateDrift( float dt )
|
||||
{
|
||||
float driftAngle = GetDriftAngle();
|
||||
|
||||
float mul = (driftAngle - MIN_DRIFT_ANGLE) / (90 - MIN_DRIFT_ANGLE);
|
||||
|
||||
if ( !_skidHandle.IsValid() )
|
||||
_skidHandle = Sound.PlayFile( SkidSound );
|
||||
|
||||
if ( !_skidHandle.IsValid() )
|
||||
return;
|
||||
|
||||
targetVolume = mul;
|
||||
targetPitch = 0.75f + 0.25f * mul;
|
||||
|
||||
_skidHandle.Pitch += (targetPitch - _skidHandle.Pitch) * dt * 5f;
|
||||
_skidHandle.Volume += (targetVolume - _skidHandle.Volume) * dt * 10f;
|
||||
_skidHandle.Position = WorldPosition;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,365 +0,0 @@
|
||||
using Sandbox;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using VeloX.Powertrain;
|
||||
|
||||
namespace VeloX;
|
||||
|
||||
public partial class VeloXCar
|
||||
{
|
||||
|
||||
[Property, Feature( "Engine" )] Engine Engine { get; set; }
|
||||
|
||||
private void EngineThink( float dt )
|
||||
{
|
||||
Engine.Throttle = Input.Down( "Forward" ) ? 1 : 0;
|
||||
Engine.ForwardStep( 0, 0 );
|
||||
}
|
||||
|
||||
|
||||
//[Property, Feature( "Engine" ), Sync] public EngineState EngineState { get; set; }
|
||||
//[Property, Feature( "Engine" )] public EngineStream Stream { get; set; }
|
||||
//public EngineStreamPlayer StreamPlayer { get; set; }
|
||||
|
||||
//[Property, Feature( "Engine" )] public float MinRPM { get; set; } = 800;
|
||||
//[Property, Feature( "Engine" )] public float MaxRPM { get; set; } = 7000;
|
||||
//[Property, Feature( "Engine" ), Range( -1, 1 )]
|
||||
//public float PowerDistribution
|
||||
//{
|
||||
// get => powerDistribution; set
|
||||
// {
|
||||
// powerDistribution = value;
|
||||
// UpdatePowerDistribution();
|
||||
// }
|
||||
//}
|
||||
//[Property, Feature( "Engine" )] public float FlyWheelMass { get; set; } = 80f;
|
||||
//[Property, Feature( "Engine" )] public float FlyWheelRadius { get; set; } = 0.5f;
|
||||
//[Property, Feature( "Engine" )] public float FlywheelFriction { get; set; } = -6000;
|
||||
//[Property, Feature( "Engine" )] public float FlywheelTorque { get; set; } = 20000;
|
||||
//[Property, Feature( "Engine" )] public float EngineBrakeTorque { get; set; } = 2000;
|
||||
//[Property, Feature( "Engine" )]
|
||||
//public Dictionary<int, float> Gears { get; set; } = new()
|
||||
//{
|
||||
// [-1] = 2.5f,
|
||||
// [0] = 0f,
|
||||
// [1] = 2.8f,
|
||||
// [2] = 1.7f,
|
||||
// [3] = 1.2f,
|
||||
// [4] = 0.9f,
|
||||
// [5] = 0.75f,
|
||||
// [6] = 0.7f
|
||||
//};
|
||||
//[Property, Feature( "Engine" )] public float DifferentialRatio { get; set; } = 1f;
|
||||
//[Property, Feature( "Engine" ), Range( 0, 1 )] public float TransmissionEfficiency { get; set; } = 0.8f;
|
||||
//[Property, Feature( "Engine" )] private float MinRPMTorque { get; set; } = 5000f;
|
||||
//[Property, Feature( "Engine" )] private float MaxRPMTorque { get; set; } = 8000f;
|
||||
//[Sync] public int Gear { get; set; } = 0;
|
||||
//[Sync] public float Clutch { get; set; } = 1;
|
||||
//[Sync( SyncFlags.Interpolate )] public float EngineRPM { get; set; }
|
||||
//public float RPMPercent => (EngineRPM - MinRPM) / MaxRPM;
|
||||
|
||||
//private const float TAU = MathF.Tau;
|
||||
|
||||
//private int MinGear { get; set; }
|
||||
//private int MaxGear { get; set; }
|
||||
|
||||
//[Sync] public bool IsRedlining { get; private set; }
|
||||
|
||||
//private float flywheelVelocity;
|
||||
//private TimeUntil switchCD = 0;
|
||||
//private float groundedCount;
|
||||
//private float burnout;
|
||||
|
||||
//private float frontBrake;
|
||||
//private float rearBrake;
|
||||
|
||||
//private float availableFrontTorque;
|
||||
//private float availableRearTorque;
|
||||
|
||||
//private float avgSideSlip;
|
||||
//private float avgPoweredRPM;
|
||||
//private float avgForwardSlip;
|
||||
|
||||
//private float inputThrottle, inputBrake;
|
||||
//private bool inputHandbrake;
|
||||
//private float transmissionRPM;
|
||||
//private float powerDistribution;
|
||||
|
||||
//public float FlywheelRPM
|
||||
//{
|
||||
// get => flywheelVelocity * 60 / TAU;
|
||||
// set
|
||||
// {
|
||||
// flywheelVelocity = value * TAU / 60; EngineRPM = value;
|
||||
// }
|
||||
//}
|
||||
//private void UpdateGearList()
|
||||
//{
|
||||
// int minGear = 0;
|
||||
// int maxGear = 0;
|
||||
|
||||
// foreach ( var (gear, ratio) in Gears )
|
||||
// {
|
||||
|
||||
// if ( gear < minGear )
|
||||
// minGear = gear;
|
||||
|
||||
// if ( gear > maxGear )
|
||||
// maxGear = gear;
|
||||
|
||||
// if ( minGear != 0 || maxGear != 0 )
|
||||
// {
|
||||
// SwitchGear( 0, false );
|
||||
// }
|
||||
// }
|
||||
|
||||
// MinGear = minGear;
|
||||
// MaxGear = maxGear;
|
||||
|
||||
//}
|
||||
|
||||
|
||||
//public void SwitchGear( int index, bool cooldown = true )
|
||||
//{
|
||||
// if ( Gear == index ) return;
|
||||
// index = Math.Clamp( index, MinGear, MaxGear );
|
||||
|
||||
// if ( index == 0 || !cooldown )
|
||||
// switchCD = 0;
|
||||
// else
|
||||
// switchCD = 0.3f;
|
||||
// Clutch = 1;
|
||||
// Gear = index;
|
||||
//}
|
||||
|
||||
//public float TransmissionToEngineRPM( int gear ) => avgPoweredRPM * Gears[gear] * DifferentialRatio * 60 / TAU;
|
||||
//public float GetTransmissionMaxRPM( int gear ) => FlywheelRPM / Gears[gear] / DifferentialRatio;
|
||||
|
||||
//private void UpdatePowerDistribution()
|
||||
//{
|
||||
// if ( Wheels is null ) return;
|
||||
// int frontCount = 0, rearCount = 0;
|
||||
|
||||
// foreach ( var wheel in Wheels )
|
||||
// {
|
||||
// if ( wheel.IsFront )
|
||||
// frontCount++;
|
||||
// else
|
||||
// rearCount++;
|
||||
|
||||
// }
|
||||
|
||||
// float frontDistribution = 0.5f + PowerDistribution * 0.5f;
|
||||
|
||||
// float rearDistribution = 1 - frontDistribution;
|
||||
|
||||
// frontDistribution /= frontCount;
|
||||
// rearDistribution /= rearCount;
|
||||
|
||||
// foreach ( var wheel in Wheels )
|
||||
// if ( wheel.IsFront )
|
||||
// wheel.DistributionFactor = frontDistribution;
|
||||
// else
|
||||
// wheel.DistributionFactor = rearDistribution;
|
||||
//}
|
||||
|
||||
//private void EngineAccelerate( float torque, float dt )
|
||||
//{
|
||||
// var inertia = 0.5f * FlyWheelMass * FlyWheelRadius * FlyWheelRadius;
|
||||
// var angularAcceleration = torque / inertia;
|
||||
|
||||
// flywheelVelocity += angularAcceleration * dt;
|
||||
//}
|
||||
|
||||
//private float GetTransmissionTorque( int gear, float minTorque, float maxTorque )
|
||||
//{
|
||||
// var torque = FlywheelRPM.Remap( MinRPM, MaxRPM, minTorque, maxTorque, true );
|
||||
// torque *= (1 - Clutch);
|
||||
// torque = torque * Gears[gear] * DifferentialRatio * TransmissionEfficiency;
|
||||
|
||||
// return gear == -1 ? -torque : torque;
|
||||
//}
|
||||
|
||||
//private void AutoGearSwitch()
|
||||
//{
|
||||
// if ( ForwardSpeed < 100 && Input.Down( "Backward" ) )
|
||||
// {
|
||||
// SwitchGear( -1, false );
|
||||
// return;
|
||||
// }
|
||||
|
||||
// var currentGear = Gear;
|
||||
|
||||
// if ( currentGear < 0 && ForwardSpeed < -100 )
|
||||
// return;
|
||||
|
||||
// if ( Math.Abs( avgForwardSlip ) > 10 )
|
||||
// return;
|
||||
|
||||
// var gear = Math.Clamp( currentGear, 1, MaxGear );
|
||||
|
||||
// float minRPM = MinRPM, maxRPM = MaxRPM;
|
||||
|
||||
|
||||
// maxRPM *= 0.98f;
|
||||
|
||||
// float gearRPM;
|
||||
|
||||
|
||||
// for ( int i = 1; i <= MaxGear; i++ )
|
||||
// {
|
||||
// gearRPM = TransmissionToEngineRPM( i );
|
||||
|
||||
// if ( (i == 1 && gearRPM < minRPM) || (gearRPM > minRPM && gearRPM < maxRPM) )
|
||||
// {
|
||||
// gear = i;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// var threshold = minRPM + (maxRPM - minRPM) * (0.5 - Throttle * 0.3);
|
||||
// if ( gear < currentGear && gear > currentGear - 2 && EngineRPM > threshold )
|
||||
// return;
|
||||
|
||||
// SwitchGear( gear );
|
||||
//}
|
||||
|
||||
//private float EngineClutch( float dt )
|
||||
//{
|
||||
// if ( !switchCD )
|
||||
// {
|
||||
// inputThrottle = 0;
|
||||
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
// if ( inputHandbrake )
|
||||
// return 1;
|
||||
|
||||
// var absForwardSpeed = Math.Abs( ForwardSpeed );
|
||||
|
||||
// if ( groundedCount < 1 && absForwardSpeed > 30 )
|
||||
// return 1;
|
||||
|
||||
// if ( ForwardSpeed < -50 && inputBrake > 0 && Gear < 0 )
|
||||
// return 1;
|
||||
|
||||
// if ( absForwardSpeed > 200 )
|
||||
// return 0;
|
||||
|
||||
// return inputThrottle > 0.1f ? 0 : 1;
|
||||
//}
|
||||
|
||||
//private void EngineThink( float dt )
|
||||
//{
|
||||
// inputThrottle = Input.Down( "Forward" ) ? 1 : 0;
|
||||
// inputBrake = Input.Down( "Backward" ) ? 1 : 0;
|
||||
// inputHandbrake = Input.Down( "Jump" );
|
||||
// if ( burnout > 0 )
|
||||
// {
|
||||
// SwitchGear( 1, false );
|
||||
// if ( inputThrottle < 0.1f || inputBrake < 0.1f )
|
||||
// burnout = 0;
|
||||
// }
|
||||
// else
|
||||
// AutoGearSwitch();
|
||||
|
||||
// if ( Gear < 0 )
|
||||
// (inputBrake, inputThrottle) = (inputThrottle, inputBrake);
|
||||
|
||||
// var rpm = FlywheelRPM;
|
||||
|
||||
// var clutch = EngineClutch( dt );
|
||||
|
||||
// if ( inputThrottle > 0.1 && inputBrake > 0.1 && Math.Abs( ForwardSpeed ) < 50 )
|
||||
// {
|
||||
// burnout = MathX.Approach( burnout, 1, dt * 2 );
|
||||
// Clutch = 0;
|
||||
|
||||
// }
|
||||
// else if ( inputHandbrake )
|
||||
// {
|
||||
// frontBrake = 0f;
|
||||
// rearBrake = 0.5f;
|
||||
// Clutch = 1;
|
||||
// clutch = 1;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if ( (Gear == -1 || Gear == 1) && inputThrottle < 0.05f && inputBrake < 0.1f && groundedCount > 1 && rpm < MinRPM * 1.2f )
|
||||
// inputBrake = 0.2f;
|
||||
|
||||
// frontBrake = inputBrake * 0.5f;
|
||||
// rearBrake = inputBrake * 0.5f;
|
||||
// }
|
||||
|
||||
// clutch = MathX.Approach( Clutch, clutch, dt * ((Gear < 2 && inputThrottle > 0.1f) ? 6 : 2) );
|
||||
|
||||
// Clutch = clutch;
|
||||
|
||||
// var isRedlining = false;
|
||||
// transmissionRPM = 0;
|
||||
|
||||
// if ( Gear != 0 )
|
||||
// {
|
||||
// transmissionRPM = TransmissionToEngineRPM( Gear );
|
||||
// transmissionRPM = Gear < 0 ? -transmissionRPM : transmissionRPM;
|
||||
// rpm = (rpm * clutch) + (MathF.Max( 0, transmissionRPM ) * (1 - clutch));
|
||||
// }
|
||||
// var throttle = Throttle;
|
||||
|
||||
// var gearTorque = GetTransmissionTorque( Gear, MinRPMTorque, MaxRPMTorque );
|
||||
|
||||
// var availableTorque = gearTorque * throttle;
|
||||
|
||||
// if ( transmissionRPM < 0 )
|
||||
// {
|
||||
// availableTorque += gearTorque * 2;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// var engineBrakeTorque = GetTransmissionTorque( Gear, EngineBrakeTorque, EngineBrakeTorque );
|
||||
|
||||
// availableTorque -= engineBrakeTorque * (1 - throttle) * 0.5f;
|
||||
// }
|
||||
|
||||
// var maxRPM = MaxRPM;
|
||||
|
||||
// if ( rpm < MinRPM )
|
||||
// {
|
||||
// rpm = MinRPM;
|
||||
// }
|
||||
// else if ( rpm > maxRPM )
|
||||
// {
|
||||
|
||||
// if ( rpm > maxRPM * 1.2f )
|
||||
// availableTorque = 0;
|
||||
|
||||
// rpm = maxRPM;
|
||||
|
||||
// if ( Gear != MaxGear || groundedCount < Wheels.Count )
|
||||
// isRedlining = true;
|
||||
// }
|
||||
|
||||
// FlywheelRPM = Math.Clamp( rpm, 0, maxRPM );
|
||||
|
||||
// if ( burnout > 0 )
|
||||
// availableTorque += availableTorque * burnout * 0.1f;
|
||||
|
||||
// var front = 0.5f + PowerDistribution * 0.5f;
|
||||
// var rear = 1 - front;
|
||||
|
||||
// availableFrontTorque = availableTorque * front;
|
||||
// availableRearTorque = availableTorque * rear;
|
||||
|
||||
// throttle = MathX.Approach( throttle, inputThrottle, dt * 4 );
|
||||
|
||||
|
||||
// EngineAccelerate( FlywheelFriction + FlywheelTorque * throttle, dt );
|
||||
|
||||
// Throttle = throttle;
|
||||
|
||||
// IsRedlining = (isRedlining && inputThrottle > 0);
|
||||
//}
|
||||
|
||||
}
|
||||
@@ -1,53 +1,51 @@
|
||||
using Sandbox;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using VeloX.Utils;
|
||||
|
||||
namespace VeloX;
|
||||
|
||||
public partial class VeloXCar
|
||||
{
|
||||
public static float ExpDecay( float a, float b, float decay, float dt ) => b + (a - b) * MathF.Exp( -decay * dt );
|
||||
[Property, Feature( "Steer" )] public float SteerConeMaxSpeed { get; set; } = 1800;
|
||||
[Property, Feature( "Steer" )] public float SteerConeMaxAngle { get; set; } = 0.25f;
|
||||
[Property, Feature( "Steer" )] public float SteerConeChangeRate { get; set; } = 8;
|
||||
[Property, Feature( "Steer" )] public float CounterSteer { get; set; } = 0.1f;
|
||||
[Property, Feature( "Steer" )] public float MaxSteerAngle { get; set; } = 35f;
|
||||
[Property, Feature( "Steer" )] public float MaxSteerAngle { get; set; } = 40f;
|
||||
|
||||
[ConVar( "steer_return_speed" )]
|
||||
[Property] public static float SteerReturnSpeed { get; set; } = 6f;
|
||||
|
||||
[ConVar( "steer_speed" )]
|
||||
public static float SteerInputResponse { get; set; } = 3f;
|
||||
|
||||
|
||||
[ConVar( "assist_mult" )]
|
||||
public static float MaxSteerAngleMultiplier { get; set; } = 1f;
|
||||
public int CarDirection { get { return ForwardSpeed < 1 ? 0 : (VelocityAngle < 90 && VelocityAngle > -90 ? 1 : -1); } }
|
||||
public float VelocityAngle { get; private set; }
|
||||
|
||||
[Sync] public float Steering { get; private set; }
|
||||
|
||||
private float currentSteerAngle;
|
||||
private float inputSteer;
|
||||
|
||||
public static float SignedAngle( Vector3 from, Vector3 to, Vector3 axis )
|
||||
{
|
||||
float unsignedAngle = Vector3.GetAngle( from, to );
|
||||
|
||||
float cross_x = from.y * to.z - from.z * to.y;
|
||||
float cross_y = from.z * to.x - from.x * to.z;
|
||||
float cross_z = from.x * to.y - from.y * to.x;
|
||||
float sign = MathF.Sign( axis.x * cross_x + axis.y * cross_y + axis.z * cross_z );
|
||||
return unsignedAngle * sign;
|
||||
}
|
||||
public float VelocityAngle { get; private set; }
|
||||
public int CarDirection { get { return ForwardSpeed.InchToMeter() < 5 ? 0 : (VelocityAngle < 90 && VelocityAngle > -90 ? 1 : -1); } }
|
||||
private void UpdateSteering( float dt )
|
||||
{
|
||||
var inputSteer = Input.AnalogMove.y;
|
||||
inputSteer = Input.AnalogMove.y;
|
||||
|
||||
|
||||
VelocityAngle = 0;// -SignedAngle( Body.Velocity, WorldRotation.Forward, WorldRotation.Up );
|
||||
float targetSteerAngle = inputSteer * MaxSteerAngle;
|
||||
|
||||
//var steerConeFactor = Math.Clamp( TotalSpeed / SteerConeMaxSpeed, 0, 1 );
|
||||
//var steerCone = 1 - steerConeFactor * (1 - SteerConeMaxAngle);
|
||||
if ( !Input.Down( "Jump" ) )
|
||||
targetSteerAngle *= Math.Clamp( 1 - Math.Clamp( TotalSpeed / 3000, 0.01f, 0.9f ), -1, 1 );
|
||||
|
||||
inputSteer = ExpDecay( this.inputSteer, inputSteer, SteerConeChangeRate, dt );
|
||||
this.inputSteer = inputSteer;
|
||||
VelocityAngle = -Body.Velocity.SignedAngle( WorldRotation.Forward, WorldRotation.Up );
|
||||
|
||||
float target = -inputSteer * MaxSteerAngle;
|
||||
if ( CarDirection > 0 )
|
||||
target -= VelocityAngle * CounterSteer;
|
||||
float targetAngle = 0;
|
||||
|
||||
inputSteer = Math.Clamp( inputSteer, -1, 1 );
|
||||
Steering = inputSteer;
|
||||
SteerAngle = new( 0, target, 0 );
|
||||
if ( TotalSpeed > 150 && CarDirection > 0 && IsOnGround )
|
||||
targetAngle = VelocityAngle * MaxSteerAngleMultiplier;
|
||||
|
||||
float lerpSpeed = Math.Abs( inputSteer ) < 0.1f ? SteerReturnSpeed : SteerInputResponse;
|
||||
|
||||
currentSteerAngle = ExpDecay( currentSteerAngle, targetSteerAngle, lerpSpeed, Time.Delta );
|
||||
Steering = currentSteerAngle + targetAngle;
|
||||
SteerAngle = new( 0, Math.Clamp( Steering, -MaxSteerAngle, MaxSteerAngle ), 0 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace VeloX;
|
||||
|
||||
public partial class VeloXCar
|
||||
{
|
||||
private void WheelThink( in float dt )
|
||||
{
|
||||
foreach ( var w in Wheels )
|
||||
w.Update( this, dt );
|
||||
}
|
||||
}
|
||||
@@ -7,21 +7,33 @@ namespace VeloX;
|
||||
[Title( "VeloX - Car" )]
|
||||
public partial class VeloXCar : VeloXBase
|
||||
{
|
||||
|
||||
protected override void OnFixedUpdate()
|
||||
{
|
||||
if ( !IsDriver )
|
||||
if ( IsProxy )
|
||||
return;
|
||||
|
||||
base.OnFixedUpdate();
|
||||
|
||||
Brake = Math.Clamp( (Input.Down( "Jump" ) ? 1 : 0), 0, 1 );
|
||||
|
||||
var dt = Time.Delta;
|
||||
|
||||
EngineThink( dt );
|
||||
WheelThink( dt );
|
||||
//EngineThink( dt );
|
||||
SimulateAerodinamics( dt );
|
||||
//WheelThink( dt );
|
||||
UpdateSteering( dt );
|
||||
|
||||
UpdateUnflip( dt );
|
||||
UpdateDrift( dt );
|
||||
}
|
||||
|
||||
private void UpdateUnflip( float dt )
|
||||
{
|
||||
if ( Math.Abs( inputSteer ) < 0.1f )
|
||||
return;
|
||||
|
||||
if ( Math.Abs( WorldRotation.Angles().roll ) < 70 )
|
||||
return;
|
||||
|
||||
var angVel = Body.AngularVelocity;
|
||||
var force = inputSteer * Mass * Math.Clamp( 1 - angVel.x / 50, 0, 1 ) * 0.05f;
|
||||
Body.AngularVelocity -= Body.WorldRotation.Forward * force * dt;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user