Compare commits
53 Commits
main
..
68e87b807e
| Author | SHA1 | Date | |
|---|---|---|---|
| 68e87b807e | |||
| e4bc796b0f | |||
| 311dd4322d | |||
| 74113c32b4 | |||
| 536ee74b61 | |||
| 34e32c6a46 | |||
| 03f1bedc61 | |||
| 07553feef1 | |||
| a1cfb77cac | |||
| ac0d3de2fb | |||
| 0c510b88d0 | |||
| 2a55eb17ad | |||
| 6d16ba6e27 | |||
| 7e6637dce6 | |||
| a3486b47c7 | |||
| db1fc63652 | |||
| 825938b41a | |||
| 53158b25cc | |||
| f5f25a4463 | |||
| addbe01755 | |||
| c4d0266673 | |||
| ce6328e135 | |||
| 0a64729698 | |||
| 51ce3b43ec | |||
| 47a0c9ffad | |||
| b05a4b3fe4 | |||
| 7d729e42c4 | |||
| d3b1b3f926 | |||
| 85984a0a07 | |||
| 57f5b345f8 | |||
| 1291ec191f | |||
| c3552ae872 | |||
| 8276769446 | |||
| 7b31fcfac5 | |||
| a698e0af7d | |||
| 941cb8745c | |||
| 794a149f00 | |||
| bbb13108e0 | |||
| 94fbbf4636 | |||
| f4b2ad38ea | |||
| 7d876aaf2d | |||
| 44d3bbef69 | |||
| 6d02f0947d | |||
| 0dc7d53bbe | |||
| cbea1d73c7 | |||
| 9bbe8f71ec | |||
| e6ed2194c3 | |||
| 7097b7fb57 | |||
| 87a305c2e5 | |||
| 045d0e6085 | |||
| cb68a98347 | |||
| 1593accd09 | |||
| 7de7f5bfb0 |
@@ -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
@@ -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)
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
Reference in New Issue
Block a user