using static SFML.Window.Mouse; namespace Car_simulation { public class Car { public Vector2 Position = new Vector2(0, 0); public Vector2 Velocity => new Vector2(WheelSystem.CarSpeed, 0); // Now directly from wheels public float Speed => WheelSystem.CarSpeed; public float Mass { get; set; } = 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.3f; 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(); // Set car mass in wheel system (so it's included in energy calculations) WheelSystem.CarMass = Mass; WheelSystem.WheelCount = WheelCount; WheelSystem.DrivenWheels = DrivenWheels; Drivetrain = new Drivetrain(Engine, WheelSystem); InitializeAudio(); } public List GetDisplayData() { return new List { $"Engine Energy: {Engine.FlywheelEnergy,7:F0} J", $"Engine Torque: {Engine.GetTorqueOutput(),7:F0} Nm", $"Engine RPM: {Engine.RPM,7:F0}", $"Total Energy: {WheelSystem.TotalEnergy,7:F0} J", $" (Wheel Rot: {WheelSystem.GetRotationalEnergy(),7:F0} J)", $" (Car Trans: {WheelSystem.GetTranslationalEnergy(),7:F0} J)", $"Wheel RPM: {WheelSystem.RPM,7:F0}", $"Vehicle: {Speed * 3.6f,7:F1} km/h", $"Throttle: {Engine.GetActualThrottle() * 100,6:F1}%", $"Power: {Engine.CurrentPower / 1000,6:F1} kW", $"Transmitted: {Drivetrain.TransmittedPower / 1000,6:F1} kW", $"Brake: {BrakeInput * 100,6:F1}%", $"Speed Diff: {Drivetrain.GetSpeedDifferenceRPM(),6:F0} RPM", $"Clutch: {ClutchInput * 100,6:F1}% disengaged", $"Clutch T: {Drivetrain.ClutchTorque,6:F0} Nm", $"Clutch Slip: {Drivetrain.GetClutchSlipPercent(),6:F1}%", $"Resistance: {CalculateTotalResistanceForce(),6:F1} N", $"Drag: {CalculateDragForce(),6:F1} N", $"Rolling: {CalculateRollingResistanceForce(),6:F1} N", $"Gear: {Drivetrain.GetCurrentGearName(),3} (Ratio: {Drivetrain.GearRatio:F2}:1)" }; } 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; if (ForceClutch) Drivetrain.ClutchEngagement = 0f; // Update engine Engine.Update(deltaTime); // Update drivetrain (transfers energy between engine and wheels+car) Drivetrain.Update(deltaTime); // Calculate and apply resistance float resistanceForce = CalculateTotalResistanceForce(); WheelSystem.ResistanceTorque = resistanceForce * WheelSystem.Radius; WheelSystem.ApplyResistance(deltaTime); // Apply braking ApplyBraking(deltaTime); // Update position based on velocity (which comes from WheelSystem) Position += Velocity * 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 ApplyBraking(float deltaTime) { if (BrakeInput <= 0) return; float brakeTorque = BrakeInput * 3000f; WheelSystem.ApplyTorque(-brakeTorque, deltaTime); } public float CalculateTotalResistanceForce() { float dragForce = CalculateDragForce(); float rollingForce = CalculateRollingResistanceForce(); return dragForce + rollingForce; } public float CalculateDragForce() { float speed = Speed; return 0.5f * AirDensity * DragCoefficient * FrontalArea * speed * speed; } public float CalculateRollingResistanceForce() { return RollingResistanceCoefficient * Mass * 9.81f; } } }