using Car_simulation.Core.Models; using Car_simulation.Input; using Car_simulation.UI; using SFML.Graphics; using SFML.System; using SFML.Window; namespace Car_simulation { internal class Program { private Car _car = new Car(); private RenderWindow _window; private Font _font; private DisplayManager _displayManager; private CarInputHandler _inputHandler; // Timing private Clock _clock = new Clock(); private Time _timePerUpdate = Time.FromSeconds(1.0f / 60.0f); private Time _accumulatedTime = Time.Zero; private float _totalTime = 0.0f; private long _updateCount = 0; static void Main(string[] args) { Program program = new Program(); program.Run(); } private void Run() { InitializeWindow(); InitializeUI(); InitializeInput(); while (_window.IsOpen) { _window.DispatchEvents(); Time elapsed = _clock.Restart(); _accumulatedTime += elapsed; while (_accumulatedTime >= _timePerUpdate) { Update(_timePerUpdate.AsSeconds()); _accumulatedTime -= _timePerUpdate; } Render(); } _window.Close(); Console.WriteLine($"\nSimulation stopped after {_updateCount} updates"); } private void InitializeWindow() { _window = new RenderWindow(new VideoMode(1000, 800), "Car Simulation", Styles.Default); _window.SetVisible(true); _window.SetFramerateLimit(60); _window.SetKeyRepeatEnabled(false); _window.Closed += (sender, e) => _window.Close(); _window.Resized += OnWindowResized; _window.KeyPressed += OnKeyPressed; } private void OnWindowResized(object sender, SizeEventArgs e) { _window.SetView(new View(new FloatRect(0, 0, e.Width, e.Height))); _displayManager?.HandleResize(e.Width, e.Height); } private void OnKeyPressed(object sender, KeyEventArgs e) { // Toggle debug info with F3 if (e.Code == Keyboard.Key.F3) { _displayManager?.ToggleDebugInfo(); } // Pass key event to input handler _inputHandler?.OnKeyPressed(e); } private void InitializeUI() { try { _font = new Font("arial.ttf"); } catch { _font = new Font("C:/Windows/Fonts/arial.ttf"); } _displayManager = new DisplayManager(_window, _font); } private void InitializeInput() { _inputHandler = new CarInputHandler(); _window.KeyPressed += (sender, e) => _inputHandler.OnKeyPressed(e); _window.KeyReleased += (sender, e) => _inputHandler.OnKeyReleased(e); } private void Update(float deltaTime) { _inputHandler.ProcessInput(deltaTime); _totalTime += deltaTime; ApplyInputToCar(deltaTime); _car.Update(deltaTime, _totalTime); // Update display with current car state _displayManager.Update(_car, deltaTime, _totalTime, _updateCount); if (_inputHandler.InputState.Quit) _window.Close(); _updateCount++; } private void ApplyInputToCar(float deltaTime) { var input = _inputHandler.InputState; _car.ThrottleInput += input.ThrottleChange; _car.BrakeInput += input.BrakeChange; _car.ThrottleInput = Math.Clamp(_car.ThrottleInput, 0f, 1f); _car.BrakeInput = Math.Clamp(_car.BrakeInput, 0f, 1f); if (input.ClutchUp) _car.ClutchInput += deltaTime * 0.5f; if (input.ClutchDown) _car.ClutchInput -= deltaTime * 0.5f; _car.ClutchInput = Math.Clamp(_car.ClutchInput, 0f, 1f); if (input.ToggleForceClutch) _car.ForceClutch = !_car.ForceClutch; if (input.GearUp) _car.Drivetrain.GearUp(); if (input.GearDown) _car.Drivetrain.GearDown(); } private void Render() { _displayManager.Draw(); _window.Display(); } } }