Test hot reloading
This commit is contained in:
parent
8ad090b582
commit
b4f41103f2
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
|||||||
.cache
|
.cache
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
main
|
main
|
||||||
|
*.so
|
||||||
|
*.o
|
||||||
|
49
compile
49
compile
@ -1,9 +1,46 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
CC=clang
|
BUILD_TYPE="debug"
|
||||||
CFLAGS="-g -Wall $(pkg-config --cflags sdl2)"
|
|
||||||
LIBS="$(pkg-config --libs sdl2)"
|
|
||||||
SRC=src/*.c
|
|
||||||
OUT=main
|
|
||||||
|
|
||||||
(set -x ; $CC $CFLAGS $LIBS $SRC -o $OUT)
|
while [[ $# > 0 ]];do
|
||||||
|
case $1 in
|
||||||
|
--release)
|
||||||
|
BUILD_TYPE="release"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*|-*|--*)
|
||||||
|
echo "Unknown option $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
CC=clang
|
||||||
|
CFLAGS="-Wall $(pkg-config --cflags sdl2)"
|
||||||
|
LIBS="$(pkg-config --libs sdl2)"
|
||||||
|
MAIN=src/main.c
|
||||||
|
MAIN_FLAGS=""
|
||||||
|
GAME=src/game.c
|
||||||
|
GAME_FLAGS="-DNDEBUG"
|
||||||
|
OUT=main
|
||||||
|
GAME_OUT=""
|
||||||
|
|
||||||
|
if [[ $BUILD_TYPE == "debug" ]]; then
|
||||||
|
CFLAGS+=" -g"
|
||||||
|
MAIN_FLAGS="-ldl -Wl,-rpath,\$ORIGIN"
|
||||||
|
GAME_FLAGS+=" -fPIC -shared"
|
||||||
|
GAME_OUT="-o game.so"
|
||||||
|
MAIN+=" src/game.c"
|
||||||
|
else
|
||||||
|
CFLAGS+=" -O3"
|
||||||
|
MAIN_FLAGS="-DNDEBUG"
|
||||||
|
GAME_FLAGS+=" -c"
|
||||||
|
MAIN+=" game.o"
|
||||||
|
fi
|
||||||
|
|
||||||
|
LOCKFILE="game.so.lock"
|
||||||
|
touch $LOCKFILE && (set -x ; $CC $CFLAGS $GAME_FLAGS $LIBS $GAME $GAME_OUT)
|
||||||
|
if [[ -f $LOCKFILE ]];then
|
||||||
|
rm $LOCKFILE
|
||||||
|
fi
|
||||||
|
(set -x ; $CC $CFLAGS $MAIN_FLAGS $LIBS $MAIN -o $OUT)
|
||||||
|
102
src/game.c
Normal file
102
src/game.c
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
#include "game.h"
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define LIB "game.so"
|
||||||
|
#define LOCKFILE "game.so.lock"
|
||||||
|
|
||||||
|
static void *handle = NULL;
|
||||||
|
static long int last_mtime;
|
||||||
|
void (*update_character)(int window_height) = NULL;
|
||||||
|
void (*render_character)(SDL_Renderer *renderer) = NULL;
|
||||||
|
|
||||||
|
bool load_symbols(void) {
|
||||||
|
struct stat st;
|
||||||
|
if (stat(LOCKFILE, &st) == 0) {
|
||||||
|
// If lock file exists, don't reload the library
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stat(LIB, &st) != 0) {
|
||||||
|
perror("Error checking library stat: ");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
long int mtime = st.st_mtim.tv_sec * 1000000000 + st.st_mtim.tv_nsec;
|
||||||
|
if (mtime == last_mtime) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_mtime = mtime;
|
||||||
|
|
||||||
|
if (handle) {
|
||||||
|
close_library();
|
||||||
|
}
|
||||||
|
|
||||||
|
handle = dlopen(LIB, RTLD_NOW | RTLD_GLOBAL);
|
||||||
|
if (!handle) {
|
||||||
|
fprintf(stderr, "Failed to load library: %s\n", dlerror());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dlerror(); // Clear errors
|
||||||
|
|
||||||
|
*(void **)(&update_character) = dlsym(handle, "update_character");
|
||||||
|
*(void **)(&render_character) = dlsym(handle, "render_character");
|
||||||
|
|
||||||
|
char *error = dlerror();
|
||||||
|
if (error != NULL) {
|
||||||
|
fprintf(stderr, "Failed to load function symbol: %s", error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_library(void) {
|
||||||
|
if (handle) {
|
||||||
|
dlclose(handle);
|
||||||
|
handle = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#include "SDL_rect.h"
|
||||||
|
#include "SDL_render.h"
|
||||||
|
|
||||||
|
typedef struct state State;
|
||||||
|
struct state {
|
||||||
|
float delta;
|
||||||
|
float speed;
|
||||||
|
SDL_Rect character;
|
||||||
|
};
|
||||||
|
|
||||||
|
static State game = {
|
||||||
|
.delta = 1.f / 60.f,
|
||||||
|
.speed = 1600.f,
|
||||||
|
.character = {.x = 375, .y = 0, .w = 50, .h = 50},
|
||||||
|
};
|
||||||
|
|
||||||
|
void update_character(int window_height) {
|
||||||
|
game.character.y += game.speed * game.delta;
|
||||||
|
if (game.character.y < 0 ||
|
||||||
|
game.character.y + game.character.h > window_height) {
|
||||||
|
game.speed *= -1.f;
|
||||||
|
|
||||||
|
if (game.character.y < 0) {
|
||||||
|
game.character.y = 0;
|
||||||
|
} else {
|
||||||
|
game.character.y = window_height - game.character.h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_character(SDL_Renderer *renderer) {
|
||||||
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||||
|
SDL_RenderFillRect(renderer, &game.character);
|
||||||
|
}
|
||||||
|
#endif
|
22
src/game.h
Normal file
22
src/game.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SDL_render.h"
|
||||||
|
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#define DEBUG 0
|
||||||
|
#else
|
||||||
|
#define DEBUG 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
bool load_symbols(void);
|
||||||
|
void close_library(void);
|
||||||
|
|
||||||
|
extern void (*update_character)(int window_height);
|
||||||
|
extern void (*render_character)(SDL_Renderer *renderer);
|
||||||
|
#else
|
||||||
|
void update_character(int window_height);
|
||||||
|
void render_character(SDL_Renderer *renderer);
|
||||||
|
#endif
|
29
src/main.c
29
src/main.c
@ -1,9 +1,16 @@
|
|||||||
|
#include "game.h"
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <SDL2/SDL_events.h>
|
#include <SDL2/SDL_events.h>
|
||||||
#include <SDL2/SDL_render.h>
|
#include <SDL2/SDL_render.h>
|
||||||
#include <SDL2/SDL_video.h>
|
#include <SDL2/SDL_video.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#define DEBUG 0
|
||||||
|
#else
|
||||||
|
#define DEBUG 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#define WINDOW_WIDTH 800
|
#define WINDOW_WIDTH 800
|
||||||
#define WINDOW_HEIGHT 600
|
#define WINDOW_HEIGHT 600
|
||||||
|
|
||||||
@ -21,6 +28,13 @@ int main(void) {
|
|||||||
|
|
||||||
SDL_Event event = {0};
|
SDL_Event event = {0};
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
if (!load_symbols()) {
|
||||||
|
fprintf(stderr, "Failed to load game library\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
while (running) {
|
while (running) {
|
||||||
while (SDL_PollEvent(&event)) {
|
while (SDL_PollEvent(&event)) {
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
@ -30,13 +44,28 @@ int main(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
if (!load_symbols()) {
|
||||||
|
fprintf(stderr, "Failed to load game library\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
update_character(WINDOW_HEIGHT);
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
||||||
|
|
||||||
SDL_RenderClear(renderer);
|
SDL_RenderClear(renderer);
|
||||||
|
|
||||||
|
render_character(renderer);
|
||||||
|
|
||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
close_library();
|
||||||
|
#endif
|
||||||
|
|
||||||
SDL_DestroyRenderer(renderer);
|
SDL_DestroyRenderer(renderer);
|
||||||
|
|
||||||
SDL_DestroyWindow(window);
|
SDL_DestroyWindow(window);
|
||||||
|
Loading…
Reference in New Issue
Block a user