using SFML.Graphics; using SFML.System; namespace Car_simulation.UI.Instruments { public class Gauge { private RectangleShape _background; private RectangleShape _needle; private Font _font; private Text _label; private Text _valueText; private Color _normalColor = Color.White; private Color _warningColor = new Color(255, 100, 100); public Vector2f Position { get; set; } public float Size { get; set; } = 200f; private float _value = 0f; private float _minValue; private float _maxValue; private float _valuePerMark; private float _linesPerMark; private string _displayText; public Gauge(Font font, Vector2f position, float size, float minValue, float maxValue, float valuePerMark, string _displayText, float linesPerMark) { _minValue = minValue; _maxValue = maxValue; _linesPerMark = linesPerMark _valuePerMark = valuePerMark; _font = font; Position = position; Size = size; Initialize(); } private void Initialize() { _background = new RectangleShape(new Vector2f(Size, Size)); _background.Position = Position; _background.FillColor = new Color(40, 40, 50); _background.OutlineThickness = 2; _background.OutlineColor = Color.White; float needleLength = Size * 0.4f; _needle = new RectangleShape(new Vector2f(needleLength, 4)); _needle.Position = new Vector2f( Position.X + Size / 2, Position.Y + Size / 2 ); _needle.FillColor = Color.Red; _needle.Origin = new Vector2f(needleLength * 0.875f, 2); _label = new Text(_displayText, _font, (uint)(Size * 0.1f)); _label.FillColor = Color.White; _label.Position = new Vector2f( Position.X + Size / 2 - _label.GetLocalBounds().Width / 2, Position.Y + Size * 0.80f ); _valueText = new Text("0", _font, (uint)(Size * 0.12f)); _valueText.FillColor = _normalColor; _valueText.Position = new Vector2f( Position.X + Size / 2 - 20, Position.Y + Size ); } public void Update(float value) { _value = value; _minValue float ratio = Math.Clamp(_value / _maxValue, 0f, 1f); float needleAngle = -45 + (270 * ratio); _needle.Rotation = needleAngle; _valueText.DisplayedString = $"{_value:F0}"; FloatRect bounds = _valueText.GetLocalBounds(); _valueText.Origin = new Vector2f(bounds.Width / 2, bounds.Height / 2); _valueText.Position = new Vector2f( Position.X + Size / 2, Position.Y + Size * 0.35f ); } public void Draw(RenderWindow window) { window.Draw(_background); DrawTickMarks(window); window.Draw(_needle); window.Draw(_label); window.Draw(_valueText); } private void DrawTickMarks(RenderWindow window) { float targetAngle = 270; int marks = (int)MathF.Ceiling(_maxValue / 1000) * 2; for (int i = marks; i >= 0; i--) { float angle = 135 + (i * (targetAngle / marks)); // 270° divided into 10 segments float startRadius = Size * 0.45f; float endRadius = Size * 0.42f; if (i % 2 == 0) // Major tick { endRadius = Size * 0.38f; float rpmValue = (i * 1000); Text label = new Text($"{rpmValue / 2000:F0}", _font, 12); label.FillColor = Color.White; float labelRadius = Size * 0.32f; float _radAngle = angle * (float)Math.PI / 180f; Vector2f labelPos = new Vector2f( Position.X + Size / 2 + labelRadius * (float)Math.Cos(_radAngle), Position.Y + Size / 2 + labelRadius * (float)Math.Sin(_radAngle) ); FloatRect bounds = label.GetLocalBounds(); label.Origin = new Vector2f(bounds.Width / 2, bounds.Height / 2); label.Position = labelPos; window.Draw(label); } float radAngle = angle * (float)Math.PI / 180f; Vector2f startPos = new Vector2f( Position.X + Size / 2 + startRadius * (float)Math.Cos(radAngle), Position.Y + Size / 2 + startRadius * (float)Math.Sin(radAngle) ); Vector2f endPos = new Vector2f( Position.X + Size / 2 + endRadius * (float)Math.Cos(radAngle), Position.Y + Size / 2 + endRadius * (float)Math.Sin(radAngle) ); Vertex[] line = new Vertex[2] { new Vertex(startPos, Color.White), new Vertex(endPos, Color.White) }; window.Draw(line, PrimitiveType.Lines); } } public void SetPosition(Vector2f position) { Position = position; Initialize(); // Re-initialize with new position } public void SetSize(float size) { Size = size; Initialize(); // Re-initialize with new size } } }