initial commit with demo in main.c

This commit is contained in:
2026-10-04 20:29:49 +02:00
commit 7e909ac7eb
8 changed files with 419 additions and 0 deletions
+59
View File
@@ -0,0 +1,59 @@
#include "engine.h"
engine_internal_state_t *internal_state = NULL;
game_state_t *game_state = NULL;
void
engine_start() {
// main game loop
while(game_state->is_running) {
uint64_t start = SDL_GetPerformanceCounter();
// poll events
while (SDL_PollEvent(&game_state->event)) {
internal_state->engine_poll_events();
}
// call the user-defined framebuffer manipulation function
internal_state->engine_update_framebuffer();
// update the texture with the modified framebuffer
SDL_UpdateTexture(
internal_state->sdl_state->texture,
NULL, game_state->framebuffer,
internal_state->sdl_state->width * sizeof(uint32_t)
);
SDL_RenderClear(
internal_state->sdl_state->renderer
);
SDL_RenderTexture(
internal_state->sdl_state->renderer,
internal_state->sdl_state->texture,
NULL, NULL
);
SDL_RenderPresent(
internal_state->sdl_state->renderer
);
uint64_t end = SDL_GetPerformanceCounter();
double elapsed =
(double)(end - start) /
(double)SDL_GetPerformanceFrequency();
// cap the framerate at '1.0/TARGET_FRAME' fps
if (elapsed < TARGET_FRAME) {
SDL_Delay((TARGET_FRAME - elapsed) * 1000);
}
}
}
void
engine_stop() {
engine_sdl_destroy(internal_state->sdl_state);
free(internal_state);
free(game_state);
}
+148
View File
@@ -0,0 +1,148 @@
#include "engine.h"
#include "error.h"
#include <SDL3/SDL_render.h>
#include <SDL3/SDL_video.h>
bool
engine_sdl_init_state(engine_sdl_state_t **state) {
*state = (engine_sdl_state_t *)
malloc(sizeof(engine_sdl_state_t));
if (*state == NULL) {
eprintf("failed to initialize engine_sdl_state");
return RCODE_FAILURE;
}
(*state)->width = WINDOW_WIDTH;
(*state)->height = WINDOW_HEIGHT;
strncpy(
(*state)->window_name, DEFAULT_WINDOW_NAME,
WINDOW_NAME_LENGTH
);
return RCODE_SUCCESS;
}
bool
engine_sdl_init_root()
{
if (!SDL_Init(SDL_INIT_VIDEO)) {
eprintf("SDL_Init failed! %s\n", SDL_GetError());
return RCODE_FAILURE;
} else {
return RCODE_SUCCESS;
}
}
bool
engine_sdl_init_window(
engine_sdl_state_t* state
) {
state->window = SDL_CreateWindow(
state->window_name,
state->width, state->height, 0
);
if (state->window == NULL) {
eprintf("SDL_CreateWindow failed! %s\n", SDL_GetError());
SDL_Quit();
return RCODE_FAILURE;
}
return RCODE_SUCCESS;
}
bool
engine_sdl_init_renderer(
engine_sdl_state_t *state
) {
state->renderer = SDL_CreateRenderer(state->window, NULL);
if (state->renderer == NULL) {
eprintf("SDL_CreateRenderer failed! %s\n", SDL_GetError());
SDL_DestroyWindow(state->window);
SDL_Quit();
return RCODE_FAILURE;
}
return RCODE_SUCCESS;
}
bool
engine_sdl_init_texture(
engine_sdl_state_t *state
) {
state->texture = SDL_CreateTexture(
state->renderer, SDL_PIXELFORMAT_XRGB8888,
SDL_TEXTUREACCESS_STREAMING,
state->width, state->height
);
if (state->texture == NULL) {
eprintf("SDL_CreateTexture failed! %s\n", SDL_GetError());
SDL_DestroyWindow(state->window);
SDL_DestroyRenderer(state->renderer);
SDL_Quit();
return RCODE_FAILURE;
}
return RCODE_SUCCESS;
}
engine_sdl_state_t*
engine_sdl_init()
{
engine_sdl_state_t *state;
if (!engine_sdl_init_state(&state) ||
!engine_sdl_init_root() ||
!engine_sdl_init_window(state) ||
!engine_sdl_init_renderer(state) ||
!engine_sdl_init_texture(state)
) {
return NULL;
}
return state;
}
/**
* only call intentinally, not when engine_sdl_init fails
* -> it cleans up after itself already
*/
void
engine_sdl_destroy(
engine_sdl_state_t *state
) {
SDL_DestroyTexture(state->texture);
SDL_DestroyRenderer(state->renderer);
SDL_DestroyWindow(state->window);
SDL_Quit();
free(state);
}
bool
engine_init(
void (*engine_poll_events)(void),
void (*engine_update_framebuffer)(void)
) {
internal_state = (engine_internal_state_t *)
malloc(sizeof(engine_internal_state_t));
game_state = (game_state_t *)
malloc(sizeof(game_state_t));
internal_state->engine_poll_events
= engine_poll_events;
internal_state->engine_update_framebuffer
= engine_update_framebuffer;
internal_state->sdl_state = engine_sdl_init();
game_state->is_running = true;
game_state->width = internal_state->sdl_state->width;
game_state->height = internal_state->sdl_state->height;
return (game_state == NULL || internal_state == NULL)
? RCODE_FAILURE : RCODE_SUCCESS;
}
+37
View File
@@ -0,0 +1,37 @@
#include "engine.h"
#include "error.h"
// alter a pixel at an imaginary x & y coordinates
void
put_pixel(
unsigned int x,
unsigned int y,
uint32_t color
) {
uint16_t w = game_state->width;
uint16_t h = game_state->height;
if (x < 0 || x >= w || y < 0 || y >= h) {
eprintf(
"CRITICAL: attempted buffer overflow in put_pixel\n"
"at x = %d, y = %d", x, y
);
} else {
game_state->framebuffer[game_state->width * y + x]
= color;
}
}
// fill the entire framebuffer with a given color
void
clear_framebuffer(
uint32_t color
) {
uint16_t w = game_state->width;
uint16_t h = game_state->height;
for (int i = 0; i < w * h; i++) {
game_state->framebuffer[i] = color;
}
}