Add armour items
This commit is contained in:
103
game.c
103
game.c
@@ -35,11 +35,19 @@
|
||||
#define ARROW_HEIGHT 4
|
||||
#define COUNTER_MASK (1 << 6)
|
||||
|
||||
#define ITEM_SPAWN_R 0.9
|
||||
#define ITEM_COLLIDE_R 0.025
|
||||
#define ITEM_SPAWN_EXP_S 40
|
||||
#define ITEM_MIN_SCORE 32
|
||||
|
||||
#define ARMOUR_COEFF 5e-6
|
||||
|
||||
#define NELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||
|
||||
enum {
|
||||
SHOT_COLLIDE_PRIOR = 1,
|
||||
SHIP_COLLIDE_PRIOR,
|
||||
ITEM_COLLIDE_PRIOR,
|
||||
};
|
||||
|
||||
static const vec2_t ship_verts[] = {
|
||||
@@ -61,6 +69,12 @@ static const vec2_t arrow_verts[][MAX_VERTS] = {
|
||||
};
|
||||
static const unsigned arrow_counts[NELEMS(arrow_verts)] = { 3, 2 };
|
||||
|
||||
static const vec2_t item_verts[][MAX_VERTS] = {
|
||||
{ { -0.025, -0.025 }, { 0.025, 0.025 } },
|
||||
{ { -0.025, 0.025 }, { 0.025, -0.025 } },
|
||||
};
|
||||
static const unsigned item_counts[NELEMS(item_verts)] = { 2, 2 };
|
||||
|
||||
static const vec2_t shot_vel = { 0, SHOT_VEL };
|
||||
|
||||
static const asteroid_size_dist_entry_t easy_dist[] = {
|
||||
@@ -85,6 +99,9 @@ static bool paused;
|
||||
static unsigned asteroid_count;
|
||||
static uint8_t counter;
|
||||
static unsigned score;
|
||||
static char *msg;
|
||||
static unsigned armour_level;
|
||||
static bool item;
|
||||
|
||||
static void cleared()
|
||||
{
|
||||
@@ -101,6 +118,17 @@ static void die()
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
static void upgrade_armour()
|
||||
{
|
||||
if (armour_level >= 9)
|
||||
return;
|
||||
|
||||
static char armour_msg[] = "ARMOUR X";
|
||||
armour_msg[7] = '0' + ++armour_level;
|
||||
msg = armour_msg;
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
static void shot_collide(unsigned a, unsigned b, physics_sep_t sep)
|
||||
{
|
||||
entity_mark(a);
|
||||
@@ -112,13 +140,30 @@ static void shot_collide(unsigned a, unsigned b, physics_sep_t sep)
|
||||
}
|
||||
}
|
||||
|
||||
static void ship_collide(unsigned, unsigned, physics_sep_t)
|
||||
static void ship_collide(unsigned a, unsigned b, physics_sep_t sep)
|
||||
{
|
||||
die();
|
||||
const float v = sep.va - sep.vb;
|
||||
const float impact = physics_get(b)->mass * v;
|
||||
const float armour = armour_level * ARMOUR_COEFF;
|
||||
if (impact < armour)
|
||||
physics_bounce(a, b, sep);
|
||||
else
|
||||
die();
|
||||
}
|
||||
|
||||
static void item_collide(unsigned a, unsigned b, physics_sep_t)
|
||||
{
|
||||
item = false;
|
||||
entity_mark(a);
|
||||
if (b == ship_entity_id)
|
||||
upgrade_armour();
|
||||
}
|
||||
|
||||
static void shoot()
|
||||
{
|
||||
if (dead || paused)
|
||||
return;
|
||||
|
||||
physics_t *ship = physics_get(ship_entity_id);
|
||||
|
||||
const vec2_t pos
|
||||
@@ -162,10 +207,12 @@ static void anim_fire(vec2_t *verts)
|
||||
|
||||
static void create_field()
|
||||
{
|
||||
item = false;
|
||||
dead = false;
|
||||
clear = false;
|
||||
paused = false;
|
||||
asteroid_count = 0;
|
||||
msg = nullptr;
|
||||
|
||||
renderer_set_wrap(true);
|
||||
|
||||
@@ -200,6 +247,7 @@ static void reset()
|
||||
{
|
||||
level = INIT_LEVEL;
|
||||
score = 0;
|
||||
armour_level = 0;
|
||||
asteroids_clear();
|
||||
create_field();
|
||||
}
|
||||
@@ -229,6 +277,24 @@ static void ship_update()
|
||||
win();
|
||||
}
|
||||
|
||||
static void add_item()
|
||||
{
|
||||
const unsigned id = entity_add();
|
||||
|
||||
for (unsigned i = 0; i < NELEMS(item_verts); ++i)
|
||||
scene_add(id, item_verts[i], item_counts[i], false);
|
||||
|
||||
const vec2_t pos = {
|
||||
.x = ITEM_SPAWN_R * rng_plusminus(),
|
||||
.y = ITEM_SPAWN_R * rng_plusminus(),
|
||||
};
|
||||
physics_add(id, pos, MAT2_ID, (vec2_t) {}, 0, 0);
|
||||
|
||||
collisions_add(id, ITEM_COLLIDE_R, ITEM_COLLIDE_PRIOR, item_collide);
|
||||
|
||||
item = true;
|
||||
}
|
||||
|
||||
void game_init()
|
||||
{
|
||||
input_on_shoot(shoot);
|
||||
@@ -241,8 +307,10 @@ void game_init()
|
||||
|
||||
void game_update()
|
||||
{
|
||||
if (dead || clear || paused)
|
||||
if (msg != nullptr || dead || clear || paused)
|
||||
++counter;
|
||||
if (counter > COUNTER_MASK)
|
||||
msg = nullptr;
|
||||
if (dead || paused)
|
||||
return;
|
||||
|
||||
@@ -252,6 +320,11 @@ void game_update()
|
||||
scene_update();
|
||||
|
||||
entities_purge();
|
||||
|
||||
const bool items_enabled = score >= ITEM_MIN_SCORE;
|
||||
if (items_enabled && !item
|
||||
&& rng_canon() < 1.0f / (60 * ITEM_SPAWN_EXP_S))
|
||||
add_item();
|
||||
}
|
||||
|
||||
void game_draw()
|
||||
@@ -261,16 +334,20 @@ void game_draw()
|
||||
scene_draw();
|
||||
|
||||
text_draw_score(score);
|
||||
|
||||
if (paused && !(counter & COUNTER_MASK)) {
|
||||
text_draw_centre("PAUSED");
|
||||
return;
|
||||
}
|
||||
if (dead && !(counter & COUNTER_MASK))
|
||||
text_draw_centre("GAME OVER");
|
||||
if (clear) {
|
||||
if (clear)
|
||||
draw_arrow();
|
||||
if (!(counter & COUNTER_MASK))
|
||||
text_draw_centre("CLEAR");
|
||||
const bool display_text = !(counter & COUNTER_MASK);
|
||||
if (display_text) {
|
||||
if (dead)
|
||||
text_draw_centre("GAME OVER");
|
||||
if (clear) {
|
||||
draw_arrow();
|
||||
if (!(counter & COUNTER_MASK))
|
||||
text_draw_centre("CLEAR");
|
||||
}
|
||||
if (paused)
|
||||
text_draw_centre("PAUSED");
|
||||
if (msg != nullptr)
|
||||
text_draw_centre(msg);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user