Add armour items
This commit is contained in:
103
game.c
103
game.c
@@ -35,11 +35,19 @@
|
|||||||
#define ARROW_HEIGHT 4
|
#define ARROW_HEIGHT 4
|
||||||
#define COUNTER_MASK (1 << 6)
|
#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]))
|
#define NELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SHOT_COLLIDE_PRIOR = 1,
|
SHOT_COLLIDE_PRIOR = 1,
|
||||||
SHIP_COLLIDE_PRIOR,
|
SHIP_COLLIDE_PRIOR,
|
||||||
|
ITEM_COLLIDE_PRIOR,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const vec2_t ship_verts[] = {
|
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 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 vec2_t shot_vel = { 0, SHOT_VEL };
|
||||||
|
|
||||||
static const asteroid_size_dist_entry_t easy_dist[] = {
|
static const asteroid_size_dist_entry_t easy_dist[] = {
|
||||||
@@ -85,6 +99,9 @@ static bool paused;
|
|||||||
static unsigned asteroid_count;
|
static unsigned asteroid_count;
|
||||||
static uint8_t counter;
|
static uint8_t counter;
|
||||||
static unsigned score;
|
static unsigned score;
|
||||||
|
static char *msg;
|
||||||
|
static unsigned armour_level;
|
||||||
|
static bool item;
|
||||||
|
|
||||||
static void cleared()
|
static void cleared()
|
||||||
{
|
{
|
||||||
@@ -101,6 +118,17 @@ static void die()
|
|||||||
counter = 0;
|
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)
|
static void shot_collide(unsigned a, unsigned b, physics_sep_t sep)
|
||||||
{
|
{
|
||||||
entity_mark(a);
|
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()
|
static void shoot()
|
||||||
{
|
{
|
||||||
|
if (dead || paused)
|
||||||
|
return;
|
||||||
|
|
||||||
physics_t *ship = physics_get(ship_entity_id);
|
physics_t *ship = physics_get(ship_entity_id);
|
||||||
|
|
||||||
const vec2_t pos
|
const vec2_t pos
|
||||||
@@ -162,10 +207,12 @@ static void anim_fire(vec2_t *verts)
|
|||||||
|
|
||||||
static void create_field()
|
static void create_field()
|
||||||
{
|
{
|
||||||
|
item = false;
|
||||||
dead = false;
|
dead = false;
|
||||||
clear = false;
|
clear = false;
|
||||||
paused = false;
|
paused = false;
|
||||||
asteroid_count = 0;
|
asteroid_count = 0;
|
||||||
|
msg = nullptr;
|
||||||
|
|
||||||
renderer_set_wrap(true);
|
renderer_set_wrap(true);
|
||||||
|
|
||||||
@@ -200,6 +247,7 @@ static void reset()
|
|||||||
{
|
{
|
||||||
level = INIT_LEVEL;
|
level = INIT_LEVEL;
|
||||||
score = 0;
|
score = 0;
|
||||||
|
armour_level = 0;
|
||||||
asteroids_clear();
|
asteroids_clear();
|
||||||
create_field();
|
create_field();
|
||||||
}
|
}
|
||||||
@@ -229,6 +277,24 @@ static void ship_update()
|
|||||||
win();
|
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()
|
void game_init()
|
||||||
{
|
{
|
||||||
input_on_shoot(shoot);
|
input_on_shoot(shoot);
|
||||||
@@ -241,8 +307,10 @@ void game_init()
|
|||||||
|
|
||||||
void game_update()
|
void game_update()
|
||||||
{
|
{
|
||||||
if (dead || clear || paused)
|
if (msg != nullptr || dead || clear || paused)
|
||||||
++counter;
|
++counter;
|
||||||
|
if (counter > COUNTER_MASK)
|
||||||
|
msg = nullptr;
|
||||||
if (dead || paused)
|
if (dead || paused)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -252,6 +320,11 @@ void game_update()
|
|||||||
scene_update();
|
scene_update();
|
||||||
|
|
||||||
entities_purge();
|
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()
|
void game_draw()
|
||||||
@@ -261,16 +334,20 @@ void game_draw()
|
|||||||
scene_draw();
|
scene_draw();
|
||||||
|
|
||||||
text_draw_score(score);
|
text_draw_score(score);
|
||||||
|
if (clear)
|
||||||
if (paused && !(counter & COUNTER_MASK)) {
|
|
||||||
text_draw_centre("PAUSED");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (dead && !(counter & COUNTER_MASK))
|
|
||||||
text_draw_centre("GAME OVER");
|
|
||||||
if (clear) {
|
|
||||||
draw_arrow();
|
draw_arrow();
|
||||||
if (!(counter & COUNTER_MASK))
|
const bool display_text = !(counter & COUNTER_MASK);
|
||||||
text_draw_centre("CLEAR");
|
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