201 lines
6.7 KiB
C#
201 lines
6.7 KiB
C#
using SFML.Graphics;
|
|
using SFML.System;
|
|
|
|
namespace Car_simulation.UI.Instruments
|
|
{
|
|
public class Speedometer
|
|
{
|
|
private RectangleShape _background;
|
|
private RectangleShape _needle;
|
|
private Font _font;
|
|
private Text _label;
|
|
private Text _speedText;
|
|
private Text _gearText;
|
|
private Color _normalColor = Color.White;
|
|
private Color _highlightColor = new Color(0, 150, 255);
|
|
|
|
public Vector2f Position { get; set; }
|
|
public float Size { get; set; } = 200f;
|
|
|
|
private float _currentSpeed = 0f;
|
|
private string _currentGear = "N";
|
|
private const float MAX_SPEED = 200f; // km/h
|
|
|
|
public Speedometer(Font font)
|
|
{
|
|
_font = font;
|
|
Initialize();
|
|
}
|
|
|
|
public Speedometer(Font font, Vector2f position, float size)
|
|
{
|
|
_font = font;
|
|
Position = position;
|
|
Size = size;
|
|
Initialize();
|
|
}
|
|
|
|
private void Initialize()
|
|
{
|
|
// Background
|
|
_background = new RectangleShape(new Vector2f(Size, Size));
|
|
_background.Position = Position;
|
|
_background.FillColor = new Color(40, 40, 50);
|
|
_background.OutlineThickness = 2;
|
|
_background.OutlineColor = Color.White;
|
|
|
|
// Needle
|
|
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.Green;
|
|
_needle.Origin = new Vector2f(needleLength * 0.875f, 2);
|
|
|
|
// Labels
|
|
_label = new Text("SPEED", _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.05f
|
|
);
|
|
|
|
_speedText = new Text("0 km/h", _font, (uint)(Size * 0.1f));
|
|
_speedText.FillColor = _normalColor;
|
|
_speedText.Position = new Vector2f(
|
|
Position.X + Size / 2 - 40,
|
|
Position.Y + Size * 0.25f
|
|
);
|
|
|
|
_gearText = new Text($"GEAR {_currentGear}", _font, (uint)(Size * 0.14f));
|
|
_gearText.FillColor = _highlightColor;
|
|
_gearText.Position = new Vector2f(
|
|
Position.X + Size * 0.5f,
|
|
Position.Y + Size * 1.1f
|
|
);
|
|
}
|
|
|
|
public void Update(float speed)
|
|
{
|
|
_currentSpeed = speed;
|
|
float speedKmh = speed * 3.6f;
|
|
|
|
// Update needle angle (-90° to +180° rotation)
|
|
float speedRatio = Math.Clamp(speedKmh / MAX_SPEED, 0f, 1f);
|
|
float needleAngle = -90 + (270 * speedRatio);
|
|
_needle.Rotation = needleAngle;
|
|
|
|
// Update speed text
|
|
_speedText.DisplayedString = $"{speedKmh:F1} km/h";
|
|
|
|
// Center speed text
|
|
FloatRect bounds = _speedText.GetLocalBounds();
|
|
_speedText.Origin = new Vector2f(bounds.Width / 2, bounds.Height / 2);
|
|
_speedText.Position = new Vector2f(
|
|
Position.X + Size / 2,
|
|
Position.Y + Size * 0.35f
|
|
);
|
|
}
|
|
|
|
public void UpdateGear(string gear)
|
|
{
|
|
_currentGear = gear;
|
|
_gearText.DisplayedString = $"GEAR {gear}";
|
|
|
|
// Center gear text
|
|
FloatRect bounds = _gearText.GetLocalBounds();
|
|
_gearText.Origin = new Vector2f(bounds.Width / 2, bounds.Height / 2);
|
|
_gearText.Position = new Vector2f(
|
|
Position.X + Size / 2,
|
|
Position.Y + Size * 1.1f
|
|
);
|
|
}
|
|
|
|
public void Draw(RenderWindow window)
|
|
{
|
|
window.Draw(_background);
|
|
|
|
// Draw tick marks
|
|
DrawTickMarks(window);
|
|
|
|
window.Draw(_needle);
|
|
window.Draw(_label);
|
|
window.Draw(_speedText);
|
|
window.Draw(_gearText);
|
|
}
|
|
|
|
private void DrawTickMarks(RenderWindow window)
|
|
{
|
|
for (int i = 0; i <= 10; i++)
|
|
{
|
|
float angle = -90 + (i * 27); // 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;
|
|
|
|
// Add number label for major ticks
|
|
float speedValue = (i * MAX_SPEED / 10f);
|
|
Text label = new Text($"{speedValue: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
|
|
}
|
|
|
|
public void SetGearColor(Color color)
|
|
{
|
|
_gearText.FillColor = color;
|
|
}
|
|
|
|
public void SetNeedleColor(Color color)
|
|
{
|
|
_needle.FillColor = color;
|
|
}
|
|
}
|
|
} |