Hot reloading: Makefile, inotify, epoll, and splitting .c/.h files
This commit is contained in:
parent
44dc3ccd48
commit
a5c6569162
2
.gitignore
vendored
2
.gitignore
vendored
@ -5,3 +5,5 @@
|
||||
/sprites.o
|
||||
/dod
|
||||
/boids
|
||||
/boids_main
|
||||
/libboids.so
|
||||
|
9
Makefile
9
Makefile
@ -1,4 +1,4 @@
|
||||
CFLAGS=-g -fsanitize=address -Wall -Wextra -pedantic -O0
|
||||
CFLAGS=-g -fsanitize=address -fno-omit-frame-pointer -Wall -Wextra -pedantic -O0
|
||||
CC=gcc
|
||||
|
||||
.PHONY: build clean run all
|
||||
@ -14,8 +14,11 @@ sprites.o: sprites.c sprites.h lib.h
|
||||
dod: dod.c ./lib/libraylib.a
|
||||
$(CC) $(CFLAGS) -Iinclude/ -lm dod.c -o dod ./lib/libraylib.a
|
||||
|
||||
boids: boids.c lib.h ./lib/libraylib.a
|
||||
$(CC) $(CFLAGS) -Iinclude/ -lm boids.c -o boids ./lib/libraylib.a
|
||||
boids_main: boids_main.c lib.h ./lib/libraylib.a
|
||||
$(CC) $(CFLAGS) -Iinclude/ -lm $< -o $@ ./lib/libraylib.a
|
||||
|
||||
libboids.so: boids_game.c boids_game.h lib.h
|
||||
$(CC) $(CFLAGS) -Iinclude/ -lm -c $< -o $@
|
||||
|
||||
run: all
|
||||
./main
|
||||
|
87
boids.c
87
boids.c
@ -1,87 +0,0 @@
|
||||
#include "include/raylib.h"
|
||||
#include "include/raymath.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "lib.h"
|
||||
|
||||
#define SCREEN_WIDTH 1024
|
||||
#define SCREEN_HEIGHT 768
|
||||
#define TARGET_FPS 60
|
||||
#define NUM_BOIDS 16
|
||||
|
||||
const float max_speed = 5.0f;
|
||||
const float max_force = 0.05;
|
||||
|
||||
typedef struct Boid {
|
||||
Point position;
|
||||
Vector2 acceleration;
|
||||
Vector2 velocity;
|
||||
} Boid;
|
||||
|
||||
int main(void) {
|
||||
InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Boids");
|
||||
|
||||
SetTargetFPS(TARGET_FPS);
|
||||
|
||||
Boid *boids = calloc(NUM_BOIDS, sizeof(Boid));
|
||||
for (int i = 0; i < NUM_BOIDS; i++) {
|
||||
Boid *boid = &boids[i];
|
||||
int rand_x = GetRandomValue(0, SCREEN_WIDTH);
|
||||
int rand_y = GetRandomValue(0, SCREEN_HEIGHT);
|
||||
boid->position = (Vector2){rand_x, rand_y};
|
||||
int rand_vx = GetRandomValue(0, 100);
|
||||
int rand_vy = GetRandomValue(0, 100);
|
||||
boid->velocity = (Vector2){rand_vx * 0.01f - 0.5f, rand_vy * 0.01f - 0.5f};
|
||||
boid->velocity = Vector2Scale(boid->velocity, 10.0f);
|
||||
// int rand_ax = GetRandomValue(0, 100);
|
||||
// int rand_ay = GetRandomValue(0, 100);
|
||||
// boid->velocity = (Vector2){rand_ax * 0.01f - 0.5f, rand_ay * 0.01f - 0.5f};
|
||||
}
|
||||
|
||||
PointOption target_pos = {0};
|
||||
|
||||
while (!WindowShouldClose()) {
|
||||
float dt = GetFrameTime();
|
||||
|
||||
// Update
|
||||
if (IsMouseButtonPressed(0)) {
|
||||
Vector2 mouse_pos = GetMousePosition();
|
||||
target_pos = (PointOption){.tag = SOME, .some.point = mouse_pos};
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < NUM_BOIDS; i++) {
|
||||
Boid *boid = &boids[i];
|
||||
if (target_pos.tag == SOME) {
|
||||
Vector2 desired = Vector2Subtract(target_pos.some.point, boid->position);
|
||||
desired = Vector2Normalize(desired);
|
||||
desired = Vector2Scale(desired, max_speed);
|
||||
Vector2 steer = Vector2Subtract(desired, boid->velocity);
|
||||
steer = Vector2ClampValue(steer, 0.0f, max_force);
|
||||
boid->acceleration = Vector2Add(boid->acceleration, steer);
|
||||
}
|
||||
boid->velocity = Vector2Add(boid->velocity, boid->acceleration);
|
||||
boid->velocity = Vector2ClampValue(boid->velocity, 0.0f, max_speed);
|
||||
boid->position = Vector2Add(boid->position, boid->velocity);
|
||||
}
|
||||
|
||||
|
||||
BeginDrawing();
|
||||
{
|
||||
ClearBackground(RAYWHITE);
|
||||
// You can draw a triangle but you'd need to rotate all 3 vectors, and I don't
|
||||
// want to get distracted with that
|
||||
// DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, GREEN);
|
||||
// DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, GREEN);
|
||||
for (int i = 0; i < NUM_BOIDS; i++) {
|
||||
Boid *boid = &boids[i];
|
||||
DrawCircle(boid->position.x, boid->position.y, 27, BLACK);
|
||||
DrawCircle(boid->position.x, boid->position.y, 20, GREEN);
|
||||
}
|
||||
}
|
||||
EndDrawing();
|
||||
}
|
||||
|
||||
free(boids);
|
||||
CloseWindow();
|
||||
}
|
102
boids_game.c
Normal file
102
boids_game.c
Normal file
@ -0,0 +1,102 @@
|
||||
#include <stdlib.h>
|
||||
#include "include/raylib.h"
|
||||
#include "include/raymath.h"
|
||||
#include "boids_game.h"
|
||||
#include "lib.h"
|
||||
|
||||
#define SCREEN_WIDTH 1300
|
||||
#define SCREEN_HEIGHT 1080
|
||||
#define NUM_BOIDS 16
|
||||
|
||||
typedef struct Boid {
|
||||
Point position;
|
||||
Vector2 acceleration;
|
||||
Vector2 velocity;
|
||||
} Boid;
|
||||
|
||||
typedef struct GameState {
|
||||
Boid *boids;
|
||||
PointOption target_pos;
|
||||
int num_boids;
|
||||
float max_speed;
|
||||
float max_force;
|
||||
} GameState;
|
||||
|
||||
GameState *init() {
|
||||
GameState *state = malloc(sizeof(struct GameApi));
|
||||
state->num_boids = 16;
|
||||
state->max_speed = 5.0f;
|
||||
state->max_force = 0.05;
|
||||
Boid *boids = malloc(state->num_boids * sizeof(Boid));
|
||||
state->boids = boids;
|
||||
for (int i = 0; i < state->num_boids; i++) {
|
||||
Boid *boid = &boids[i];
|
||||
int rand_x = GetRandomValue(0, SCREEN_WIDTH);
|
||||
int rand_y = GetRandomValue(0, SCREEN_HEIGHT);
|
||||
boid->position = (Vector2){rand_x, rand_y};
|
||||
int rand_vx = GetRandomValue(0, 100);
|
||||
int rand_vy = GetRandomValue(0, 100);
|
||||
boid->velocity = (Vector2){rand_vx * 0.01f - 0.5f, rand_vy * 0.01f - 0.5f};
|
||||
// boid->velocity = Vector2Scale(boid->velocity, 10.0f);
|
||||
// int rand_ax = GetRandomValue(0, 100);
|
||||
// int rand_ay = GetRandomValue(0, 100);
|
||||
// boid->velocity = (Vector2){rand_ax * 0.01f - 0.5f, rand_ay * 0.01f - 0.5f};
|
||||
boid->acceleration = (Vector2){0};
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void finalize(GameState *state) {
|
||||
(void)state;
|
||||
}
|
||||
|
||||
void reload(GameState *state) {
|
||||
(void)state;
|
||||
}
|
||||
|
||||
void unload(GameState *state) {
|
||||
(void)state;
|
||||
}
|
||||
|
||||
void step(GameState *state) {
|
||||
// Process Input
|
||||
if (IsMouseButtonPressed(0)) {
|
||||
Vector2 mouse_pos = GetMousePosition();
|
||||
state->target_pos = (PointOption){.tag = SOME, .some.point = mouse_pos};
|
||||
}
|
||||
|
||||
|
||||
// Update
|
||||
for (int i = 0; i < NUM_BOIDS; i++) {
|
||||
Boid *boid = &state->boids[i];
|
||||
if (state->target_pos.tag == SOME) {
|
||||
Vector2 desired = Vector2Subtract(state->target_pos.some.point, boid->position);
|
||||
desired = Vector2Normalize(desired);
|
||||
desired = Vector2Scale(desired, state->max_speed);
|
||||
Vector2 steer = Vector2Subtract(desired, boid->velocity);
|
||||
steer = Vector2ClampValue(steer, 0.0f, state->max_force);
|
||||
boid->acceleration = Vector2Add(boid->acceleration, steer);
|
||||
}
|
||||
boid->velocity = Vector2Add(boid->velocity, boid->acceleration);
|
||||
boid->velocity = Vector2ClampValue(boid->velocity, 0.0f, state->max_speed);
|
||||
boid->position = Vector2Add(boid->position, boid->velocity);
|
||||
}
|
||||
|
||||
|
||||
// Update
|
||||
BeginDrawing();
|
||||
{
|
||||
ClearBackground(RAYWHITE);
|
||||
// You can draw a triangle but you'd need to rotate all 3 vectors, and I don't
|
||||
// want to get distracted with that
|
||||
// DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, GREEN);
|
||||
// DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, GREEN);
|
||||
for (int i = 0; i < NUM_BOIDS; i++) {
|
||||
Boid *boid = &state->boids[i];
|
||||
DrawCircle(boid->position.x, boid->position.y, 27, BLACK);
|
||||
DrawCircle(boid->position.x, boid->position.y, 20, GREEN);
|
||||
}
|
||||
}
|
||||
EndDrawing();
|
||||
}
|
13
boids_game.h
Normal file
13
boids_game.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
struct GameState;
|
||||
|
||||
typedef struct GameApi {
|
||||
struct GameApi *(*init)();
|
||||
void (*finalize) (struct GameApi *state);
|
||||
void (*reload) (struct GameApi *state);
|
||||
void (*unload) (struct GameApi *state);
|
||||
void (*step) (struct GameApi *state);
|
||||
} GameApi;
|
||||
|
||||
extern const struct GameApi GAME_API;
|
79
boids_main.c
Normal file
79
boids_main.c
Normal file
@ -0,0 +1,79 @@
|
||||
#define _DEFAULT_SOURCE // usleep()
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/inotify.h>
|
||||
// #include "inotify-syscalls.h"
|
||||
#include "include/raylib.h"
|
||||
#include "include/raymath.h"
|
||||
#include "boids_game.h"
|
||||
|
||||
#define SCREEN_WIDTH 1300
|
||||
#define SCREEN_HEIGHT 1080
|
||||
#define TARGET_FPS 60
|
||||
|
||||
const char *GAME_LIB = "./libboids.so";
|
||||
char epoll_buf[1024];
|
||||
|
||||
struct Game {
|
||||
void *handle;
|
||||
struct GameApi api;
|
||||
struct GameState *state;
|
||||
};
|
||||
#define MAX_EVENTS 1
|
||||
|
||||
int main(void) {
|
||||
int fd = inotify_init();
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Error initializing inotify\n");
|
||||
}
|
||||
int wd;
|
||||
wd = inotify_add_watch(fd, GAME_LIB, IN_MODIFY);
|
||||
|
||||
// create epoll instance
|
||||
int epollfd = epoll_create1(0);
|
||||
if (epollfd == -1) {
|
||||
fprintf(stderr, "Error creating epoll instance\n");
|
||||
}
|
||||
|
||||
struct epoll_event event;
|
||||
event.events = EPOLLIN;
|
||||
event.data.fd = fd;
|
||||
|
||||
// register inotify fd with epoll
|
||||
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event) == -1) {
|
||||
fprintf(stderr, "Error adding inotify descriptor to epoll\n");
|
||||
}
|
||||
|
||||
InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Boids");
|
||||
|
||||
SetTargetFPS(TARGET_FPS);
|
||||
|
||||
struct epoll_event events[MAX_EVENTS];
|
||||
|
||||
while (!WindowShouldClose()) {
|
||||
int nfds = epoll_wait(epollfd, events, MAX_EVENTS, 0);
|
||||
if (nfds == -1) {
|
||||
fprintf(stderr, "epoll_wait failed\n");
|
||||
break;
|
||||
}
|
||||
|
||||
for (int n = 0; n < nfds; ++n) {
|
||||
if (events[n].data.fd == fd) {
|
||||
printf("SO has been updated!\n");
|
||||
read(fd, epoll_buf, sizeof(epoll_buf));
|
||||
}
|
||||
}
|
||||
|
||||
BeginDrawing();
|
||||
ClearBackground(BEIGE);
|
||||
EndDrawing();
|
||||
}
|
||||
|
||||
inotify_rm_watch(fd, wd);
|
||||
close(fd);
|
||||
close(epollfd);
|
||||
CloseWindow();
|
||||
}
|
18
hours.org
18
hours.org
@ -1,12 +1,22 @@
|
||||
* Bexorg Hours
|
||||
#+BEGIN: clocktable :scope subtree :maxlevel 2
|
||||
#+CAPTION: Clock summary at [2024-01-06 Sat 12:28]
|
||||
| Headline | Time |
|
||||
|------------+------|
|
||||
| *Total time* | *0:00* |
|
||||
#+CAPTION: Clock summary at [2024-01-09 Tue 20:31]
|
||||
| Headline | Time | |
|
||||
|----------------------+------+------|
|
||||
| *Total time* | *3:41* | |
|
||||
|----------------------+------+------|
|
||||
| Bexorg Hours | 3:41 | |
|
||||
| \_ <2024-01-06 Sat> | | 2:10 |
|
||||
| \_ <2024-01-09 Tue> | | 1:31 |
|
||||
#+END:
|
||||
|
||||
** <2024-01-06 Sat>
|
||||
:LOGBOOK:
|
||||
CLOCK: [2024-01-06 Sat 11:00]--[2024-01-06 Sat 13:10] => 2:10
|
||||
:END:
|
||||
** <2024-01-09 Tue>
|
||||
:LOGBOOK:
|
||||
CLOCK: [2024-01-09 Tue 19:30]--[2024-01-09 Tue 20:31] => 1:01
|
||||
CLOCK: [2024-01-09 Tue 10:45]--[2024-01-09 Tue 11:15] => 0:30
|
||||
:END:
|
||||
|
||||
|
8
main.c
8
main.c
@ -6,7 +6,7 @@
|
||||
|
||||
#define TEXTURES_BUF_SIZE 16
|
||||
#define TARGET_FPS 60
|
||||
#define MAX_KNIGHTS 512
|
||||
#define MAX_KNIGHTS 10000
|
||||
#define SCREEN_WIDTH 1300
|
||||
#define SCREEN_HEIGHT 1080
|
||||
|
||||
@ -36,7 +36,7 @@ typedef enum Direction {
|
||||
// DIR_DOWN_RIGHT = 7,
|
||||
} Direction;
|
||||
|
||||
typedef struct {
|
||||
typedef struct Knight {
|
||||
Point position;
|
||||
Point move_target_point;
|
||||
u8 look_dir;
|
||||
@ -45,7 +45,7 @@ typedef struct {
|
||||
u8 ordered_to_move;
|
||||
} Knight;
|
||||
|
||||
typedef struct {
|
||||
typedef struct GameState {
|
||||
int frame_count;
|
||||
Point camera_position;
|
||||
|
||||
@ -59,7 +59,7 @@ typedef struct {
|
||||
int entity_count;
|
||||
} GameState;
|
||||
|
||||
typedef struct {
|
||||
typedef struct Assets {
|
||||
Texture2D *textures;
|
||||
} Assets;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user