using Car_simulation.Core.Physics; namespace Car_simulation.Core.Components { public class WheelSystem : ICarComponent { // Physical properties public float Radius { get; set; } = 0.3f; public float WheelInertia { get; set; } = 2.0f; public float CarMass { get; set; } = 1500f; public int WheelCount { get; set; } = 4; public int DrivenWheels { get; set; } = 2; // State public float TotalEnergy { get; set; } = 0f; public float AngularVelocity => GetOmega(); public float RPM => GetRPM(); public float CarSpeed => GetCarSpeed(); // Derived properties public float GetTotalRotationalInertia() => WheelInertia * WheelCount; public float GetEquivalentCarInertia() => CarMass * Radius * Radius; public float GetTotalInertia() => GetTotalRotationalInertia() + GetEquivalentCarInertia(); // Calculations public float GetOmega() { if (TotalEnergy <= 0 || GetTotalInertia() <= 0) return 0f; return MathF.Sqrt(2f * TotalEnergy / GetTotalInertia()); } public float GetRPM() => AngularVelocity * PhysicsUtil.RAD_PER_SEC_TO_RPM; public float GetCarSpeed() => AngularVelocity * Radius; public float GetRotationalEnergy() { float omega = GetOmega(); return 0.5f * GetTotalRotationalInertia() * omega * omega; } public float GetTranslationalEnergy() { float speed = GetCarSpeed(); return 0.5f * CarMass * speed * speed; } public float GetEnergyFromSpeed(float speed) { float omega = speed / Radius; float rotationalEnergy = 0.5f * GetTotalRotationalInertia() * omega * omega; float translationalEnergy = 0.5f * CarMass * speed * speed; return rotationalEnergy + translationalEnergy; } public void SetSpeed(float speed) => TotalEnergy = GetEnergyFromSpeed(speed); public void ApplyWork(float work) { TotalEnergy += work; TotalEnergy = Math.Max(TotalEnergy, 0); } public void ApplyTorque(float torque, float deltaTime) { if (torque == 0) return; float work = torque * AngularVelocity * deltaTime; ApplyWork(work); } public void ApplyResistance(float resistanceTorque, float deltaTime) { if (resistanceTorque <= 0 || AngularVelocity == 0) return; float omega = AngularVelocity; if (MathF.Abs(omega) < 0.1f) return; float resistanceSign = -MathF.Sign(omega); float alpha = (resistanceSign * resistanceTorque) / GetTotalInertia(); float omegaNew = omega + alpha * deltaTime; if (MathF.Sign(omegaNew) != MathF.Sign(omega)) { omegaNew = 0; } float energyNew = 0.5f * GetTotalInertia() * omegaNew * omegaNew; TotalEnergy = Math.Max(energyNew, 0); } public void Update(float deltaTime) { // WheelSystem updates are handled by Car through other components } } }