Add project files.
This commit is contained in:
221
Car simulation/Car.cs
Normal file
221
Car simulation/Car.cs
Normal file
@@ -0,0 +1,221 @@
|
||||
using static SFML.Window.Mouse;
|
||||
|
||||
namespace Car_simulation
|
||||
{
|
||||
public class Car
|
||||
{
|
||||
public Vector2 Position = new Vector2(0, 0);
|
||||
public Vector2 Velocity = new Vector2(0, 0);
|
||||
public float Speed => Velocity.Length;
|
||||
|
||||
public float Mass = 1500f; // kg
|
||||
public int WheelCount = 4;
|
||||
public int DrivenWheels = 2;
|
||||
|
||||
public float ThrottleInput = 0f;
|
||||
public float BrakeInput = 0f;
|
||||
public float ClutchInput = 1f; // 0 = engaged, 1 = disengaged
|
||||
public bool ForceClutch = false;
|
||||
public float SteeringInput = 0f;
|
||||
|
||||
// Aerodynamics
|
||||
private const float AirDensity = 1.225f;
|
||||
public float DragCoefficient = 0.1f;
|
||||
public float FrontalArea = 2.2f; // m²
|
||||
public float RollingResistanceCoefficient = 0.015f;
|
||||
|
||||
// Components
|
||||
public Engine Engine;
|
||||
public Drivetrain Drivetrain;
|
||||
public WheelSystem WheelSystem;
|
||||
|
||||
private EngineSound _engineSound;
|
||||
private bool _audioEnabled = true;
|
||||
|
||||
public Car()
|
||||
{
|
||||
Engine = new Engine();
|
||||
WheelSystem = new WheelSystem();
|
||||
Drivetrain = new Drivetrain(Engine, WheelSystem);
|
||||
|
||||
// Initial setup
|
||||
WheelSystem.WheelCount = WheelCount;
|
||||
WheelSystem.DrivenWheels = DrivenWheels;
|
||||
|
||||
InitializeAudio();
|
||||
}
|
||||
|
||||
private void InitializeAudio()
|
||||
{
|
||||
try
|
||||
{
|
||||
_engineSound = new EngineSound();
|
||||
_engineSound.SetEngineState(Engine.IdleRPM, 0f);
|
||||
_engineSound.StartSound();
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Audio initialization failed: {ex.Message}");
|
||||
_audioEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
Engine.Throttle = ThrottleInput;
|
||||
Drivetrain.ClutchEngagement = 1f - ClutchInput; // Convert: 0 input = 1 engagement
|
||||
|
||||
if (ForceClutch)
|
||||
Drivetrain.ClutchEngagement = 0f;
|
||||
|
||||
float resistanceTorque = CalculateResistanceTorque();
|
||||
WheelSystem.ResistanceTorque = resistanceTorque;
|
||||
|
||||
Drivetrain.Update(deltaTime);
|
||||
WheelSystem.ApplyResistance(deltaTime);
|
||||
|
||||
float engineLoad = Drivetrain.CalculateEngineLoad(deltaTime);
|
||||
Engine.Update(deltaTime, engineLoad);
|
||||
|
||||
UpdateVehicleMotion(deltaTime);
|
||||
ApplyBraking(deltaTime);
|
||||
|
||||
if (_audioEnabled)
|
||||
{
|
||||
UpdateAudio();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateAudio()
|
||||
{
|
||||
try
|
||||
{
|
||||
float throttle = Engine.GetActualThrottle();
|
||||
_engineSound.SetEngineState(Engine.RPM, throttle);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Audio update error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateVehicleMotion(float deltaTime)
|
||||
{
|
||||
// Calculate net force
|
||||
float tractiveForce = CalculateTractiveForce();
|
||||
float resistanceForce = CalculateTotalResistanceForce();
|
||||
float netForce = tractiveForce - resistanceForce;
|
||||
|
||||
// Calculate acceleration: a = F / m
|
||||
float acceleration = netForce / Mass;
|
||||
|
||||
// Update velocity: v = v₀ + a·Δt
|
||||
if (Velocity.Length > 0)
|
||||
{
|
||||
Vector2 direction = Velocity.Normalized();
|
||||
float newSpeed = Velocity.Length + acceleration * deltaTime;
|
||||
newSpeed = Math.Max(newSpeed, 0); // Don't go backwards without reverse gear
|
||||
Velocity = direction * newSpeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Starting from standstill
|
||||
Velocity = new Vector2(acceleration * deltaTime, 0);
|
||||
}
|
||||
|
||||
Position += Velocity * deltaTime;
|
||||
|
||||
// Sync wheel speed with actual vehicle speed (with slip allowance)
|
||||
float currentWheelSpeed = Velocity.Length;
|
||||
WheelSystem.SetSpeed(currentWheelSpeed);
|
||||
}
|
||||
|
||||
private float CalculateTractiveForce()
|
||||
{
|
||||
// 1. Get the torque available at the wheels
|
||||
float wheelTorque = Drivetrain.ClutchTorque * Drivetrain.Efficiency;
|
||||
|
||||
// 2. Convert torque to theoretical force: F = τ / r
|
||||
float theoreticalForce = wheelTorque / WheelSystem.Radius;
|
||||
|
||||
// 3. Account for weight distribution and driven wheels
|
||||
// Normal load on driven wheels = (DrivenWheels / WheelCount) * Weight
|
||||
float drivenWheelNormalLoad = (DrivenWheels / (float)WheelCount) * Mass * 9.81f;
|
||||
|
||||
// 4. Calculate maximum tractive force based on friction (tire grip)
|
||||
float frictionCoefficient = 1.2f; // Typical tire on dry asphalt
|
||||
float maxTractiveForce = drivenWheelNormalLoad * frictionCoefficient;
|
||||
|
||||
// 5. Limit the force by what the tires can actually grip
|
||||
// Also handle direction (forward/reverse)
|
||||
if (theoreticalForce > 0)
|
||||
{
|
||||
return Math.Min(theoreticalForce, maxTractiveForce);
|
||||
}
|
||||
else
|
||||
{
|
||||
// For reverse or engine braking
|
||||
return Math.Max(theoreticalForce, -maxTractiveForce);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyBraking(float deltaTime)
|
||||
{
|
||||
if (BrakeInput <= 0) return;
|
||||
|
||||
float brakeTorque = BrakeInput * 500f; // 500 Nm max brake torque
|
||||
|
||||
WheelSystem.ApplyTorque(-brakeTorque, deltaTime);
|
||||
}
|
||||
|
||||
public float CalculateTotalResistanceForce()
|
||||
{
|
||||
float dragForce = CalculateDragForce();
|
||||
float rollingForce = CalculateRollingResistanceForce();
|
||||
return dragForce + rollingForce;
|
||||
}
|
||||
|
||||
private float CalculateDragForce()
|
||||
{
|
||||
// F_drag = 0.5 * ρ * Cd * A * v²
|
||||
float speed = Speed;
|
||||
return 0.5f * AirDensity * DragCoefficient * FrontalArea * speed * speed;
|
||||
}
|
||||
|
||||
private float CalculateRollingResistanceForce()
|
||||
{
|
||||
// F_rolling = C_r * m * g
|
||||
return RollingResistanceCoefficient * Mass * 9.81f;
|
||||
}
|
||||
|
||||
// Convert resistance force to wheel torque
|
||||
public float CalculateResistanceTorque()
|
||||
{
|
||||
float totalForce = CalculateTotalResistanceForce();
|
||||
return totalForce * WheelSystem.Radius;
|
||||
}
|
||||
|
||||
public void DisplayUpdate()
|
||||
{
|
||||
Console.SetCursorPosition(0, 0);
|
||||
Console.WriteLine($"Engine Energy: {Engine.FlywheelEnergy,7:F0} J");
|
||||
Console.WriteLine($"Engine Torque: {Engine.GetTorqueOutput(),7:F0} Nm");
|
||||
Console.WriteLine($"Engine RPM: {Engine.RPM,7:F0}");
|
||||
Console.WriteLine($"Wheel Energy: {WheelSystem.WheelEnergy,7:F0} J");
|
||||
Console.WriteLine($"Wheel RPM: {WheelSystem.RPM,7:F0}");
|
||||
Console.WriteLine($"Vehicle: {Speed * 3.6f,7:F1} km/h");
|
||||
Console.WriteLine($"Throttle: {Engine.GetActualThrottle() * 100,6:F1}%");
|
||||
Console.WriteLine($"Power: {Engine.CurrentPower / 1000,6:F1} kW");
|
||||
Console.WriteLine($"Transmitted: {Drivetrain.TransmittedPower / 1000,6:F1} kW");
|
||||
Console.WriteLine($"Brake: {BrakeInput * 100,6:F1}%");
|
||||
Console.WriteLine($"Clutch: {ClutchInput * 100,6:F1}% disengaged");
|
||||
Console.WriteLine($"Speed Diff: {Drivetrain.GetSpeedDifferenceRPM(),6:F0} RPM");
|
||||
Console.WriteLine($"Clutch T: {Drivetrain.ClutchTorque,6:F0} Nm");
|
||||
Console.WriteLine($"Resistance: {CalculateTotalResistanceForce(),6:F1} N");
|
||||
Console.WriteLine($"Drag: {CalculateDragForce(),6:F1} N");
|
||||
Console.WriteLine($"Rolling: {CalculateRollingResistanceForce(),6:F1} N");
|
||||
Console.WriteLine($"Gear: {Drivetrain.GetCurrentGearName(),3} (Ratio: {Drivetrain.GearRatio:F2}:1)");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user