diff --git a/Core/Window.cs b/Core/Window.cs index 708ee0c..9109ee0 100644 --- a/Core/Window.cs +++ b/Core/Window.cs @@ -1,8 +1,10 @@ using OpenTK.Graphics.OpenGL4; +using OpenTK.Mathematics; using OpenTK.Windowing.Common; using OpenTK.Windowing.Desktop; using OpenTK.Windowing.GraphicsLibraryFramework; using Voxel.Graphics; +using Voxel.UI; namespace Voxel.Core { @@ -16,6 +18,8 @@ namespace Voxel.Core public event Action Update; public event Action Tick; + private Label _fpsLabel = new Label("FPS: N/A", 16, 16, 24, Vector4.One); + private double _tickTime; public const double TICK_LENGTH = 1.0 / 20.0; // 20 TPS @@ -55,14 +59,18 @@ namespace Voxel.Core timeElapsed += e.Time; float alpha = (float)(_tickTime / Window.TICK_LENGTH); float deltaTime = (float)e.Time; + if (timeElapsed >= 1) { Console.WriteLine("FPS: " + frames.ToString()); + _fpsLabel.Text = $"FPS: {frames}"; timeElapsed = 0; frames = 0; } Update.Invoke(deltaTime, alpha); + + Renderer.RenderLabel(_fpsLabel); Renderer.Render(); diff --git a/Entities/Player.cs b/Entities/Player.cs index 1bb49db..541c816 100644 --- a/Entities/Player.cs +++ b/Entities/Player.cs @@ -1,8 +1,10 @@ -using OpenTK.Mathematics; +using System.Net.Sockets; +using OpenTK.Mathematics; using OpenTK.Windowing.Common; using OpenTK.Windowing.GraphicsLibraryFramework; using Voxel.Core; using Voxel.Graphics; +using Voxel.UI; namespace Voxel.Entities { @@ -15,11 +17,14 @@ namespace Voxel.Entities private int _jumpTicks = 0; private Blocks _selectedBlock = Blocks.OakPlanks; - private Vector3 previousPosition; + private Vector3 _previousPosition; + private Label _positionLabel = new Label("Position:", 16, 48, 24, Vector4.One); + private Label _blockLabel = new Label("Selected Block:", 16, 80, 24, Vector4.One); public Player(Vector3 startPos, World world) : base(startPos, 0.5f, 1.8f, world) { Input.OnMouseWheel += SwitchBlock; + _blockLabel.Text = $"Selected block: {_selectedBlock}"; } public void PlaceBlock() @@ -48,7 +53,7 @@ namespace Voxel.Entities _world.UpdateChunkLoading(Position); - previousPosition = Position; + _previousPosition = Position; float forwards = 0; float sidewards = 0; @@ -94,6 +99,8 @@ namespace Voxel.Entities } } else _jumpTicks = 0; + + _positionLabel.Text = $"Position: {Position.X:F2}, {Position.Y:F2}, {Position.Z:F2}"; } public void Jump() @@ -104,9 +111,12 @@ namespace Voxel.Entities public void Update(float deltaTime, float alpha) { - Camera.Position = Vector3.Lerp(previousPosition, Position, alpha) + Vector3.UnitY * 1.62f; + Camera.Position = Vector3.Lerp(_previousPosition, Position, alpha) + Vector3.UnitY * 1.62f; Rotation = Camera.Yaw; + Renderer.RenderLabel(_positionLabel); + Renderer.RenderLabel(_blockLabel); + if (lastClick > 0) { lastClick -= deltaTime; @@ -159,7 +169,7 @@ namespace Voxel.Entities _blockIndex = (_blockIndex + direction + count) % count; _selectedBlock = BlockDefinitions.CreativeInventory[_blockIndex]; - + _blockLabel.Text = $"Selected block: {_selectedBlock}"; Console.WriteLine(_selectedBlock); } } diff --git a/Graphics/Camera.cs b/Graphics/Camera.cs index 24c7401..d6a5d17 100644 --- a/Graphics/Camera.cs +++ b/Graphics/Camera.cs @@ -14,8 +14,8 @@ namespace Voxel.Graphics public static float Speed = 5f; public static float ShiftSpeed = 20f; - private static int _width; - private static int _height; + public static int Width; + public static int Height; public static Matrix4 view => Matrix4.LookAt(Position, Position + Front, Vector3.UnitY); @@ -47,7 +47,7 @@ namespace Voxel.Graphics public static void UpdateProjection() { float fov = MathHelper.DegreesToRadians(FOV); - float aspectRatio = _width / (float)_height; + float aspectRatio = Width / (float)Height; float near = 0.1f; float far = 1000f; @@ -56,8 +56,8 @@ namespace Voxel.Graphics public static void UpdateSize(int width, int height) { - _width = width; - _height = height; + Width = width; + Height = height; UpdateProjection(); } diff --git a/Graphics/Renderer.cs b/Graphics/Renderer.cs index bd25413..84cc19a 100644 --- a/Graphics/Renderer.cs +++ b/Graphics/Renderer.cs @@ -1,6 +1,7 @@ using OpenTK.Graphics.OpenGL4; using OpenTK.Mathematics; using Voxel.Core; +using Voxel.UI; namespace Voxel.Graphics { @@ -131,11 +132,11 @@ namespace Voxel.Graphics _uiShader.Use(); - Matrix4 projection = Matrix4.CreateOrthographicOffCenter(0, WindowWidth, WindowHeight, 0, -1, 1); + Matrix4 projection = Matrix4.CreateOrthographicOffCenter(0, Camera.Width, Camera.Height, 0, -1, 1); _uiShader.SetMatrix4("projection", projection); _uiTexture.Bind(TextureUnit.Texture0); - _guiBatcher.DrawString("Voxel Engine v0.1", 15, 70, 20, Vector4.One); + _guiBatcher.DrawString("Voxel Engine v0.1", 16, 112, 24, Vector4.One); _guiBatcher.Render(); @@ -174,5 +175,11 @@ namespace Voxel.Graphics { _buffersDirty = true; } + + //temp + public static void RenderLabel(Label label) + { + _guiBatcher.DrawString(label.Text, label.X, label.Y, label.Size, label.Color); + } } } diff --git a/UI/CharData.cs b/UI/CharData.cs new file mode 100644 index 0000000..286a54c --- /dev/null +++ b/UI/CharData.cs @@ -0,0 +1,47 @@ +public static class CharWidth +{ + private static readonly Dictionary CharWidths = new Dictionary(); + + static CharWidth() + { + // Default for all ASCII + for (char c = (char)32; c <= (char)126; c++) + CharWidths[c] = 5.0f; + + // Override exceptions + CharWidths[' '] = 3.0f; + CharWidths['!'] = 1.0f; + CharWidths['"'] = 3.0f; + CharWidths['\''] = 1.0f; + CharWidths['('] = 3.0f; + CharWidths[')'] = 3.0f; + CharWidths['*'] = 3.0f; + CharWidths[','] = 1.0f; + CharWidths['.'] = 1.0f; + CharWidths[':'] = 1.0f; + CharWidths[';'] = 1.0f; + CharWidths['<'] = 4.0f; + CharWidths['>'] = 4.0f; + CharWidths['@'] = 6.0f; + CharWidths['I'] = 3.0f; + CharWidths['['] = 3.0f; + CharWidths[']'] = 3.0f; + CharWidths['`'] = 2.0f; + CharWidths['f'] = 4.0f; + CharWidths['i'] = 1.0f; + CharWidths['k'] = 4.0f; + CharWidths['l'] = 2.0f; + CharWidths['t'] = 3.0f; + CharWidths['{'] = 3.0f; + CharWidths['|'] = 1.0f; + CharWidths['}'] = 3.0f; + CharWidths['~'] = 6.0f; + } + + public static float GetWidth(char c) + { + if (CharWidths.TryGetValue(c, out float width)) + return width; + return 5.0f; + } +} \ No newline at end of file diff --git a/UI/GuiBatcher.cs b/UI/GuiBatcher.cs index 5aba069..144a24e 100644 --- a/UI/GuiBatcher.cs +++ b/UI/GuiBatcher.cs @@ -77,7 +77,10 @@ public class GuiBatcher ); DrawQuad(currentX, y, size, size, uv, color); - currentX += size * 0.8f; // Tighten horizontal spacing + + float charWidthPixels = (CharWidth.GetWidth(c) + 1) / 8; + float charWidthWorldUnits = size * charWidthPixels; + currentX += charWidthWorldUnits; } } } \ No newline at end of file diff --git a/UI/Label.cs b/UI/Label.cs new file mode 100644 index 0000000..9bac942 --- /dev/null +++ b/UI/Label.cs @@ -0,0 +1,21 @@ +using OpenTK.Mathematics; + +namespace Voxel.UI { + public class Label + { + public string Text; + public float X; + public float Y; + public float Size; + public Vector4 Color; + + public Label(string text, float x, float y, float size, Vector4 color) + { + Text = text; + X = x; + Y = y; + Size = size; + Color = color; + } + } +} \ No newline at end of file diff --git a/World/World.cs b/World/World.cs index 2e297e5..9d3fb6e 100644 --- a/World/World.cs +++ b/World/World.cs @@ -1,6 +1,7 @@ using OpenTK.Mathematics; using Voxel.Graphics; using Voxel.Physics; +using Voxel.UI; namespace Voxel.Core {