Add levelling
This commit is contained in:
110
game.c
110
game.c
@@ -8,7 +8,6 @@
|
||||
#include <assert.h>
|
||||
#include <linux/input-event-codes.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define SHIP_COLLIDE_R 0.05
|
||||
@@ -17,14 +16,14 @@
|
||||
#define FIRE_MEAN -0.15
|
||||
#define FIRE_JITTER 0.01
|
||||
|
||||
#define INIT_LEVEL 1
|
||||
|
||||
#define ASTEROID_MIN_VERTS 5
|
||||
#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
|
||||
#define INIT_ASTEROIDS 1
|
||||
|
||||
#define ASTEROID_SMALL 0.05f
|
||||
#define ASTEROID_MEDIUM 0.1f
|
||||
#define ASTEROID_LARGE 0.2f
|
||||
@@ -54,6 +53,10 @@
|
||||
#define MAX_SHAPES_PER_ENTITY 2
|
||||
#define MAX_COLLISIONS 128U
|
||||
|
||||
#define ARROW_SCALE 0.025
|
||||
#define ARROW_WIDTH 4
|
||||
#define ARROW_HEIGHT 4
|
||||
|
||||
#define COUNTER_MASK (1 << 6)
|
||||
|
||||
#define NELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||
@@ -103,6 +106,12 @@ static const vec2_t fire_verts[] = {
|
||||
};
|
||||
static const vec2_t shot_verts[] = { { 0.0, -0.02 }, { 0.0, 0.02 } };
|
||||
|
||||
static const vec2_t arrow_verts[][MAX_VERTS] = {
|
||||
{ { 1, 2 }, { 2, 0 }, { 1, -2 } },
|
||||
{ { -2, 0 }, { 2, 0 } },
|
||||
};
|
||||
static const unsigned arrow_counts[NELEMS(arrow_verts)] = { 3, 2 };
|
||||
|
||||
static entity_t entities[MAX_ENTITIES];
|
||||
static mat3_t transforms[MAX_ENTITIES];
|
||||
static shape_t shapes[MAX_SHAPES];
|
||||
@@ -110,25 +119,22 @@ static shape_t shapes[MAX_SHAPES];
|
||||
static unsigned entity_count;
|
||||
static unsigned shape_count;
|
||||
|
||||
static float aspect;
|
||||
static unsigned level;
|
||||
|
||||
static bool dead;
|
||||
static unsigned asteroid_count;
|
||||
static float aspect;
|
||||
static uint8_t counter;
|
||||
|
||||
static unsigned ship_entity_id;
|
||||
static unsigned ship_shape_id;
|
||||
static unsigned fire_shape_id;
|
||||
|
||||
static void restart()
|
||||
{
|
||||
game_init(aspect);
|
||||
}
|
||||
|
||||
static entity_t *add_entity(unsigned *id_out)
|
||||
{
|
||||
const unsigned id = entity_count++;
|
||||
memset(entities + id, 0, sizeof(entity_t));
|
||||
entities[id].dir = (mat2_t) { { 1, 0 }, { 0, 1 } };
|
||||
entities[id].dir = MAT2_ID;
|
||||
if (id_out != nullptr)
|
||||
*id_out = id;
|
||||
return entities + id;
|
||||
@@ -340,20 +346,28 @@ static void bounce(collision_t c)
|
||||
b->vel = vec2_add(b->vel, vec2_scale(n, vb2 - vb1));
|
||||
}
|
||||
|
||||
static void cleared()
|
||||
{
|
||||
renderer_set_wrap(false);
|
||||
}
|
||||
|
||||
static void destroy_asteroid(entity_t *a, vec2_t shot_vel)
|
||||
{
|
||||
a->dead = true;
|
||||
--asteroid_count;
|
||||
|
||||
float r;
|
||||
if (a->radius == ASTEROID_HUGE)
|
||||
if (a->radius == ASTEROID_HUGE) {
|
||||
r = ASTEROID_LARGE;
|
||||
else if (a->radius == ASTEROID_LARGE)
|
||||
} else if (a->radius == ASTEROID_LARGE) {
|
||||
r = ASTEROID_MEDIUM;
|
||||
else if (a->radius == ASTEROID_MEDIUM)
|
||||
} else if (a->radius == ASTEROID_MEDIUM) {
|
||||
r = ASTEROID_SMALL;
|
||||
else
|
||||
} else {
|
||||
if (asteroid_count == 0)
|
||||
cleared();
|
||||
return;
|
||||
}
|
||||
|
||||
const unsigned n = REPLACE_MIN + rng_uint32() % REPLACE_RANGE;
|
||||
const float da = 2 * PI / n;
|
||||
@@ -383,8 +397,6 @@ static void destroy_asteroid(entity_t *a, vec2_t shot_vel)
|
||||
|
||||
++asteroid_count;
|
||||
}
|
||||
|
||||
printf("asteroid count: %u\n", asteroid_count);
|
||||
}
|
||||
|
||||
static void handle_collisions(const collision_t *collisions, unsigned count)
|
||||
@@ -423,12 +435,27 @@ static void handle_collisions(const collision_t *collisions, unsigned count)
|
||||
}
|
||||
}
|
||||
|
||||
void game_init(float _aspect)
|
||||
static void draw_arrow()
|
||||
{
|
||||
input_on_shoot(shoot);
|
||||
input_on_restart(restart);
|
||||
const float tx = aspect - ARROW_SCALE * (ARROW_WIDTH / 2.0 + 2);
|
||||
const mat3_t m = {
|
||||
{ ARROW_SCALE, 0, 0 },
|
||||
{ 0, ARROW_SCALE, 0 },
|
||||
{ tx, 0, 1 },
|
||||
};
|
||||
|
||||
aspect = _aspect;
|
||||
const vec3_t c_mod = { 0, 0, 1 };
|
||||
const vec3_t s_mod = { ARROW_WIDTH + 2, ARROW_HEIGHT + 2, 0 };
|
||||
const vec3_t c = mat3_mul_vec3(m, c_mod);
|
||||
const vec3_t s = mat3_mul_vec3(m, s_mod);
|
||||
renderer_clear_rect(vec3_reduce(c), (vec2_t) { s.x, s.y });
|
||||
|
||||
for (unsigned i = 0; i < NELEMS(arrow_verts); ++i)
|
||||
renderer_draw(arrow_verts[i], arrow_counts[i], m, false);
|
||||
}
|
||||
|
||||
static void create_field()
|
||||
{
|
||||
dead = false;
|
||||
counter = 0;
|
||||
entity_count = shape_count = 0;
|
||||
@@ -450,19 +477,38 @@ void game_init(float _aspect)
|
||||
fire->vert_count = NELEMS(fire_verts);
|
||||
memcpy(fire->verts, fire_verts, sizeof(fire_verts));
|
||||
|
||||
for (unsigned i = 0; i < INIT_ASTEROIDS; ++i)
|
||||
for (unsigned i = 0; i < level; ++i)
|
||||
spawn_asteroid();
|
||||
}
|
||||
|
||||
static void win()
|
||||
{
|
||||
renderer_set_wrap(true);
|
||||
++level;
|
||||
create_field();
|
||||
}
|
||||
|
||||
static void reset()
|
||||
{
|
||||
level = INIT_LEVEL;
|
||||
create_field();
|
||||
}
|
||||
|
||||
void game_init(float _aspect)
|
||||
{
|
||||
input_on_shoot(shoot);
|
||||
input_on_restart(reset);
|
||||
aspect = _aspect;
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
void game_update()
|
||||
{
|
||||
if (dead) {
|
||||
if (dead || asteroid_count == 0)
|
||||
++counter;
|
||||
if (dead)
|
||||
return;
|
||||
}
|
||||
|
||||
if (asteroid_count == 0 && counter <= COUNTER_MASK)
|
||||
++counter;
|
||||
|
||||
ship_update();
|
||||
|
||||
@@ -472,6 +518,11 @@ void game_update()
|
||||
e->dir = mat2_mul_mat2(mat2_rotation(e->omg), e->dir);
|
||||
e->pos = vec2_add(e->pos, e->vel);
|
||||
|
||||
if (asteroid_count == 0 && i == ship_entity_id) {
|
||||
if (e->pos.x > aspect)
|
||||
win();
|
||||
}
|
||||
|
||||
if (e->pos.y > 1)
|
||||
e->pos.y -= 2;
|
||||
else if (e->pos.y <= -1)
|
||||
@@ -507,6 +558,9 @@ void game_draw()
|
||||
if (dead && !(counter & COUNTER_MASK))
|
||||
text_draw("GAME OVER");
|
||||
|
||||
if (asteroid_count == 0 && counter < COUNTER_MASK)
|
||||
text_draw("CLEAR");
|
||||
if (!dead && asteroid_count == 0) {
|
||||
draw_arrow();
|
||||
if (!(counter & COUNTER_MASK))
|
||||
text_draw("CLEAR");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user