using Car_simulation.Core.Components; using Car_simulation.Core.Physics; using Car_simulation.Audio; namespace Car_simulation.Core.Models { public class Car { // Basic properties public Vector2 Position = new Vector2(0, 0); public float Mass { get; set; } = 2000f; // Inputs public float ThrottleInput = 0f; public float BrakeInput = 0f; public float ClutchInput = 1f; public bool ForceClutch = false; public float SteeringInput = 0f; // Components public Engine Engine { get; private set; } public Drivetrain Drivetrain { get; private set; } public WheelSystem WheelSystem { get; private set; } public BrakeSystem BrakeSystem { get; private set; } public Aerodynamics Aerodynamics { get; private set; } // Derived properties public Vector2 Velocity => new Vector2(WheelSystem.CarSpeed, 0); public float Speed => WheelSystem.CarSpeed; // Audio private EngineSound _engineSound; private bool _audioEnabled = true; public Car() { InitializeComponents(); InitializeAudio(); } private void InitializeComponents() { Engine = new Engine(); WheelSystem = new WheelSystem(); WheelSystem.CarMass = Mass; WheelSystem.WheelCount = 4; WheelSystem.DrivenWheels = 2; Drivetrain = new Drivetrain(Engine, WheelSystem); BrakeSystem = new BrakeSystem(WheelSystem); Aerodynamics = new Aerodynamics(); } 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 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)" }; } public void Update(float deltaTime, float totalTime) { // Update inputs Engine.Throttle = ThrottleInput; Drivetrain.ClutchEngagement = 1f - ClutchInput; BrakeSystem.BrakeInput = BrakeInput; if (ForceClutch) Drivetrain.ClutchEngagement = 0f; // Update components Engine.UpdateWithTime(deltaTime, totalTime); Drivetrain.Update(deltaTime); // Apply resistance float resistanceForce = CalculateTotalResistanceForce(); WheelSystem.ApplyResistance(resistanceForce * WheelSystem.Radius, deltaTime); // Apply braking BrakeSystem.Update(deltaTime); // Update position Position += Velocity * deltaTime; // Update audio 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}"); } } public float CalculateTotalResistanceForce() { return Aerodynamics.CalculateTotalResistanceForce(Speed, Mass); } public float CalculateDragForce() { return Aerodynamics.CalculateDragForce(Speed); } public float CalculateRollingResistanceForce() { return Aerodynamics.CalculateRollingResistanceForce(Mass); } } }