Replace big asteroids with smaller ones when shot
This commit is contained in:
84
game.c
84
game.c
@@ -15,7 +15,8 @@
|
||||
#define FIRE_JITTER 0.01
|
||||
|
||||
#define ASTEROID_MIN_VERTS 5
|
||||
#define ASTEROID_VERT_RANGE (MAX_VERTS - ASTEROID_MIN_VERTS)
|
||||
#define ASTEROID_MAX_VERTS 8
|
||||
#define ASTEROID_VERT_RANGE (ASTEROID_MAX_VERTS - ASTEROID_MIN_VERTS)
|
||||
#define ASTEROID_A_JITTER 0.8
|
||||
#define ASTEROID_VEL_JITTER 0.001
|
||||
#define ASTEROID_OMG_JITTER 0.005
|
||||
@@ -27,11 +28,22 @@
|
||||
#define ASTEROID_R_JITTER 0.02
|
||||
#define ASTEROID_MIN_DIST 0.8
|
||||
|
||||
#define REPLACE_MIN 2
|
||||
#define REPLACE_MAX 4
|
||||
#define REPLACE_RANGE (REPLACE_MAX - REPLACE_MIN)
|
||||
#define REPLACE_R_COEFF 0.5
|
||||
#define REPLACE_R_JITTER 0.02
|
||||
#define REPLACE_A_JITTER 0.4
|
||||
#define REPLACE_V_JITTER 0.001
|
||||
#define REPLACE_RADIAL_V_COEFF 0.005
|
||||
#define REPLACE_OMG_JITTER 0.01
|
||||
|
||||
#define LIN_PWR 0.0001
|
||||
#define ROT_PWR 0.002
|
||||
|
||||
#define SHOT_VEL 0.04
|
||||
#define SHOT_COLLIDE_R 0.005
|
||||
#define SHOT_MASS 0.005
|
||||
|
||||
#define MAX_SHAPES 256U
|
||||
#define MAX_ENTITIES 128U
|
||||
@@ -69,6 +81,8 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
unsigned entities[2];
|
||||
float vs[2];
|
||||
vec2_t normal;
|
||||
} collision_t;
|
||||
|
||||
static const vec2_t ship_verts[] = {
|
||||
@@ -268,9 +282,19 @@ static unsigned check_collisions(collision_t *out)
|
||||
for (unsigned i = 0; i < entity_count; ++i) {
|
||||
for (unsigned j = i + 1; j < entity_count; ++j) {
|
||||
if (intersecting(i, j)) {
|
||||
const vec2_t n
|
||||
= vec2_norm(vec2_sub(entities[j].pos, entities[i].pos));
|
||||
const float vi = vec2_dot(entities[i].vel, n);
|
||||
const float vj = vec2_dot(entities[j].vel, n);
|
||||
if (vi < 0 && vj > 0)
|
||||
continue;
|
||||
|
||||
assert(count < MAX_COLLISIONS);
|
||||
out[count].entities[0] = i;
|
||||
out[count].entities[1] = j;
|
||||
out[count].vs[0] = vi;
|
||||
out[count].vs[1] = vj;
|
||||
out[count].normal = n;
|
||||
++count;
|
||||
}
|
||||
}
|
||||
@@ -278,16 +302,18 @@ static unsigned check_collisions(collision_t *out)
|
||||
return count;
|
||||
}
|
||||
|
||||
static void bounce_asteroids(entity_t *a, entity_t *b)
|
||||
static void bounce(collision_t c)
|
||||
{
|
||||
entity_t *a = entities + c.entities[0];
|
||||
entity_t *b = entities + c.entities[1];
|
||||
|
||||
const float ma = a->radius * a->radius;
|
||||
const float mb = b->radius * b->radius;
|
||||
const float m = ma + mb;
|
||||
|
||||
const vec2_t n = vec2_norm(vec2_sub(b->pos, a->pos));
|
||||
|
||||
const float va1 = vec2_dot(a->vel, n);
|
||||
const float vb1 = vec2_dot(b->vel, n);
|
||||
const vec2_t n = c.normal;
|
||||
const float va1 = c.vs[0];
|
||||
const float vb1 = c.vs[1];
|
||||
|
||||
const float va2 = (va1 * (ma - mb) + 2 * mb * vb1) / m;
|
||||
const float vb2 = (vb1 * (mb - ma) + 2 * ma * va1) / m;
|
||||
@@ -296,6 +322,46 @@ static void bounce_asteroids(entity_t *a, entity_t *b)
|
||||
b->vel = vec2_add(b->vel, vec2_scale(n, vb2 - vb1));
|
||||
}
|
||||
|
||||
static void destroy_asteroid(entity_t *a, vec2_t shot_vel)
|
||||
{
|
||||
a->dead = true;
|
||||
|
||||
float r;
|
||||
if (fabs(a->radius - ASTEROID_LARGE) < 1e-3)
|
||||
r = ASTEROID_MEDIUM;
|
||||
else if (fabs(a->radius - ASTEROID_MEDIUM) < 1e-3)
|
||||
r = ASTEROID_SMALL;
|
||||
else
|
||||
return;
|
||||
|
||||
const unsigned n = REPLACE_MIN + rng_uint32() % REPLACE_RANGE;
|
||||
const float da = 2 * PI / n;
|
||||
|
||||
const float m = a->radius * a->radius;
|
||||
const vec2_t p
|
||||
= vec2_add(vec2_scale(a->vel, m), vec2_scale(shot_vel, SHOT_MASS));
|
||||
const vec2_t inherit_v = vec2_scale(p, 1 / n * (m + SHOT_MASS));
|
||||
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
const float disp_r = REPLACE_R_COEFF * a->radius
|
||||
+ REPLACE_R_JITTER * rng_plusminus();
|
||||
const float disp_a = i * da + REPLACE_A_JITTER * rng_plusminus();
|
||||
const vec2_t disp = { disp_r * cosf(disp_a), disp_r * sinf(disp_a) };
|
||||
|
||||
const vec2_t radial_v = vec2_scale(
|
||||
vec2_norm(disp), REPLACE_RADIAL_V_COEFF * rng_canon());
|
||||
const vec2_t jitter_v = {
|
||||
REPLACE_V_JITTER * rng_plusminus(),
|
||||
REPLACE_V_JITTER * rng_plusminus(),
|
||||
};
|
||||
|
||||
entity_t *e = gen_asteroid(r, nullptr);
|
||||
e->pos = vec2_add(a->pos, disp);
|
||||
e->vel = vec2_add(inherit_v, vec2_add(radial_v, jitter_v));
|
||||
e->omg = a->omg / n + REPLACE_OMG_JITTER * rng_plusminus();
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_collisions(const collision_t *collisions, unsigned count)
|
||||
{
|
||||
for (unsigned i = 0; i < count; ++i) {
|
||||
@@ -312,17 +378,17 @@ static void handle_collisions(const collision_t *collisions, unsigned count)
|
||||
continue;
|
||||
|
||||
if (a->tag == COLLISION_ASTEROID && b->tag == COLLISION_ASTEROID) {
|
||||
bounce_asteroids(a, b);
|
||||
bounce(c);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (a->tag == COLLISION_SHOT) {
|
||||
a->dead = true;
|
||||
b->dead = true;
|
||||
destroy_asteroid(b, a->vel);
|
||||
}
|
||||
if (b->tag == COLLISION_SHOT) {
|
||||
a->dead = true;
|
||||
b->dead = true;
|
||||
destroy_asteroid(a, b->vel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user