diff options
Diffstat (limited to 'in_practice/breakout/linux.c')
-rw-r--r-- | in_practice/breakout/linux.c | 131 |
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; +} |