From 7db0c66920b965fa262f306ba0ee6c380a8025bb Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Sat, 18 Oct 2025 17:43:22 +0100 Subject: [PATCH] Add control / update logic --- main.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- maths.c | 73 ++++++++++++++++++++++++++++++++++++++++++-- maths.h | 27 ++++++++++++----- renderer.c | 5 +-- renderer.h | 2 +- 5 files changed, 179 insertions(+), 17 deletions(-) diff --git a/main.c b/main.c index 216787c..f6b1dd3 100644 --- a/main.c +++ b/main.c @@ -3,19 +3,38 @@ #include #include +#include + +#define LIN_PWR 0.0001 +#define ROT_PWR 0.001 #define MAX(a, b) ((a) < (b) ? (b) : (a)) #define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) +static float aspect; static bool quit = false; +static struct { + int rot; + int fwd; +} input; + +static struct { + vec2_t pos; + vec2_t vel; + mat2_t dir; + float omg; +} state; + static const vec2_t ship[] = { - { 0.0, 0.1 }, + { 0.0, 0.08 }, { 0.05, -0.1 }, - { 0.0, -0.05 }, + { 0.0, -0.07 }, { -0.05, -0.1 }, }; +static const vec2_t thrust = { 0, LIN_PWR }; + static void key_press_callback(int key) { switch (key) { @@ -23,21 +42,82 @@ static void key_press_callback(int key) quit = true; break; + case KEY_UP: + ++input.fwd; + break; + + case KEY_LEFT: + ++input.rot; + break; + case KEY_RIGHT: + --input.rot; + break; + default: break; } } +static void key_release_callback(int key) +{ + switch (key) { + case KEY_Q: + quit = true; + break; + + case KEY_UP: + --input.fwd; + break; + + case KEY_LEFT: + --input.rot; + break; + case KEY_RIGHT: + ++input.rot; + break; + + default: + break; + } +} + +static mat3_t update() +{ + state.omg += ROT_PWR * (float)input.rot; + state.dir = mat2_mul_mat2(mat2_rotation(state.omg), state.dir); + + const vec2_t acc + = mat2_mul_vec2(state.dir, vec2_scale(thrust, (float)input.fwd)); + state.vel = vec2_add(state.vel, acc); + state.pos = vec2_add(state.pos, state.vel); + + if (state.pos.y > 1) + state.pos.y -= 2; + else if (state.pos.y < -1) + state.pos.y += 2; + if (state.pos.x > aspect) + state.pos.x -= 2 * aspect; + else if (state.pos.x < -aspect) + state.pos.x += 2 * aspect; + + return mat3_mul_mat3( + mat3_translation(state.pos), mat2_extend(state.dir)); +} + int main() { const int input_fd = input_init(); input_on_press(key_press_callback); + input_on_release(key_release_callback); const renderer_params_t renderer_params = renderer_init(); + aspect = renderer_params.aspect; const int drm_fd = renderer_params.drm_fd; renderer_clear(); renderer_swap(); + state.dir = (mat2_t) { { 1, 0 }, { 0, 1 } }; + const int max_fd = MAX(input_fd, drm_fd); fd_set set; @@ -53,8 +133,11 @@ int main() if (FD_ISSET(drm_fd, &set)) { renderer_handle(); + + const mat3_t m = update(); + renderer_clear(); - renderer_draw(ship, NELEMS(ship)); + renderer_draw(ship, NELEMS(ship), m); renderer_swap(); } } diff --git a/maths.c b/maths.c index 126c4c4..37567eb 100644 --- a/maths.c +++ b/maths.c @@ -1,15 +1,82 @@ #include "maths.h" +#include + +vec2_t vec2_add(vec2_t v1, vec2_t v2) +{ + return (vec2_t) { v1.x + v2.x, v1.y + v2.y }; +} + +vec2_t vec2_scale(vec2_t v, float s) +{ + return (vec2_t) { s * v.x, s * v.y }; +} + vec3_t vec2_extend(vec2_t v) { return (vec3_t) { v.x, v.y, 1 }; } +mat2_t mat2_rotation(float theta) +{ + return (mat2_t) { + { cosf(theta), sinf(theta) }, + { -sinf(theta), cosf(theta) }, + }; +} + +vec2_t mat2_mul_vec2(mat2_t m, vec2_t v) +{ + return (vec2_t) { + m.x.x * v.x + m.y.x * v.y, + m.x.y * v.x + m.y.y * v.y, + }; +} + +mat2_t mat2_mul_mat2(mat2_t m1, mat2_t m2) +{ +#define ELEM(i, j) m1.x.j *m2.i.x + m1.y.j *m2.i.y + return (mat2_t) { + { ELEM(x, x), ELEM(x, y) }, + { ELEM(y, x), ELEM(y, y) }, + }; +#undef ELEM +} + +mat3_t mat2_extend(mat2_t m) +{ + return (mat3_t) { + { m.x.x, m.x.y, 0 }, + { m.y.x, m.y.y, 0 }, + { 0, 0, 1 }, + }; +} + +mat3_t mat3_translation(vec2_t v) +{ + return (mat3_t) { + { 1, 0, 0 }, + { 0, 1, 0 }, + { v.x, v.y, 1 }, + }; +} + vec3_t mat3_mul_vec3(mat3_t m, vec3_t v) { return (vec3_t) { - .x = m.x.x * v.x + m.y.x * v.y + m.z.x * v.z, - .y = m.x.y * v.x + m.y.y * v.y + m.z.y * v.z, - .z = m.x.z * v.x + m.y.z * v.y + m.z.z * v.z, + m.x.x * v.x + m.y.x * v.y + m.z.x * v.z, + m.x.y * v.x + m.y.y * v.y + m.z.y * v.z, + m.x.z * v.x + m.y.z * v.y + m.z.z * v.z, }; } + +mat3_t mat3_mul_mat3(mat3_t m1, mat3_t m2) +{ +#define ELEM(i, j) m1.x.j *m2.i.x + m1.y.j *m2.i.y + m1.z.j *m2.i.z + return (mat3_t) { + { ELEM(x, x), ELEM(x, y), ELEM(x, z) }, + { ELEM(y, x), ELEM(y, y), ELEM(y, z) }, + { ELEM(z, x), ELEM(z, y), ELEM(z, z) }, + }; +#undef ELEM +} diff --git a/maths.h b/maths.h index c38348a..5b720b0 100644 --- a/maths.h +++ b/maths.h @@ -1,24 +1,35 @@ #ifndef MATHS_H #define MATHS_H +#define PI 3.14159265358979323846264 + typedef struct { - float x; - float y; + float x, y; } vec2_t; typedef struct { - float x; - float y; - float z; + vec2_t x, y; +} mat2_t; + +typedef struct { + float x, y, z; } vec3_t; typedef struct { - vec3_t x; - vec3_t y; - vec3_t z; + vec3_t x, y, z; } mat3_t; +vec2_t vec2_add(vec2_t v1, vec2_t v2); +vec2_t vec2_scale(vec2_t v, float s); vec3_t vec2_extend(vec2_t v); + +mat2_t mat2_rotation(float theta); +vec2_t mat2_mul_vec2(mat2_t m, vec2_t v); +mat2_t mat2_mul_mat2(mat2_t m1, mat2_t m2); +mat3_t mat2_extend(mat2_t m); + +mat3_t mat3_translation(vec2_t v); vec3_t mat3_mul_vec3(mat3_t m, vec3_t v); +mat3_t mat3_mul_mat3(mat3_t m1, mat3_t m2); #endif diff --git a/renderer.c b/renderer.c index 1cc42a5..6e1147c 100644 --- a/renderer.c +++ b/renderer.c @@ -143,11 +143,12 @@ void renderer_swap() back = (back + 1) & 1; } -void renderer_draw(const vec2_t *vs, unsigned count) +void renderer_draw(const vec2_t *vs, unsigned count, mat3_t model) { + mat3_t transform = mat3_mul_mat3(view, model); assert(count < MAX_VERTS_PER_DRAW); for (unsigned i = 0; i < count; ++i) - vert_buf[i] = mat3_mul_vec3(view, vec2_extend(vs[i])); + vert_buf[i] = mat3_mul_vec3(transform, vec2_extend(vs[i])); for (unsigned i = 1; i < count; ++i) draw_line(vert_buf[i - 1], vert_buf[i]); draw_line(vert_buf[count - 1], vert_buf[0]); diff --git a/renderer.h b/renderer.h index 71fed06..ff628d5 100644 --- a/renderer.h +++ b/renderer.h @@ -17,6 +17,6 @@ void renderer_handle(); void renderer_clear(); void renderer_swap(); -void renderer_draw(const vec2_t *vs, unsigned count); +void renderer_draw(const vec2_t *vs, unsigned count, mat3_t model); #endif