diff --git a/BuildTime.txt b/BuildTime.txt index e5f6166..d02b029 100644 --- a/BuildTime.txt +++ b/BuildTime.txt @@ -1 +1 @@ -2026-04-03 22:22:40 \ No newline at end of file +2026-04-04 12:15:03 \ No newline at end of file diff --git a/GitCommit.txt b/GitCommit.txt index a721cec..8f4061e 100644 --- a/GitCommit.txt +++ b/GitCommit.txt @@ -1 +1 @@ -1c1f85c \ No newline at end of file +836f199 \ No newline at end of file diff --git a/Gui/Apps/DemoLauncher.cs b/Gui/Apps/DemoLauncher.cs index af176e8..961b935 100644 --- a/Gui/Apps/DemoLauncher.cs +++ b/Gui/Apps/DemoLauncher.cs @@ -50,6 +50,7 @@ namespace CMLeonOS.Gui.Apps new AppMetadata("Mandelbrot", () => { return new Apps.Demos.Mandelbrot(); }, Icons.Icon_Mandelbrot, Color.Black ), new AppMetadata("Cube3D (OSGD)", () => { return new Apps.Demos.Cube3D(); }, AppManager.DefaultAppIcon, Color.Black ), new AppMetadata("Pyramid3D (OSGD)", () => { return new Apps.Demos.Pyramid3D(); }, AppManager.DefaultAppIcon, Color.Black ), + new AppMetadata("GLXGears (OSGD)", () => { return new Apps.Demos.GLXGears(); }, AppManager.DefaultAppIcon, Color.Black ), }; private const string message = "Demo Launcher"; diff --git a/Gui/Apps/Demos/GLXGears.cs b/Gui/Apps/Demos/GLXGears.cs new file mode 100644 index 0000000..6fa4fbc --- /dev/null +++ b/Gui/Apps/Demos/GLXGears.cs @@ -0,0 +1,132 @@ +using CMLeonOS; +using CMLeonOS.Gui.UILib; +using CMLeonOS.OSGraphicDraw; +using System; +using System.Drawing; + +namespace CMLeonOS.Gui.Apps.Demos +{ + internal class GLXGears : Process + { + internal GLXGears() : base("GLXGears", ProcessType.Application) { } + + private readonly WindowManager wm = ProcessManager.GetProcess(); + private AppWindow window; + + private double redAngle = 0d; + private double greenAngle = 0d; + private double blueAngle = 0d; + + private int fps = 0; + private int frames = 0; + private int lastSecond = -1; + + private const double ScenePitch = 0.48d; + private const double SceneYaw = -0.36d; + private const double FovScale = 260d; + private const double CameraDistance = 10.5d; + + private Vec3 TransformPoint(Vec3 p) + { + p = Vec3.RotateX(p, ScenePitch); + p = Vec3.RotateY(p, SceneYaw); + return p; + } + + private void Draw3DLine(Vec3 a, Vec3 b, Color color) + { + a = TransformPoint(a); + b = TransformPoint(b); + Renderer3D.DrawLine3D(window, a, b, color, FovScale, CameraDistance); + } + + private void DrawGear(Vec3 center, double outerRadius, double innerRadius, double depth, int teeth, double angle, Color color) + { + int ringCount = teeth * 2; + Vec3[] frontOuter = new Vec3[ringCount]; + Vec3[] backOuter = new Vec3[ringCount]; + Vec3[] frontInner = new Vec3[ringCount]; + Vec3[] backInner = new Vec3[ringCount]; + + double frontZ = center.Z + (depth * 0.5d); + double backZ = center.Z - (depth * 0.5d); + + for (int i = 0; i < ringCount; i++) + { + bool tooth = (i % 2) == 0; + double radius = tooth ? outerRadius : outerRadius * 0.84d; + double t = (i / (double)ringCount) * (Math.PI * 2d) + angle; + double c = Math.Cos(t); + double s = Math.Sin(t); + + frontOuter[i] = new Vec3(center.X + (radius * c), center.Y + (radius * s), frontZ); + backOuter[i] = new Vec3(center.X + (radius * c), center.Y + (radius * s), backZ); + + frontInner[i] = new Vec3(center.X + (innerRadius * c), center.Y + (innerRadius * s), frontZ); + backInner[i] = new Vec3(center.X + (innerRadius * c), center.Y + (innerRadius * s), backZ); + } + + for (int i = 0; i < ringCount; i++) + { + int n = (i + 1) % ringCount; + + Draw3DLine(frontOuter[i], frontOuter[n], color); + Draw3DLine(backOuter[i], backOuter[n], color); + Draw3DLine(frontOuter[i], backOuter[i], color); + + Draw3DLine(frontInner[i], frontInner[n], color); + Draw3DLine(backInner[i], backInner[n], color); + Draw3DLine(frontInner[i], backInner[i], color); + + if ((i % 2) == 0) + { + Draw3DLine(frontOuter[i], frontInner[i], color); + Draw3DLine(backOuter[i], backInner[i], color); + } + } + } + + private void RenderGears() + { + window.Clear(Color.FromArgb(14, 16, 23)); + + DrawGear(new Vec3(-2.6d, -0.8d, 0.0d), 1.85d, 0.72d, 0.75d, 20, redAngle, Color.FromArgb(238, 95, 95)); + DrawGear(new Vec3(2.35d, -0.95d, 0.0d), 1.65d, 0.66d, 0.75d, 18, greenAngle, Color.FromArgb(108, 214, 132)); + DrawGear(new Vec3(0.25d, 2.0d, 0.0d), 1.45d, 0.58d, 0.75d, 16, blueAngle, Color.FromArgb(113, 170, 255)); + + window.DrawString("OSGD GLXGears", Color.FromArgb(182, 194, 214), 10, 8); + window.DrawString("FPS: " + fps.ToString(), Color.FromArgb(182, 194, 214), 10, 26); + wm.Update(window); + } + + public override void Start() + { + base.Start(); + window = new AppWindow(this, 220, 120, 620, 420); + window.Title = "GLXGears"; + window.CanResize = true; + window.Closing = TryStop; + wm.AddWindow(window); + + RenderGears(); + } + + public override void Run() + { + redAngle += 0.055d; + greenAngle -= 0.082d; + blueAngle += 0.105d; + + DateTime now = DateTime.Now; + frames++; + if (lastSecond != now.Second) + { + fps = frames; + frames = 0; + lastSecond = now.Second; + } + + RenderGears(); + } + } +} diff --git a/Gui/Apps/Tetris.cs b/Gui/Apps/Tetris.cs index 896386e..cf74427 100644 --- a/Gui/Apps/Tetris.cs +++ b/Gui/Apps/Tetris.cs @@ -20,6 +20,9 @@ namespace CMLeonOS.Gui.Apps private readonly Random random = new Random(); private AppWindow window; + private Button slowButton; + private Button normalButton; + private Button fastButton; private readonly int[] board = new int[BoardWidth * BoardHeight]; private int[] curX = new int[4]; @@ -33,6 +36,7 @@ namespace CMLeonOS.Gui.Apps private int level = 1; private int frameCounter = 0; private int dropFrames = 36; + private int speedMode = 1; // 0: Slow, 1: Normal, 2: Fast private bool dirty = true; @@ -72,6 +76,59 @@ namespace CMLeonOS.Gui.Apps return (y * BoardWidth) + x; } + private int GetBaseDropFrames() + { + if (speedMode == 0) return 48; + if (speedMode == 2) return 24; + return 36; + } + + private int GetMinDropFrames() + { + if (speedMode == 0) return 14; + if (speedMode == 2) return 7; + return 10; + } + + private void UpdateDropFramesFromMode() + { + int baseFrames = GetBaseDropFrames(); + int minFrames = GetMinDropFrames(); + dropFrames = Math.Max(minFrames, baseFrames - ((level - 1) * 2)); + } + + private string GetSpeedModeLabel() + { + if (speedMode == 0) return "Slow"; + if (speedMode == 2) return "Fast"; + return "Normal"; + } + + private void SetSpeedButtonStyle() + { + if (slowButton == null || normalButton == null || fastButton == null) return; + + slowButton.Background = speedMode == 0 ? UITheme.Accent : UITheme.SurfaceMuted; + slowButton.Border = speedMode == 0 ? UITheme.AccentDark : UITheme.SurfaceBorder; + slowButton.Foreground = speedMode == 0 ? Color.White : UITheme.TextPrimary; + + normalButton.Background = speedMode == 1 ? UITheme.Accent : UITheme.SurfaceMuted; + normalButton.Border = speedMode == 1 ? UITheme.AccentDark : UITheme.SurfaceBorder; + normalButton.Foreground = speedMode == 1 ? Color.White : UITheme.TextPrimary; + + fastButton.Background = speedMode == 2 ? UITheme.Accent : UITheme.SurfaceMuted; + fastButton.Border = speedMode == 2 ? UITheme.AccentDark : UITheme.SurfaceBorder; + fastButton.Foreground = speedMode == 2 ? Color.White : UITheme.TextPrimary; + } + + private void SetSpeedMode(int mode) + { + speedMode = Math.Max(0, Math.Min(2, mode)); + UpdateDropFramesFromMode(); + SetSpeedButtonStyle(); + dirty = true; + } + private bool InBounds(int x, int y) { return x >= 0 && x < BoardWidth && y >= 0 && y < BoardHeight; @@ -174,7 +231,7 @@ namespace CMLeonOS.Gui.Apps else score += 800 * level; level = 1 + (lines / 10); - dropFrames = Math.Max(10, 36 - ((level - 1) * 2)); + UpdateDropFramesFromMode(); dirty = true; } } @@ -271,7 +328,7 @@ namespace CMLeonOS.Gui.Apps score = 0; lines = 0; level = 1; - dropFrames = 36; + UpdateDropFramesFromMode(); frameCounter = 0; gameOver = false; SpawnPiece(); @@ -306,6 +363,15 @@ namespace CMLeonOS.Gui.Apps case ConsoleKeyEx.Spacebar: HardDrop(); break; + case ConsoleKeyEx.D1: + SetSpeedMode(0); + break; + case ConsoleKeyEx.D2: + SetSpeedMode(1); + break; + case ConsoleKeyEx.D3: + SetSpeedMode(2); + break; } } @@ -357,10 +423,12 @@ namespace CMLeonOS.Gui.Apps window.DrawString("Score: " + score.ToString(), Color.White, sideX, 62); window.DrawString("Lines: " + lines.ToString(), Color.White, sideX, 82); window.DrawString("Level: " + level.ToString(), Color.White, sideX, 102); + window.DrawString("Speed: " + GetSpeedModeLabel(), Color.White, sideX, 122); window.DrawString("Keys:", Color.FromArgb(186, 198, 216), sideX, 136); window.DrawString("Arrows Move", Color.FromArgb(186, 198, 216), sideX, 154); window.DrawString("Up Rotate", Color.FromArgb(186, 198, 216), sideX, 172); window.DrawString("Space Drop", Color.FromArgb(186, 198, 216), sideX, 190); + window.DrawString("1/2/3 Speed", Color.FromArgb(186, 198, 216), sideX, 208); if (gameOver) { @@ -389,6 +457,22 @@ namespace CMLeonOS.Gui.Apps window.OnKeyPressed = OnKeyPressed; wm.AddWindow(window); + slowButton = new Button(window, 206, 338, 62, 20); + slowButton.Text = "Slow"; + slowButton.OnClick = (_, _) => SetSpeedMode(0); + wm.AddWindow(slowButton); + + normalButton = new Button(window, 274, 338, 72, 20); + normalButton.Text = "Normal"; + normalButton.OnClick = (_, _) => SetSpeedMode(1); + wm.AddWindow(normalButton); + + fastButton = new Button(window, 352, 338, 62, 20); + fastButton.Text = "Fast"; + fastButton.OnClick = (_, _) => SetSpeedMode(2); + wm.AddWindow(fastButton); + + SetSpeedButtonStyle(); ResetGame(); Render(); }