1using System.Numerics;
2using static SDL2.SDL;
3using static SDL2.SDL_ttf;
4using static SDL2.SDL_image;
5using Fjord.Input;
6using Fjord.Graphics;
7using Fjord.Scenes;
8using Fjord.Ui;
9
10namespace Fjord;
11
12public class Window
13{
14 public int Width;
15 public int Height;
16}
17public static class Game
18{
19 public static IntPtr SDLWindow;
20 public static IntPtr SDLRenderer;
21
22 public static Window Window = new();
23
24 internal static bool Running = true;
25
26 private static ulong _timeNow = 0;
27 private static ulong _timeLast = 0;
28 public static double DeltaTime { internal set; get; } = 0.0;
29
30 internal static float InputFPS = 0;
31 internal static float UpdateFPS = 0;
32 internal static float ProgramFPS = 0;
33
34 private static double _fpsCapLast = 0;
35 public static double FPSMax = 144;
36
37 public static ulong MillisecondsSinceStart => SDL_GetTicks64();
38 public static ulong SecondsSinceStart => SDL_GetTicks64() / 1000;
39
40 public static void Initialize(string title, int width, int height)
41 {
42 #if DEBUG
43 Debug.Log("Running in debug mode");
44 #else
45 Debug.Log("Running in release mode");
46 #endif
47
48 SDL_Init(SDL_INIT_EVERYTHING);
49
50 SDLWindow = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height,
51 SDL_WindowFlags.SDL_WINDOW_OPENGL | SDL_WindowFlags.SDL_WINDOW_RESIZABLE);
52
53 SDLRenderer = SDL_CreateRenderer(SDLWindow, 0, SDL_RendererFlags.SDL_RENDERER_ACCELERATED);
54
55 Window = new()
56 {
57 Width = width,
58 Height = height
59 };
60
61 SDL_SetRenderDrawBlendMode(SDLRenderer, SDL_BlendMode.SDL_BLENDMODE_BLEND);
62
63 IMG_Init(IMG_InitFlags.IMG_INIT_PNG);
64 Font.Initialize();
65 Debug.Initialize();
66 GlobalInput.Initialize();
67 SceneHandler.Initialize();
68 Debug.Log("Fjord Initalized");
69 }
70
71 public static void Stop()
72 {
73 Debug.Log("Fjord Stopped");
74 Running = false;
75 SDL_DestroyRenderer(SDLRenderer);
76 SDL_DestroyWindow(SDLWindow);
77 Font.Destroy();
78
79 List<string> PrintLogs = new();
80
81 foreach(DebugLog log in Debug.Logs)
82 {
83 if(log.level != LogLevel.User)
84 PrintLogs.Add(String.Format("[{0}] {1} {2} -> {3}", log.time, log.level.ToString(), log.sender, log.message));
85 else
86 PrintLogs.Add(String.Format("[{0}] {1} -> {2}", log.time, log.level.ToString(), log.message));
87 }
88
89 var Path = "./Logs/Log_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".txt";
90 if(!Directory.Exists("./Logs"))
91 {
92 Directory.CreateDirectory("./Logs");
93 }
94 if(PrintLogs.Count > 0)
95 {
96 File.WriteAllLines(Path, PrintLogs);
97 }
98 }
99
100 public static void Run()
101 {
102 while (Running)
103 {
104 var FPSCapNow = SDL_GetTicks64();
105 var FPSCapDelta = FPSCapNow - _fpsCapLast;
106
107 if(FPSCapDelta > 1000/FPSMax)
108 {
109 _timeNow = SDL_GetPerformanceCounter();
110 DeltaTime = ((_timeNow - _timeLast)*1000 / (double)SDL_GetPerformanceFrequency()) * 0.001;
111 if(DeltaTime > 0.01)
112 {
113 DeltaTime = 0.01;
114 }
115 _timeLast = _timeNow;
116
117 _fpsCapLast = FPSCapNow;
118
119 ulong programStart = SDL_GetPerformanceCounter();
120
121 ulong inputStart = SDL_GetPerformanceCounter();
122 EventHandler.HandleEvents();
123 ulong inputEnd = SDL_GetPerformanceCounter();
124
125 ulong updateStart = SDL_GetPerformanceCounter();
126 Update();
127 ulong updateEnd = SDL_GetPerformanceCounter();
128
129 ulong programEnd = SDL_GetPerformanceCounter();
130
131
132
133 var elapsed = (inputEnd - inputStart) / (float)SDL_GetPerformanceFrequency();
134 InputFPS = 1f / elapsed;
135
136 elapsed = (updateEnd - updateStart) / (float)SDL_GetPerformanceFrequency();
137 UpdateFPS = 1f / elapsed;
138
139 elapsed = (programEnd - programStart) / (float)SDL_GetPerformanceFrequency();
140 ProgramFPS = 1f / elapsed;
141
142 for (var i = 0; i < GlobalKeyboard.downKeys.Length; i++)
143 {
144 GlobalKeyboard.pressedKeys[i] = false;
145 GlobalKeyboard.downKeysLast[i] = GlobalKeyboard.downKeys[i];
146 }
147
148 foreach (var key in GlobalMouse.pressedKeys.Keys.ToList())
149 {
150 GlobalMouse.pressedKeys[key] = false;
151 GlobalMouse.downKeysLast[key] = GlobalMouse.downKeys[key];
152 }
153 GlobalMouse.downKeys[MB.ScrollDown] = false;
154 GlobalMouse.downKeys[MB.ScrollLeft] = false;
155 GlobalMouse.downKeys[MB.ScrollRight] = false;
156 GlobalMouse.downKeys[MB.ScrollUp] = false;
157
158 if(SceneHandler.LoadedScenes.All(s => SceneHandler.Scenes[s].MouseInsideScene != true))
159 {
160 SDL_ShowCursor(SDL_ENABLE);
161 }
162
163 GC.Collect();
164 GC.WaitForPendingFinalizers();
165 }
166 }
167 }
168
169 public static void Update()
170 {
171 SDL_GetWindowSize(SDLWindow, out Window.Width, out Window.Height);
172
173 SDL_SetRenderDrawColor(SDLRenderer, 0, 0, 0, 255);
174 SDL_RenderClear(SDLRenderer);
175
176 foreach (string id in new List<string>(SceneHandler.LoadedScenes))
177 {
178 SceneHandler.Scenes[id].UpdateCall();
179 }
180
181 Draw.DrawDrawBuffer(Draw.drawBuffer, null);
182 Draw.drawBuffer = new();
183
184 SDL_RenderPresent(SDLRenderer);
185
186 if (GlobalKeyboard.Pressed(Key.D, Mod.LShift, Mod.LCtrl))
187 {
188 if (!SceneHandler.IsLoaded<InspectorScene>())
189 SceneHandler.Load<InspectorScene>();
190 else
191 SceneHandler.Unload<InspectorScene>();
192 }
193
194 if (GlobalKeyboard.Pressed(Key.C, Mod.LShift, Mod.LCtrl))
195 {
196 if (!SceneHandler.IsLoaded<ConsoleScene>()) {
197 SceneHandler.Load<ConsoleScene>();
198 } else
199 SceneHandler.Unload<ConsoleScene>();
200 }
201
202 if (GlobalKeyboard.Pressed(Key.F, Mod.LShift, Mod.LCtrl))
203 {
204 if (!SceneHandler.IsLoaded<PerformanceScene>())
205 {
206 SceneHandler.Load<PerformanceScene>();
207 }
208 else
209 {
210 PerformanceScene scene = SceneHandler.Get<PerformanceScene>()!;
211 if (scene.WindowSize.X < 450)
212 {
213 if(scene.Position < 2)
214 scene.SetRelativeWindowSize(scene.RelativeWindowSize.x, scene.RelativeWindowSize.y, scene.RelativeWindowSize.w + 0.14f, scene.RelativeWindowSize.h);
215 else
216 scene.SetRelativeWindowSize(scene.RelativeWindowSize.x - 0.14f, scene.RelativeWindowSize.y, scene.RelativeWindowSize.w, scene.RelativeWindowSize.h);
217 scene.Size = true;
218 } else
219 {
220 if (scene.Position < 2)
221 scene.SetRelativeWindowSize(scene.RelativeWindowSize.x, scene.RelativeWindowSize.y, scene.RelativeWindowSize.w - 0.14f, scene.RelativeWindowSize.h);
222 else
223 scene.SetRelativeWindowSize(scene.RelativeWindowSize.x + 0.14f, scene.RelativeWindowSize.y, scene.RelativeWindowSize.w, scene.RelativeWindowSize.h);
224 scene.Size = false;
225 SceneHandler.Unload<PerformanceScene>();
226 }
227
228 }
229 }
230 }
231}