commit a153e90c16beff5435e298b1ac0f0051d7ab7fe1 Author: Timerix Date: Sun Jun 14 02:20:41 2026 +0500 kamni diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e334c97 --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +# Build results +[Bb]in/ +.bin/ +[Dd]ebug/ +[Rr]elease/ +[Rr]eleases/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ +[Pp]ublish/ +*.log + +# IDE files +.vs/ +.vscode/ +.vshistory/ +.idea/ +.editorconfig +*.user +*.DotSettings + +# temp files +.old*/ +old/ +tmp/ +temp/ +*.tmp +*.temp diff --git a/Kamni.sln b/Kamni.sln new file mode 100644 index 0000000..f1d19f5 --- /dev/null +++ b/Kamni.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kamni", "Kamni\Kamni.csproj", "{FDBA03C5-E5E7-4847-96FA-860C5A496144}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FDBA03C5-E5E7-4847-96FA-860C5A496144}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDBA03C5-E5E7-4847-96FA-860C5A496144}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FDBA03C5-E5E7-4847-96FA-860C5A496144}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FDBA03C5-E5E7-4847-96FA-860C5A496144}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/Kamni/Kamni.csproj b/Kamni/Kamni.csproj new file mode 100644 index 0000000..f74cad9 --- /dev/null +++ b/Kamni/Kamni.csproj @@ -0,0 +1,16 @@ + + + Exe + net8.0 + latest + disable + enable + true + + + + + + + + diff --git a/Kamni/src/PathHelper.cs b/Kamni/src/PathHelper.cs new file mode 100644 index 0000000..f9b6a52 --- /dev/null +++ b/Kamni/src/PathHelper.cs @@ -0,0 +1,14 @@ +namespace Kamni; + +public static class PathHelper +{ + public static readonly IOPath UserDataDir = Path.Concat( +#if DEBUG + "!user_data", +#else + Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), +#endif + "Kamni"); + + public static readonly IOPath LogDir = Path.Concat(UserDataDir, "log"); +} \ No newline at end of file diff --git a/Kamni/src/Program.cs b/Kamni/src/Program.cs new file mode 100644 index 0000000..dbd9f02 --- /dev/null +++ b/Kamni/src/Program.cs @@ -0,0 +1,108 @@ +global using System; +global using System.Numerics; +global using DTLib.Logging; +global using DTLib.Filesystem; +global using File = DTLib.Filesystem.File; +global using Directory = DTLib.Filesystem.Directory; +global using Path = DTLib.Filesystem.Path; +using System.Linq; +using System.Runtime.InteropServices; +using Raylib_cs; +using static Raylib_cs.Raylib; + +namespace Kamni; + +public static class Program +{ + public static readonly Version GameVersion = new(0, 1, 0); + public static Settings Settings { get; private set; } = null!; + public static ILogger Logger { get; private set; } = null!; + + public static int Main(string[] args) + { + Settings = Settings.Load(); + Logger = new CompositeLogger( + new ConsoleLogger(), + new FileLogger($"{PathHelper.LogDir}engine.log") + ); + Logger.DebugLogEnabled = true; + // TODO: add game.log, script.log + // TODO: add /unsafe and other options to CSharpScript.toml + + var logger = new ContextLogger("Main", Logger); + logger.LogInfo($"Starting Kamni v{GameVersion}"); + + unsafe + { + SetTraceLogCallback(&RaylibLogHandler); + SetTraceLogLevel(TraceLogLevel.All); + } + + SetTargetFPS(Settings.target_fps); + + ConfigFlags windowFlags = 0; + windowFlags |= Settings.WindowMode switch + { + WindowMode.Window => ConfigFlags.ResizableWindow, + WindowMode.Borderless => ConfigFlags.BorderlessWindowMode, + WindowMode.Fullscreen => ConfigFlags.FullscreenMode, + _ => throw new ArgumentOutOfRangeException() + }; + SetConfigFlags(windowFlags); + + SetWindowMinSize(480, 360); + InitWindow(Settings.WindowMode == WindowMode.Window ? 720 : 0 , Settings.WindowMode == WindowMode.Window ? 480 : 0, $"Kamni v{GameVersion}"); + while (!WindowShouldClose()) + { + BeginDrawing(); + DrawFrame(); + EndDrawing(); + } + + CloseWindow(); + return 0; + } + + static float[] randomRotations = []; + static float sumT = 999999; + + static void DrawFrame() + { + + Vector2 center = new(GetRenderWidth() / 2f, GetRenderHeight() / 2f); + float deltaT = GetFrameTime(); + sumT += deltaT; + if (sumT > 0.5) + { + sumT = 0; + randomRotations = Enumerable.Range(0, 7).Select(_ => (float)Random.Shared.Next(-30, 30)).ToArray(); + } + ClearBackground(Color.DarkBlue); + DrawPoly(new(center.X, center.Y - 100), 5, 32, randomRotations[0], Color.Red); + DrawPoly(new(center.X - 100, center.Y - 50), 5, 32, randomRotations[1], Color.Pink); + DrawPoly(new(center.X + 100, center.Y - 50), 5, 32, randomRotations[2], Color.Orange); + DrawPoly(new(center.X - 150, center.Y + 25), 5, 32, randomRotations[3], Color.Purple); + DrawPoly(new(center.X + 150, center.Y + 25), 5, 32, randomRotations[4], Color.Yellow); + DrawPoly(new(center.X - 60, center.Y + 75), 5, 32, randomRotations[3], Color.SkyBlue); + DrawPoly(new(center.X + 60, center.Y + 75), 5, 32, randomRotations[4], Color.Green); + // DrawPoly(new (center.X + 75, center.Y + 25), 5, 32, 0, Color.Orange); + DrawFPS(5, 5); + } + + [UnmanagedCallersOnly(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])] + private static unsafe void RaylibLogHandler(int logLevel_, sbyte* text_, sbyte* args_) + { + string message = Logging.GetLogMessage(new IntPtr(text_), new IntPtr(args_)); + LogSeverity severity = (TraceLogLevel)logLevel_ switch + { + TraceLogLevel.Trace => LogSeverity.Debug, + TraceLogLevel.Debug => LogSeverity.Debug, + TraceLogLevel.Info => LogSeverity.Info, + TraceLogLevel.Warning => LogSeverity.Warn, + TraceLogLevel.Error => LogSeverity.Error, + TraceLogLevel.Fatal => LogSeverity.Error, + _ => throw new ArgumentOutOfRangeException(nameof(logLevel_)) + }; + Logger.Log("Raylib", severity, message); + } +} \ No newline at end of file diff --git a/Kamni/src/Settings.cs b/Kamni/src/Settings.cs new file mode 100644 index 0000000..1ba46d2 --- /dev/null +++ b/Kamni/src/Settings.cs @@ -0,0 +1,46 @@ +using Tomlyn; + +namespace Kamni; + +public enum WindowMode +{ + Window, Borderless, Fullscreen +} + +public class Settings +{ + public WindowMode WindowMode { get; set; } = WindowMode.Window; + + public int target_fps { get; set; } = 60; + + public static Settings Load() + { + Settings s; + if (!File.Exists(SettingsFile)) + { + s = new Settings(); + s.Save(); + return s; + } + + s = TomlSerializer.Deserialize(File.ReadAllText(SettingsFile), TomlSerializerOptions) + ?? throw new Exception($"can't load settings {SettingsFile}"); + return s; + } + + public void Save() + { + string settingsStr = TomlSerializer.Serialize(this); + File.WriteAllText(SettingsFile, settingsStr); + } + + private static readonly TomlSerializerOptions TomlSerializerOptions = new() + { + WriteIndented = true, + IndentSize = 4, + MaxDepth = 64, + DefaultIgnoreCondition = TomlIgnoreCondition.WhenWritingNull, + }; + + private static readonly IOPath SettingsFile = $"{PathHelper.UserDataDir}/settings.toml"; +} \ No newline at end of file