diff --git a/main.c b/main.c index 6a5d26b..f5d15c6 100644 --- a/main.c +++ b/main.c @@ -1,9 +1,11 @@ #include "input.h" #include "renderer.h" +#include #include #include #include +#include #include #include @@ -16,8 +18,11 @@ #define LIN_PWR 0.0001 #define ROT_PWR 0.002 +#define SHOT_VEL 0.04 + #define MAX_SHAPES 8U #define MAX_ENTITIES 8U +#define MAX_SHAPES_PER_ENTITY 2 #define MAX(a, b) ((a) < (b) ? (b) : (a)) #define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) @@ -34,8 +39,13 @@ typedef struct { vec2_t vel; mat2_t dir; float omg; + unsigned shapes[MAX_SHAPES_PER_ENTITY]; + unsigned shape_count; + bool wrap; } entity_t; +static vec2_t shot_verts[] = { { 0.0, -0.015 }, { 0.0, 0.015 } }; + static shape_t shapes[MAX_SHAPES] = { { .visible = true, @@ -61,7 +71,12 @@ static shape_t shapes[MAX_SHAPES] = { }; static entity_t entities[MAX_ENTITIES] = { - { .dir = { { 1, 0 }, { 0, 1 } } }, + { + .dir = { { 1, 0 }, { 0, 1 } }, + .shape_count = 2, + .shapes = { 0, 1 }, + .wrap = true, + }, }; static mat3_t transforms[MAX_ENTITIES]; @@ -76,6 +91,67 @@ static struct { int fwd; } input; +static void shoot() +{ + if (entity_count >= MAX_ENTITIES || shape_count >= MAX_SHAPES) + return; + + const entity_t *ship = entities + SHIP; + const shape_t *ship_shape = shapes + SHIP; + + const int id = entity_count++; + entity_t *e = entities + id; + e->dir = ship->dir; + e->pos = vec2_add( + ship->pos, mat2_mul_vec2(ship->dir, ship_shape->verts[0])); + e->vel = vec2_add( + ship->vel, mat2_mul_vec2(ship->dir, (vec2_t) { 0, SHOT_VEL })); + e->omg = 0; + + const int shape_id = shape_count++; + shape_t *s = shapes + shape_id; + s->visible = true; + s->entity = id; + s->vert_count = NELEMS(shot_verts); + memcpy(s->verts, shot_verts, sizeof(shot_verts)); + + e->shapes[0] = shape_id; + e->shape_count = 1; +} + +static void remove_shape(unsigned id) +{ + if (id < shape_count - 1) { + const shape_t *last = shapes + shape_count - 1; + memcpy(shapes + id, shapes + shape_count - 1, sizeof(shape_t)); + for (unsigned i = 0; i < entities[last->entity].shape_count; ++i) { + if (entities[last->entity].shapes[i] == shape_count - 1) { + entities[last->entity].shapes[i] = id; + break; + } + } + } + --shape_count; +} + +static void remove_entity(unsigned id) +{ + assert(id != SHIP); + + entity_t *e = entities + id; + for (unsigned i = 0; i < e->shape_count; ++i) + remove_shape(e->shapes[i]); + + if (id < entity_count - 1) { + const entity_t *last = entities + entity_count - 1; + memcpy(e, last, sizeof(entity_t)); + for (unsigned i = 0; i < e->shape_count; ++i) + shapes[e->shapes[i]].entity = id; + } + + --entity_count; +} + static void key_press_callback(int key) { switch (key) { @@ -94,6 +170,10 @@ static void key_press_callback(int key) --input.rot; break; + case KEY_SPACE: + shoot(); + break; + default: break; } @@ -102,10 +182,6 @@ static void key_press_callback(int key) static void key_release_callback(int key) { switch (key) { - case KEY_Q: - quit = true; - break; - case KEY_UP: --input.fwd; break; @@ -122,6 +198,15 @@ static void key_release_callback(int key) } } +static void key_repeat_callback(int key) +{ + switch (key) { + case KEY_SPACE: + shoot(); + break; + } +} + static mat3_t entity_transform(unsigned id) { const entity_t *e = entities + id; @@ -157,14 +242,22 @@ static void update() e->dir = mat2_mul_mat2(mat2_rotation(e->omg), e->dir); e->pos = vec2_add(e->pos, e->vel); - if (e->pos.y > 1) - e->pos.y -= 2; - else if (e->pos.y < -1) - e->pos.y += 2; - if (e->pos.x > aspect) - e->pos.x -= 2 * aspect; - else if (e->pos.x < -aspect) - e->pos.x += 2 * aspect; + if (e->wrap) { + if (e->pos.y > 1) + e->pos.y -= 2; + else if (e->pos.y <= -1) + e->pos.y += 2; + if (e->pos.x >= aspect) + e->pos.x -= 2 * aspect; + else if (e->pos.x < -aspect) + e->pos.x += 2 * aspect; + } else { + if (e->pos.y > 1 || e->pos.y <= -1 || e->pos.x >= aspect + || e->pos.x < -aspect) { + remove_entity(i--); + continue; + } + } transforms[i] = entity_transform(i); } @@ -190,6 +283,7 @@ int main() const int input_fd = input_init(); input_on_press(key_press_callback); input_on_release(key_release_callback); + input_on_repeat(key_repeat_callback); const renderer_params_t renderer_params = renderer_init(); aspect = renderer_params.aspect;