summaryrefslogtreecommitdiff
path: root/in_practice/breakout/linux.c
diff options
context:
space:
mode:
Diffstat (limited to 'in_practice/breakout/linux.c')
-rw-r--r--in_practice/breakout/linux.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/in_practice/breakout/linux.c b/in_practice/breakout/linux.c
new file mode 100644
index 0000000..2150ed9
--- /dev/null
+++ b/in_practice/breakout/linux.c
@@ -0,0 +1,131 @@
+#include "game.h"
+#include "sys.h"
+
+#include <SDL3/SDL.h>
+#include <GL/glew.h>
+
+#define DEBUG 1
+
+typedef struct {
+ SDL_Window *window;
+ i32 width;
+ i32 height;
+ SDL_Renderer *renderer;
+ u64 last_counter;
+ f32 dt;
+} sdl_context_t;
+
+static sdl_context_t init_sdl(i32 width, i32 height, i32 debug)
+{
+ sdl_context_t ctx = {0};
+ ctx.width = width;
+ ctx.height = height;
+ SDL_Init(SDL_INIT_VIDEO);
+ u64 flags = SDL_WINDOW_OPENGL;
+ SDL_CreateWindowAndRenderer("breakout", ctx.width, ctx.height, flags, &ctx.window, &ctx.renderer);
+ if (debug)
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
+ SDL_GLContext glctx = SDL_GL_CreateContext(ctx.window);
+ SDL_GL_MakeCurrent(ctx.window, glctx);
+ SDL_GL_SetSwapInterval(0);
+ ctx.last_counter = SDL_GetPerformanceCounter();
+ glewInit();
+ return ctx;
+}
+
+static void process_sdl_key(input_t *input, i32 scancode, i32 pressed)
+{
+ switch (scancode) {
+ case SDL_SCANCODE_ESCAPE:
+ input->escape.current = pressed;
+ break;
+ case SDL_SCANCODE_RIGHT:
+ input->right.current = pressed;
+ break;
+ case SDL_SCANCODE_LEFT:
+ input->left.current = pressed;
+ break;
+ case SDL_SCANCODE_SPACE:
+ input->space.current = pressed;
+ break;
+ default:
+ break;
+ }
+}
+
+static void process_sdl_events(game_t *game)
+{
+ SDL_Event event;
+ while (SDL_PollEvent(&event)) {
+ switch (event.type) {
+ case SDL_EVENT_KEY_DOWN:
+ case SDL_EVENT_KEY_UP:
+ process_sdl_key(&game->input, event.key.scancode, event.key.down);
+ default:
+ break;
+ }
+ }
+}
+
+static f32 get_elapsed(u64 last_counter)
+{
+ u64 frequency = SDL_GetPerformanceFrequency();
+ u64 current_counter = SDL_GetPerformanceCounter();
+ return (f32)(current_counter - last_counter) / (f32)frequency;
+}
+
+static void lock_framerate_sdl(sdl_context_t *ctx, i32 fps)
+{
+ f32 elapsed = get_elapsed(ctx->last_counter) * 1000.0f;
+ f32 target = 1000.0f / (f32)fps;
+ f32 sleep = target - elapsed;
+ if (sleep > 0)
+ SDL_Delay((u32)sleep);
+ do {
+ elapsed = get_elapsed(ctx->last_counter) * 1000.0f;
+ } while (elapsed < target);
+ ctx->dt = get_elapsed(ctx->last_counter);
+ ctx->last_counter = SDL_GetPerformanceCounter();
+}
+
+static void fps_info(f32 dt, i32 again)
+{
+ static f32 time = 0;
+ static i32 lastsec = 0;
+ static f32 sumdt = 0;
+ static i32 sumfps = 0;
+ static f32 frame_count = 0;
+ time += dt;
+ sumdt += dt;
+ sumfps += (i32)(1.0f / dt);
+ frame_count++;
+ i32 sec = (i32)time;
+ if (sec != 0 && sec % again == 0) {
+ if (lastsec != sec) {
+ f32 mean_dt = sumdt / frame_count;
+ f32 mean_fps = sumfps / frame_count;
+ info("time: %d dt: %f fps: %f", sec, mean_dt, mean_fps);
+ lastsec = sec;
+ sumdt = 0;
+ sumfps = 0;
+ frame_count = 0;
+ }
+ }
+}
+
+i32 main(void)
+{
+ sdl_context_t ctx = init_sdl(1600, 800, DEBUG);
+ game_t game = init_game(ctx.width, ctx.height);
+ while (game.running) {
+ process_sdl_events(&game);
+ process_input(&game);
+ update_game(&game, ctx.dt);
+ update_input(&game.input);
+ lock_framerate_sdl(&ctx, 60);
+ fps_info(ctx.dt, 10);
+ render_game(game);
+ SDL_GL_SwapWindow(ctx.window);
+ }
+ return 0;
+}