#include #include #include "include/raylib.h" #include "include/raymath.h" #include "boids_game.h" #include "lib.h" #define SCREEN_WIDTH 1300 #define SCREEN_HEIGHT 1080 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; static GameState *init() { InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Boids"); SetTargetFPS(60); 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}; } printf("Initialized Game\n"); return state; } static void finalize(GameState *state) { free(state->boids); CloseWindow(); } static void reload(GameState *state) { (void)state; state->max_speed = 5.0f; state->max_force = 0.1; printf("Reloaded Game\n"); } static void unload(GameState *state) { (void)state; } static int step(GameState *state) { if (WindowShouldClose()) { return 1; } int return_int = 0; if (IsKeyPressed(KEY_SPACE)) { return_int = 2; } // 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 < state->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 < state->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(); return return_int; } const struct GameApi GAME_API = { .init = init, .reload = reload, .step = step, .unload = unload, .finalize = finalize };