using OpenTK.Graphics.OpenGL4; using OpenTK.Windowing.Common; using OpenTK.Windowing.Common.Input; using OpenTK.Windowing.Desktop; using OpenTK.Windowing.GraphicsLibraryFramework; namespace Voxel { public class Window(int width, int height, string title) : GameWindow(GameWindowSettings.Default, new NativeWindowSettings() { ClientSize = (width, height), Title = title }) { public readonly int Width = width; public readonly int Height = height; public uint frames = 0; public double timeElapsed = 0; public event Action Update; public event Action Tick; private double _tickTime; public const double TICK_LENGTH = 1.0 / 20.0; // 20 TPS protected override void OnUpdateFrame(FrameEventArgs e) { base.OnUpdateFrame(e); _tickTime += e.Time; while (_tickTime >= TICK_LENGTH) { _tickTime -= TICK_LENGTH; Tick(); // run exactly once per tick } if (Input.GetKey(Keys.Escape)) { Close(); } if (Input.GetKey(Keys.F11)) { if (!IsFullscreen) WindowState = WindowState.Fullscreen; else WindowState = WindowState.Normal; } } protected override void OnRenderFrame(FrameEventArgs e) { base.OnRenderFrame(e); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); frames++; timeElapsed += e.Time; float alpha = (float)(_tickTime / Window.TICK_LENGTH); float deltaTime = (float)e.Time; if (timeElapsed >= 1) { Console.WriteLine("FPS: " + frames.ToString()); timeElapsed = 0; frames = 0; } Update.Invoke(deltaTime, alpha); Renderer.Render(); SwapBuffers(); } protected override void OnFramebufferResize(FramebufferResizeEventArgs e) { base.OnFramebufferResize(e); Camera.UpdateSize(e.Width, e.Height); GL.Viewport(0, 0, e.Width, e.Height); } protected override void OnLoad() { base.OnLoad(); GL.ClearColor(0.72f, 0.88f, 0.97f, 1f); GL.Enable(EnableCap.CullFace); GL.Enable(EnableCap.DepthTest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); CursorState = CursorState.Grabbed; VSync = VSyncMode.On; Camera.UpdateSize(Width, Height); } protected override void OnMouseMove(MouseMoveEventArgs e) { base.OnMouseMove(e); Camera.UpdateMouse(e.Delta); } protected override void OnKeyUp(KeyboardKeyEventArgs e) { base.OnKeyUp(e); Input.SetKey(e.Key, false); } protected override void OnKeyDown(KeyboardKeyEventArgs e) { base.OnKeyDown(e); Input.SetKey(e.Key, true); } protected override void OnMouseDown(MouseButtonEventArgs e) { base.OnMouseDown(e); Input.SetMouseButton(e.Button, true); } protected override void OnMouseUp(MouseButtonEventArgs e) { base.OnMouseUp(e); Input.SetMouseButton(e.Button, false); } protected override void OnMouseWheel(MouseWheelEventArgs e) { base.OnMouseWheel(e); Input.MouseWheel(e); } } }