Add armour items

This commit is contained in:
Camden Dixie O'Brien
2025-10-18 10:58:41 +01:00
parent 74113c32b4
commit 311dd4322d

103
game.c
View File

@@ -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);
}
}