From c3552ae872e3071526263f803cb641d28286f062 Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Tue, 14 Oct 2025 14:34:12 +0100 Subject: [PATCH] Add asteroids --- game.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 84 insertions(+), 8 deletions(-) diff --git a/game.c b/game.c index 8ee784e..1d66a93 100644 --- a/game.c +++ b/game.c @@ -6,11 +6,19 @@ #include #include +#include #include #define FIRE_MEAN -0.15 #define FIRE_JITTER 0.01 +#define ASTEROID_MIN_VERTS 5 +#define ASTEROID_VERT_RANGE (MAX_VERTS - ASTEROID_MIN_VERTS) +#define ASTEROID_A_JITTER 0.8 +#define ASTEROID_VEL_JITTER 0.001 +#define ASTEROID_OMG_JITTER 0.005 +#define INIT_ASTEROIDS 8 + #define LIN_PWR 0.0001 #define ROT_PWR 0.002 @@ -22,14 +30,6 @@ #define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) -typedef struct { - bool visible; - int entity; - unsigned vert_count; - vec2_t verts[MAX_VERTS]; - uint8_t flags; -} shape_t; - typedef struct { vec2_t pos; vec2_t vel; @@ -40,6 +40,20 @@ typedef struct { bool wrap; } entity_t; +typedef struct { + bool visible; + int entity; + unsigned vert_count; + vec2_t verts[MAX_VERTS]; + uint8_t flags; +} shape_t; + +typedef enum { + ASTEROID_SMALL, + ASTEROID_MEDIUM, + ASTEROID_LARGE, +} asteroid_size_t; + static const vec2_t ship_verts[] = { { 0.0, 0.11 }, { 0.05, -0.07 }, @@ -110,6 +124,65 @@ static void shoot() memcpy(s->verts, shot_verts, sizeof(shot_verts)); } +static void gen_asteroid_shape(asteroid_size_t size, shape_t *out) +{ + float r_mean, r_jitter; + switch (size) { + case ASTEROID_SMALL: + r_mean = 0.05; + r_jitter = 0.02; + break; + case ASTEROID_MEDIUM: + r_mean = 0.1; + r_jitter = 0.02; + break; + case ASTEROID_LARGE: + r_mean = 0.15; + r_jitter = 0.05; + } + + const unsigned n + = ASTEROID_MIN_VERTS + rng_uint32() % (ASTEROID_VERT_RANGE); + out->vert_count = n; + + const float da = 2.0f * PI / n; + for (unsigned i = 0; i < n; ++i) { + const float r = r_mean + rng_plusminus() * r_jitter; + const float a + = i * da + ASTEROID_A_JITTER * rng_plusminus() * da / 2; + out->verts[i] = (vec2_t) { r * cosf(a), r * sinf(a) }; + } +} + +static void add_asteroid() +{ + unsigned id; + entity_t *e = add_entity(&id); + e->wrap = true; + e->pos.y = rng_plusminus(); + e->pos.x = aspect * rng_plusminus(); + e->vel = (vec2_t) { + ASTEROID_VEL_JITTER * rng_plusminus(), + ASTEROID_VEL_JITTER * rng_plusminus(), + }; + e->omg = ASTEROID_OMG_JITTER * rng_plusminus(); + + shape_t *s = add_shape(id, nullptr); + s->visible = true; + s->flags = WRAP | CONNECT; + + asteroid_size_t size; + const float r = rng_canon(); + if (r < 0.2) + size = ASTEROID_SMALL; + else if (r < 0.5) + size = ASTEROID_MEDIUM; + else + size = ASTEROID_LARGE; + + gen_asteroid_shape(size, s); +} + static void remove_shape(unsigned id) { if (id < shape_count - 1) { @@ -179,6 +252,9 @@ void game_init(float _aspect) fire->flags = WRAP | CONNECT; fire->vert_count = NELEMS(fire_verts); memcpy(fire->verts, fire_verts, sizeof(fire_verts)); + + for (unsigned i = 0; i < INIT_ASTEROIDS; ++i) + add_asteroid(); } void game_update()