Compare commits

..

53 Commits

Author SHA1 Message Date
Camden Dixie O'Brien 68e87b807e Write README 2025-10-18 17:42:34 +01:00
Camden Dixie O'Brien e4bc796b0f Add license (Komorebi 2.0.0) 2025-10-18 17:42:11 +01:00
Camden Dixie O'Brien 311dd4322d Add armour items 2025-10-18 17:42:08 +01:00
Camden Dixie O'Brien 74113c32b4 Handle wrapping in physics_separation() 2025-10-18 10:58:18 +01:00
Camden Dixie O'Brien 536ee74b61 Refactor into more modular architecture 2025-10-17 14:59:41 +01:00
Camden Dixie O'Brien 34e32c6a46 Make aspect global 2025-10-16 14:28:59 +01:00
Camden Dixie O'Brien 03f1bedc61 Add pausing 2025-10-16 14:22:10 +01:00
Camden Dixie O'Brien 07553feef1 Add score 2025-10-16 13:45:31 +01:00
Camden Dixie O'Brien a1cfb77cac Add levelling 2025-10-15 18:37:21 +01:00
Camden Dixie O'Brien ac0d3de2fb Only display "clear" message for a short time 2025-10-15 14:58:17 +01:00
Camden Dixie O'Brien 0c510b88d0 Don't spawn small asteroids 2025-10-15 14:45:08 +01:00
Camden Dixie O'Brien 2a55eb17ad Add huge asteroids 2025-10-15 14:44:29 +01:00
Camden Dixie O'Brien 6d16ba6e27 Add "clear" text when all asteroids destroyed 2025-10-15 14:21:31 +01:00
Camden Dixie O'Brien 7e6637dce6 Create text module for displaying messages 2025-10-15 14:21:31 +01:00
Camden Dixie O'Brien a3486b47c7 Add restart and handle quitting with callback 2025-10-15 13:13:44 +01:00
Camden Dixie O'Brien db1fc63652 Add game over message 2025-10-15 13:04:14 +01:00
Camden Dixie O'Brien 825938b41a Track asteroid count 2025-10-15 13:03:56 +01:00
Camden Dixie O'Brien 53158b25cc Add shooting recoil 2025-10-15 13:02:07 +01:00
Camden Dixie O'Brien f5f25a4463 Add renderer function to clear rectangle 2025-10-15 13:01:18 +01:00
Camden Dixie O'Brien addbe01755 Tweak some parameters 2025-10-14 19:29:32 +01:00
Camden Dixie O'Brien c4d0266673 Wrap all entities and shapes 2025-10-14 19:04:40 +01:00
Camden Dixie O'Brien ce6328e135 Replace big asteroids with smaller ones when shot 2025-10-14 18:29:56 +01:00
Camden Dixie O'Brien 0a64729698 Prevent asteroids from spawning overlapped 2025-10-14 17:38:43 +01:00
Camden Dixie O'Brien 51ce3b43ec Increase min distance asteroids spawn at 2025-10-14 17:28:23 +01:00
Camden Dixie O'Brien 47a0c9ffad Implement asteroid bouncing 2025-10-14 17:19:02 +01:00
Camden Dixie O'Brien b05a4b3fe4 Rename collision_radius to just radius 2025-10-14 16:56:53 +01:00
Camden Dixie O'Brien 7d729e42c4 Handle collisions 2025-10-14 16:51:52 +01:00
Camden Dixie O'Brien d3b1b3f926 Implement collision detection 2025-10-14 16:51:42 +01:00
Camden Dixie O'Brien 85984a0a07 Add collision info to entities 2025-10-14 16:14:35 +01:00
Camden Dixie O'Brien 57f5b345f8 Refactor asteroid generation 2025-10-14 16:09:38 +01:00
Camden Dixie O'Brien 1291ec191f Add more vector operations 2025-10-14 16:04:14 +01:00
Camden Dixie O'Brien c3552ae872 Add asteroids 2025-10-14 14:34:12 +01:00
Camden Dixie O'Brien 8276769446 Move all input handling into input module 2025-10-14 12:29:13 +01:00
Camden Dixie O'Brien 7b31fcfac5 Create RNG module 2025-10-14 12:06:06 +01:00
Camden Dixie O'Brien a698e0af7d Factor game logic into own module 2025-10-13 23:25:46 +01:00
Camden Dixie O'Brien 941cb8745c Increase max shapes and entities 2025-10-13 22:41:13 +01:00
Camden Dixie O'Brien 794a149f00 Allow display wrapping to be specified per shape 2025-10-13 22:41:09 +01:00
Camden Dixie O'Brien bbb13108e0 Add shooting 2025-10-13 22:41:09 +01:00
Camden Dixie O'Brien 94fbbf4636 Add random jitter to fire 2025-10-13 21:21:09 +01:00
Camden Dixie O'Brien f4b2ad38ea Move ship vertices so origin is closer to visual centre 2025-10-13 21:10:43 +01:00
Camden Dixie O'Brien 7d876aaf2d Refactor to seperate shapes and physics 2025-10-13 21:04:50 +01:00
Camden Dixie O'Brien 44d3bbef69 Rename MAX_VERTS_PER_DRAW to MAX_VERTS 2025-10-13 20:14:10 +01:00
Camden Dixie O'Brien 6d02f0947d Grab input device to stop key events reaching terminal 2025-10-13 20:14:07 +01:00
Camden Dixie O'Brien 0dc7d53bbe Add fire when thrust is active 2025-10-13 20:14:07 +01:00
Camden Dixie O'Brien cbea1d73c7 Use warning flags in build script 2025-10-13 18:44:20 +01:00
Camden Dixie O'Brien 9bbe8f71ec Add control / update logic 2025-10-13 18:43:40 +01:00
Camden Dixie O'Brien e6ed2194c3 Fix wrapping 2025-10-13 18:42:18 +01:00
Camden Dixie O'Brien 7097b7fb57 Implement simple line drawing 2025-10-13 16:22:10 +01:00
Camden Dixie O'Brien 87a305c2e5 Create separate input module 2025-10-13 16:09:02 +01:00
Camden Dixie O'Brien 045d0e6085 Create separate renderer and framebuffer modules 2025-10-13 16:09:02 +01:00
Camden Dixie O'Brien cb68a98347 Set up input handling 2025-10-13 13:07:20 +01:00
Camden Dixie O'Brien 1593accd09 Implement back-buffering 2025-10-12 19:17:21 +01:00
Camden Dixie O'Brien 7de7f5bfb0 Set up drawing to framebuffer 2025-10-12 18:22:18 +01:00
7 changed files with 39 additions and 111 deletions
+2 -4
View File
@@ -3,10 +3,8 @@
This is a clone (ish) of the classic game Asteroids, written in C23 This is a clone (ish) of the classic game Asteroids, written in C23
for Linux. To build the program, you'll need the Linux headers, a for Linux. To build the program, you'll need the Linux headers, a
C23-compatible compiler and libdrm, along with its headers. There is C23-compatible compiler and libdrm, along with its headers. There is
a build script that uses GCC; simply running this (./build.sh) is a build script that uses GCC; simply running this (`./build.sh`) is
likely to work on many systems. However, you will likely need to likely to work on many systems.
adjust the input and video devices used (in input.c and renderer.c
respectively) to match your system.
The game directly uses Linux DRM, so it doesn't play nice with X, The game directly uses Linux DRM, so it doesn't play nice with X,
display managers etc. You'll likely want to change to a virtual TTY display managers etc. You'll likely want to change to a virtual TTY
+6 -6
View File
@@ -13,9 +13,9 @@
#define MIN_VERTS 5 #define MIN_VERTS 5
#define VERT_RANGE (MAX_VERTS - MIN_VERTS) #define VERT_RANGE (MAX_VERTS - MIN_VERTS)
#define A_JITTER 0.8 #define A_JITTER 0.8
#define V_JITTER 0.0005 #define V_JITTER 0.001
#define ROT_JITTER 0.005 #define ROT_JITTER 0.005
#define R_JITTER 0.01 #define R_JITTER 0.02
#define MIN_DIST 0.8 #define MIN_DIST 0.8
#define REPLACE_MIN 3 #define REPLACE_MIN 3
@@ -41,10 +41,10 @@ static unsigned count;
static entry_t entries[MAX_ENTITIES]; static entry_t entries[MAX_ENTITIES];
static float radii[] = { static float radii[] = {
[ASTEROID_SMALL] = 0.025f, [ASTEROID_SMALL] = 0.05f,
[ASTEROID_MEDIUM] = 0.05f, [ASTEROID_MEDIUM] = 0.1f,
[ASTEROID_LARGE] = 0.1f, [ASTEROID_LARGE] = 0.2f,
[ASTEROID_HUGE] = 0.2f, [ASTEROID_HUGE] = 0.4f,
}; };
static void update(unsigned new_entity_id, void *ref) static void update(unsigned new_entity_id, void *ref)
+1 -2
View File
@@ -9,5 +9,4 @@ defs="-D_POSIX_C_SOURCE=200809L"
$cc $warn $flags $libs $defs \ $cc $warn $flags $libs $defs \
-o asteroids \ -o asteroids \
asteroids.c collisions.c entity.c fb.c game.c input.c \ asteroids.c collisions.c entity.c fb.c game.c input.c \
main.c maths.c physics.c scene.c renderer.c rng.c \ main.c maths.c physics.c scene.c renderer.c rng.c text.c
self_destruct.c text.c
+29 -30
View File
@@ -8,7 +8,6 @@
#include "renderer.h" #include "renderer.h"
#include "rng.h" #include "rng.h"
#include "scene.h" #include "scene.h"
#include "self_destruct.h"
#include "text.h" #include "text.h"
#include <assert.h> #include <assert.h>
@@ -16,34 +15,32 @@
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
#define FPS 60
#define INIT_LEVEL 1 #define INIT_LEVEL 1
#define SHIP_COLLIDE_R 0.025 #define SHIP_COLLIDE_R 0.05
#define SHIP_MASS 0.01 #define SHIP_MASS 0.02
#define FIRE_JITTER 0.005 #define FIRE_MEAN -0.15
#define FIRE_JITTER 0.01
#define LIN_PWR 0.00005 #define LIN_PWR 0.0001
#define ROT_PWR 0.002 #define ROT_PWR 0.002
#define SHOT_VEL 0.03 #define SHOT_VEL 0.03
#define SHOT_COLLIDE_R 0.015 #define SHOT_COLLIDE_R 0.03
#define SHOT_MASS 0.00025 #define SHOT_MASS 0.001
#define SHOT_LIFETIME_S 4
#define ARROW_SCALE 0.0125 #define ARROW_SCALE 0.025
#define ARROW_WIDTH 4 #define ARROW_WIDTH 4
#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_SPAWN_R 0.9
#define ITEM_COLLIDE_R 0.0125 #define ITEM_COLLIDE_R 0.025
#define ITEM_SPAWN_EXP_S 40 #define ITEM_SPAWN_EXP_S 40
#define ITEM_MIN_SCORE 32 #define ITEM_MIN_SCORE 32
#define ARMOUR_COEFF 2.5e-6 #define ARMOUR_COEFF 5e-6
#define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) #define NELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
@@ -54,17 +51,17 @@ enum {
}; };
static const vec2_t ship_verts[] = { static const vec2_t ship_verts[] = {
{ 0.0, 0.055 }, { 0.0, 0.11 },
{ 0.025, -0.035 }, { 0.05, -0.07 },
{ 0.0, -0.02 }, { 0.0, -0.04 },
{ -0.025, -0.035 }, { -0.05, -0.07 },
}; };
static const vec2_t fire_verts[] = { static const vec2_t fire_verts[] = {
{ 0.0, -0.075 }, { 0.0, -0.15 },
{ 0.0075, -0.035 }, { 0.015, -0.07 },
{ -0.0075, -0.035 }, { -0.015, -0.07 },
}; };
static const vec2_t shot_verts[] = { { 0.0, -0.01 }, { 0.0, 0.01 } }; static const vec2_t shot_verts[] = { { 0.0, -0.02 }, { 0.0, 0.02 } };
static const vec2_t arrow_verts[][MAX_VERTS] = { static const vec2_t arrow_verts[][MAX_VERTS] = {
{ { 1, 2 }, { 2, 0 }, { 1, -2 } }, { { 1, 2 }, { 2, 0 }, { 1, -2 } },
@@ -73,8 +70,8 @@ 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] = { static const vec2_t item_verts[][MAX_VERTS] = {
{ { -0.0125, -0.0125 }, { 0.0125, 0.0125 } }, { { -0.025, -0.025 }, { 0.025, 0.025 } },
{ { -0.0125, 0.0125 }, { 0.0125, -0.0125 } }, { { -0.025, 0.025 }, { 0.025, -0.025 } },
}; };
static const unsigned item_counts[NELEMS(item_verts)] = { 2, 2 }; static const unsigned item_counts[NELEMS(item_verts)] = { 2, 2 };
@@ -178,7 +175,6 @@ static void shoot()
scene_add(id, shot_verts, NELEMS(shot_verts), false); scene_add(id, shot_verts, NELEMS(shot_verts), false);
physics_add(id, pos, ship->dir, vel, 0, SHOT_MASS); physics_add(id, pos, ship->dir, vel, 0, SHOT_MASS);
collisions_add(id, SHOT_COLLIDE_R, SHOT_COLLIDE_PRIOR, shot_collide); 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_ship = vec2_scale(ship->vel, ship->mass);
const vec2_t p_shot = vec2_scale(vel, SHOT_MASS); const vec2_t p_shot = vec2_scale(vel, SHOT_MASS);
@@ -194,13 +190,19 @@ static void draw_arrow()
{ tx, 0, 1 }, { tx, 0, 1 },
}; };
const vec3_t c_mod = { 0, 0, 1 };
const vec3_t s_mod = { ARROW_WIDTH + 2, ARROW_HEIGHT + 2, 0 };
const vec3_t c = mat3_mul_vec3(m, c_mod);
const vec3_t s = mat3_mul_vec3(m, s_mod);
renderer_clear_rect(vec3_reduce(c), (vec2_t) { s.x, s.y });
for (unsigned i = 0; i < NELEMS(arrow_verts); ++i) for (unsigned i = 0; i < NELEMS(arrow_verts); ++i)
renderer_draw(arrow_verts[i], arrow_counts[i], m, false); renderer_draw(arrow_verts[i], arrow_counts[i], m, false);
} }
static void anim_fire(vec2_t *verts) static void anim_fire(vec2_t *verts)
{ {
verts[0].y = fire_verts[0].y + FIRE_JITTER * rng_plusminus(); verts[0].y = FIRE_MEAN + FIRE_JITTER * rng_plusminus();
} }
static void create_field() static void create_field()
@@ -218,7 +220,6 @@ static void create_field()
scene_clear(); scene_clear();
physics_init(); physics_init();
collisions_init(); collisions_init();
self_destruct_clear();
ship_entity_id = entity_add(); ship_entity_id = entity_add();
scene_add(ship_entity_id, ship_verts, NELEMS(ship_verts), true); scene_add(ship_entity_id, ship_verts, NELEMS(ship_verts), true);
@@ -315,16 +316,14 @@ void game_update()
ship_update(); ship_update();
physics_update(); physics_update();
self_destruct_update();
collisions_update(); collisions_update();
scene_update(); scene_update();
entities_purge(); entities_purge();
const bool items_enabled const bool items_enabled = score >= ITEM_MIN_SCORE;
= !clear && score >= ITEM_MIN_SCORE && armour_level < 9;
if (items_enabled && !item if (items_enabled && !item
&& rng_canon() < 1.0f / (FPS * ITEM_SPAWN_EXP_S)) && rng_canon() < 1.0f / (60 * ITEM_SPAWN_EXP_S))
add_item(); add_item();
} }
-60
View File
@@ -1,60 +0,0 @@
#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
View File
@@ -1,8 +0,0 @@
#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
+1 -1
View File
@@ -9,7 +9,7 @@
#define MAX_LINES 2 #define MAX_LINES 2
#define TEXT_HEIGHT 8 #define TEXT_HEIGHT 8
#define TEXT_SCALE 0.0125 #define TEXT_SCALE 0.025
#define LETTER_WIDTH 3 #define LETTER_WIDTH 3
#define SPACE_WIDTH 1 #define SPACE_WIDTH 1