dod-test/no_dod.c
2025-05-27 15:06:51 +01:00

212 lines
5.4 KiB
C

#include "wapp.h"
#include "common.h"
#include "raylib.h"
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#define OBJECT_COMMON struct {Position position; Scale scale;}
typedef struct Position Position;
struct Position {
f32 x;
f32 y;
};
typedef struct Scale Scale;
struct Scale {
f32 width;
f32 height;
};
typedef struct Velocity Velocity;
struct Velocity {
f32 x;
f32 y;
};
typedef struct Wanderer Wanderer;
struct Wanderer {
OBJECT_COMMON;
Velocity velocity;
bool slow;
};
typedef struct SlowZone SlowZone;
struct SlowZone {
OBJECT_COMMON;
};
void init_wanderer(Wanderer *wanderer, XOR256State *state);
void move_wanderer(Wanderer *wanderer, const SlowZone *zones);
void render_wanderer(const Wanderer *wanderer);
void init_slow_zone(SlowZone *zone, XOR256State *state);
void render_slow_zone(const SlowZone *zone);
bool inside_zone(const Wanderer *wanderer, const SlowZone *zone);
f32 get_random_float(XOR256State *state);
int main(void) {
SetTraceLogLevel(LOG_NONE);
InitWindow(WIDTH, HEIGHT, "No-DOD test");
SetTargetFPS(120);
Allocator arena = wapp_mem_arena_allocator_init(MB(20));
XOR256State state = wapp_prng_xorshift_init_state();
u64 wanderers_size = sizeof(Wanderer) * WANDERER_COUNT;
u64 zones_size = sizeof(SlowZone) * ZONE_COUNT;
Wanderer *wanderers = wapp_mem_allocator_alloc(&arena, wanderers_size);
SlowZone *zones = wapp_mem_allocator_alloc(&arena, zones_size);
assert(wanderers != NULL && zones != NULL);
memset(wanderers, 0, wanderers_size);
memset(zones, 0, zones_size);
for (u64 i = 0; i < WANDERER_COUNT; ++i) {
init_wanderer(&(wanderers[i]), &state);
}
for (u64 i = 0; i < ZONE_COUNT; ++i) {
init_slow_zone(&(zones[i]),&state);
}
while (!WindowShouldClose()) {
f64 time = GetTime();
if (time >= 20.0) {
break;
}
for (u64 i = 0; i < WANDERER_COUNT; ++i) {
move_wanderer(&(wanderers[i]), zones);
}
BeginDrawing();
ClearBackground(BG_COLOR);
for (u64 i = 0; i < ZONE_COUNT; ++i) {
render_slow_zone(&(zones[i]));
}
for (u64 i = 0; i < WANDERER_COUNT; ++i) {
render_wanderer(&(wanderers[i]));
}
DrawFPS(10, 10);
EndDrawing();
}
wapp_mem_arena_allocator_destroy(&arena);
CloseWindow();
return 0;
}
void init_wanderer(Wanderer *wanderer, XOR256State *state) {
wanderer->position = (Position){
.x = wapp_prng_xorshift_256(state) % WIDTH,
.y = wapp_prng_xorshift_256(state) % HEIGHT,
};
f32 scale = (f32)((wapp_prng_xorshift_256(state) % (MAX_WANDERER_DIM + 1 - MIN_WANDERER_DIM)) + MIN_WANDERER_DIM);
wanderer->scale = (Scale){
.width = scale,
.height = scale,
};
wanderer->velocity = (Velocity){
.x = get_random_float(state),
.y = get_random_float(state),
};
}
void move_wanderer(Wanderer *wanderer, const SlowZone *zones) {
wanderer->position.x += wanderer->velocity.x;
wanderer->position.y += wanderer->velocity.y;
f32 max_x = WIDTH - wanderer->scale.width;
f32 max_y = HEIGHT - wanderer->scale.height;
if (wanderer->position.x < 0 || wanderer->position.x >= max_x) {
wanderer->position.x = min(max(wanderer->position.x, 0), max_x);
wanderer->velocity.x *= -1;
}
if (wanderer->position.y < 0 || wanderer->position.y >= max_y) {
wanderer->position.y = min(max(wanderer->position.y, 0), max_y);
wanderer->velocity.y *= -1;
}
bool was_slow = wanderer->slow;
wanderer->slow = false;
for (u64 i = 0; i < ZONE_COUNT; ++i) {
if (inside_zone(wanderer, &(zones[i]))) {
wanderer->slow = true;
break;
}
}
if (!was_slow && wanderer->slow) {
wanderer->velocity.x *= WANDERER_SLOWDOWN_FACTOR;
wanderer->velocity.y *= WANDERER_SLOWDOWN_FACTOR;
} else if (was_slow && !(wanderer->slow)) {
wanderer->velocity.x *= WANDERER_SPEEDUP_FACTOR;
wanderer->velocity.y *= WANDERER_SPEEDUP_FACTOR;
}
}
void render_wanderer(const Wanderer *wanderer) {
Color color = wanderer->slow ? ZONE_COLOR : FG_COLOR;
DrawRectangle(
(i32)wanderer->position.x,
(i32)wanderer->position.y,
(i32)wanderer->scale.width,
(i32)wanderer->scale.height,
color
);
}
void init_slow_zone(SlowZone *zone, XOR256State *state) {
zone->position = (Position){
.x = wapp_prng_xorshift_256(state) % WIDTH,
.y = wapp_prng_xorshift_256(state) % HEIGHT,
};
zone->scale = (Scale){
.width = wapp_prng_xorshift_256(state) % ((u64)HALF_WIDTH - MIN_ZONE_DIM) + MIN_ZONE_DIM,
.height = wapp_prng_xorshift_256(state) % ((u64)HALF_HEIGHT - MIN_ZONE_DIM) + MIN_ZONE_DIM,
};
}
void render_slow_zone(const SlowZone *zone) {
DrawRectangleLines(
zone->position.x,
zone->position.y,
zone->scale.width,
zone->scale.height,
ZONE_COLOR
);
}
bool inside_zone(const Wanderer *wanderer, const SlowZone *zone) {
f32 wanderer_min_x = wanderer->position.x + wanderer->scale.width;
f32 wanderer_min_y = wanderer->position.y + wanderer->scale.height;
f32 wanderer_max_x = wanderer->position.x;
f32 wanderer_max_y = wanderer->position.y;
f32 zone_x0 = zone->position.x;
f32 zone_y0 = zone->position.y;
f32 zone_x1 = zone->position.x + zone->scale.width;
f32 zone_y1 = zone->position.y + zone->scale.height;
return (wanderer_min_x > zone_x0 && wanderer_min_y > zone_y0 &&
wanderer_max_x < zone_x1 && wanderer_max_y < zone_y1);
}
f32 get_random_float(XOR256State *state) {
i64 random = (i64)wapp_prng_xorshift_256(state) - INT64_MAX;
return (f32)(random) / (f32)(INT64_MAX);
}