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 FIRE_JITTER 0.01
|
||||||
|
|
||||||
#define ASTEROID_MIN_VERTS 5
|
#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_A_JITTER 0.8
|
||||||
#define ASTEROID_VEL_JITTER 0.001
|
#define ASTEROID_VEL_JITTER 0.001
|
||||||
#define ASTEROID_OMG_JITTER 0.005
|
#define ASTEROID_OMG_JITTER 0.005
|
||||||
@@ -27,11 +28,22 @@
|
|||||||
#define ASTEROID_R_JITTER 0.02
|
#define ASTEROID_R_JITTER 0.02
|
||||||
#define ASTEROID_MIN_DIST 0.8
|
#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 LIN_PWR 0.0001
|
||||||
#define ROT_PWR 0.002
|
#define ROT_PWR 0.002
|
||||||
|
|
||||||
#define SHOT_VEL 0.04
|
#define SHOT_VEL 0.04
|
||||||
#define SHOT_COLLIDE_R 0.005
|
#define SHOT_COLLIDE_R 0.005
|
||||||
|
#define SHOT_MASS 0.005
|
||||||
|
|
||||||
#define MAX_SHAPES 256U
|
#define MAX_SHAPES 256U
|
||||||
#define MAX_ENTITIES 128U
|
#define MAX_ENTITIES 128U
|
||||||
@@ -69,6 +81,8 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned entities[2];
|
unsigned entities[2];
|
||||||
|
float vs[2];
|
||||||
|
vec2_t normal;
|
||||||
} collision_t;
|
} collision_t;
|
||||||
|
|
||||||
static const vec2_t ship_verts[] = {
|
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 i = 0; i < entity_count; ++i) {
|
||||||
for (unsigned j = i + 1; j < entity_count; ++j) {
|
for (unsigned j = i + 1; j < entity_count; ++j) {
|
||||||
if (intersecting(i, 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);
|
assert(count < MAX_COLLISIONS);
|
||||||
out[count].entities[0] = i;
|
out[count].entities[0] = i;
|
||||||
out[count].entities[1] = j;
|
out[count].entities[1] = j;
|
||||||
|
out[count].vs[0] = vi;
|
||||||
|
out[count].vs[1] = vj;
|
||||||
|
out[count].normal = n;
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,16 +302,18 @@ static unsigned check_collisions(collision_t *out)
|
|||||||
return count;
|
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 ma = a->radius * a->radius;
|
||||||
const float mb = b->radius * b->radius;
|
const float mb = b->radius * b->radius;
|
||||||
const float m = ma + mb;
|
const float m = ma + mb;
|
||||||
|
|
||||||
const vec2_t n = vec2_norm(vec2_sub(b->pos, a->pos));
|
const vec2_t n = c.normal;
|
||||||
|
const float va1 = c.vs[0];
|
||||||
const float va1 = vec2_dot(a->vel, n);
|
const float vb1 = c.vs[1];
|
||||||
const float vb1 = vec2_dot(b->vel, n);
|
|
||||||
|
|
||||||
const float va2 = (va1 * (ma - mb) + 2 * mb * vb1) / m;
|
const float va2 = (va1 * (ma - mb) + 2 * mb * vb1) / m;
|
||||||
const float vb2 = (vb1 * (mb - ma) + 2 * ma * va1) / 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));
|
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)
|
static void handle_collisions(const collision_t *collisions, unsigned count)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < count; ++i) {
|
for (unsigned i = 0; i < count; ++i) {
|
||||||
@@ -312,17 +378,17 @@ static void handle_collisions(const collision_t *collisions, unsigned count)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (a->tag == COLLISION_ASTEROID && b->tag == COLLISION_ASTEROID) {
|
if (a->tag == COLLISION_ASTEROID && b->tag == COLLISION_ASTEROID) {
|
||||||
bounce_asteroids(a, b);
|
bounce(c);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a->tag == COLLISION_SHOT) {
|
if (a->tag == COLLISION_SHOT) {
|
||||||
a->dead = true;
|
a->dead = true;
|
||||||
b->dead = true;
|
destroy_asteroid(b, a->vel);
|
||||||
}
|
}
|
||||||
if (b->tag == COLLISION_SHOT) {
|
if (b->tag == COLLISION_SHOT) {
|
||||||
a->dead = true;
|
|
||||||
b->dead = true;
|
b->dead = true;
|
||||||
|
destroy_asteroid(a, b->vel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user