#include "wapp.h" #include "common.h" #include "raylib.h" #include #include #include #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); }