Make shots self-destruct after 4 seconds

This commit is contained in:
2025-10-19 18:41:06 +01:00
parent cc5c118582
commit 6aec397072
4 changed files with 78 additions and 2 deletions

View File

@@ -9,4 +9,5 @@ defs="-D_POSIX_C_SOURCE=200809L"
$cc $warn $flags $libs $defs \
-o asteroids \
asteroids.c collisions.c entity.c fb.c game.c input.c \
main.c maths.c physics.c scene.c renderer.c rng.c text.c
main.c maths.c physics.c scene.c renderer.c rng.c \
self_destruct.c text.c

9
game.c
View File

@@ -8,6 +8,7 @@
#include "renderer.h"
#include "rng.h"
#include "scene.h"
#include "self_destruct.h"
#include "text.h"
#include <assert.h>
@@ -15,6 +16,8 @@
#include <math.h>
#include <string.h>
#define FPS 60
#define INIT_LEVEL 1
#define SHIP_COLLIDE_R 0.025
@@ -28,6 +31,7 @@
#define SHOT_VEL 0.03
#define SHOT_COLLIDE_R 0.015
#define SHOT_MASS 0.00025
#define SHOT_LIFETIME_S 4
#define ARROW_SCALE 0.0125
#define ARROW_WIDTH 4
@@ -174,6 +178,7 @@ static void shoot()
scene_add(id, shot_verts, NELEMS(shot_verts), false);
physics_add(id, pos, ship->dir, vel, 0, SHOT_MASS);
collisions_add(id, SHOT_COLLIDE_R, SHOT_COLLIDE_PRIOR, shot_collide);
self_destruct_add(id, FPS * SHOT_LIFETIME_S);
const vec2_t p_ship = vec2_scale(ship->vel, ship->mass);
const vec2_t p_shot = vec2_scale(vel, SHOT_MASS);
@@ -213,6 +218,7 @@ static void create_field()
scene_clear();
physics_init();
collisions_init();
self_destruct_clear();
ship_entity_id = entity_add();
scene_add(ship_entity_id, ship_verts, NELEMS(ship_verts), true);
@@ -309,6 +315,7 @@ void game_update()
ship_update();
physics_update();
self_destruct_update();
collisions_update();
scene_update();
@@ -317,7 +324,7 @@ void game_update()
const bool items_enabled
= !clear && score >= ITEM_MIN_SCORE && armour_level < 9;
if (items_enabled && !item
&& rng_canon() < 1.0f / (60 * ITEM_SPAWN_EXP_S))
&& rng_canon() < 1.0f / (FPS * ITEM_SPAWN_EXP_S))
add_item();
}

60
self_destruct.c Normal file
View File

@@ -0,0 +1,60 @@
#include "self_destruct.h"
#include "entity.h"
#include <assert.h>
#include <string.h>
#define MAX 256U
typedef struct {
unsigned entity_id;
unsigned component_id;
unsigned rem;
} cmp_t;
static unsigned count;
static cmp_t cmps[MAX];
static void update(unsigned new_entity_id, void *ref)
{
cmp_t *c = (cmp_t *)ref;
c->entity_id = new_entity_id;
}
static void remove(void *ref)
{
cmp_t *c = (cmp_t *)ref;
const cmp_t *last = cmps + (count - 1);
if (c < last) {
memcpy(c, last, sizeof(cmp_t));
entity_update_component(c->entity_id, c->component_id, c);
}
--count;
}
void self_destruct_clear()
{
count = 0;
}
void self_destruct_update()
{
for (unsigned i = 0; i < count; ++i) {
if (cmps[i].rem == 0)
entity_mark(cmps[i].entity_id);
else
--cmps[i].rem;
}
}
void self_destruct_add(unsigned id, unsigned frames)
{
assert(count < MAX);
cmp_t *c = cmps + count++;
*c = (cmp_t) {
.entity_id = id,
.rem = frames,
.component_id = entity_add_component(id, update, remove, c),
};
}

8
self_destruct.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef SELF_DESTRUCT_H
#define SELF_DESTRUCT_H
void self_destruct_clear();
void self_destruct_update();
void self_destruct_add(unsigned id, unsigned frames);
#endif