Create text module for displaying messages
This commit is contained in:
2
build.sh
2
build.sh
@@ -8,4 +8,4 @@ defs="-D_POSIX_C_SOURCE=200809L"
|
|||||||
|
|
||||||
$cc $warn $flags $libs $defs \
|
$cc $warn $flags $libs $defs \
|
||||||
-o asteroids \
|
-o asteroids \
|
||||||
fb.c game.c input.c main.c maths.c renderer.c rng.c
|
fb.c game.c input.c main.c maths.c renderer.c rng.c text.c
|
||||||
|
|||||||
50
game.c
50
game.c
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
|
#include "text.h"
|
||||||
#include "rng.h"
|
#include "rng.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@@ -51,10 +52,7 @@
|
|||||||
#define MAX_SHAPES_PER_ENTITY 2
|
#define MAX_SHAPES_PER_ENTITY 2
|
||||||
#define MAX_COLLISIONS 128U
|
#define MAX_COLLISIONS 128U
|
||||||
|
|
||||||
#define GAME_OVER_WIDTH 24
|
#define COUNTER_MASK (1 << 6)
|
||||||
#define GAME_OVER_HEIGHT 8
|
|
||||||
#define GAME_OVER_SCALE 0.025
|
|
||||||
#define GAME_OVER_COUNTER_MASK (1 << 6)
|
|
||||||
|
|
||||||
#define NELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
|
#define NELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||||
|
|
||||||
@@ -103,40 +101,6 @@ static const vec2_t fire_verts[] = {
|
|||||||
};
|
};
|
||||||
static const vec2_t shot_verts[] = { { 0.0, -0.02 }, { 0.0, 0.02 } };
|
static const vec2_t shot_verts[] = { { 0.0, -0.02 }, { 0.0, 0.02 } };
|
||||||
|
|
||||||
static const vec2_t game_over_verts[][MAX_VERTS] = {
|
|
||||||
// G
|
|
||||||
{ { -10, 4 }, { -12, 4 }, { -12, -4 }, { -10, -4 }, { -10, 0 } },
|
|
||||||
// A
|
|
||||||
{ { -9, -4 }, { -8, 4 }, { -7, -4 } },
|
|
||||||
{ { -8.75, -2 }, { -7.25, -2 } },
|
|
||||||
// M
|
|
||||||
{ { -6, -4 }, { -6, 4 }, { -5, -4 }, { -4, 4 }, { -4, -4 } },
|
|
||||||
// E
|
|
||||||
{ { -1, 4 }, { -3, 4 }, { -3, -4 }, { -1, -4 } },
|
|
||||||
{ { -3, 0 }, { -2, 0 } },
|
|
||||||
// O
|
|
||||||
{ { 1, 4 }, { 1, -4 }, { 3, -4 }, { 3, 4 }, { 1, 4 } },
|
|
||||||
// V
|
|
||||||
{ { 4, 4 }, { 5, -4 }, { 6, 4 } },
|
|
||||||
// E
|
|
||||||
{ { 9, 4 }, { 7, 4 }, { 7, -4 }, { 9, -4 } },
|
|
||||||
{ { 7, 0 }, { 8, 0 } },
|
|
||||||
// R
|
|
||||||
{ { 10, -4 }, { 10, 4 }, { 12, 4 }, { 12, -2 }, { 10, -2 }, { 12, -4 } },
|
|
||||||
};
|
|
||||||
static const unsigned game_over_lens[NELEMS(game_over_verts)] = {
|
|
||||||
5, 3, 2, 5, 4, 2, 5, 3, 4, 2, 6,
|
|
||||||
};
|
|
||||||
static const mat3_t game_over_transform = {
|
|
||||||
{ GAME_OVER_SCALE, 0, 0 },
|
|
||||||
{ 0, GAME_OVER_SCALE, 0 },
|
|
||||||
{ 0, 0, 1 },
|
|
||||||
};
|
|
||||||
static const vec2_t game_over_bg = {
|
|
||||||
.x = (GAME_OVER_WIDTH + 2) * GAME_OVER_SCALE,
|
|
||||||
.y = (GAME_OVER_HEIGHT + 2) * GAME_OVER_SCALE,
|
|
||||||
};
|
|
||||||
|
|
||||||
static entity_t entities[MAX_ENTITIES];
|
static entity_t entities[MAX_ENTITIES];
|
||||||
static mat3_t transforms[MAX_ENTITIES];
|
static mat3_t transforms[MAX_ENTITIES];
|
||||||
static shape_t shapes[MAX_SHAPES];
|
static shape_t shapes[MAX_SHAPES];
|
||||||
@@ -530,12 +494,6 @@ void game_draw()
|
|||||||
shapes[i].connect);
|
shapes[i].connect);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dead && !(counter & GAME_OVER_COUNTER_MASK)) {
|
if (dead && !(counter & COUNTER_MASK))
|
||||||
renderer_clear_rect((vec2_t) { 0, 0 }, game_over_bg);
|
text_draw("GAME OVER");
|
||||||
for (unsigned i = 0; i < NELEMS(game_over_verts); ++i) {
|
|
||||||
renderer_draw(
|
|
||||||
game_over_verts[i], game_over_lens[i], game_over_transform,
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
117
text.c
Normal file
117
text.c
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
#include "text.h"
|
||||||
|
|
||||||
|
#include "renderer.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#define NELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||||
|
|
||||||
|
#define MAX_LINES 2
|
||||||
|
|
||||||
|
#define TEXT_HEIGHT 8
|
||||||
|
#define TEXT_SCALE 0.025
|
||||||
|
#define LETTER_WIDTH 3
|
||||||
|
#define SPACE_WIDTH 1
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned line_count;
|
||||||
|
unsigned line_lens[MAX_LINES];
|
||||||
|
vec2_t lines[MAX_LINES][MAX_VERTS];
|
||||||
|
} glyph_t;
|
||||||
|
|
||||||
|
static const mat3_t text_transform = {
|
||||||
|
{ TEXT_SCALE, 0, 0 },
|
||||||
|
{ 0, TEXT_SCALE, 0 },
|
||||||
|
{ 0, 0, 1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const glyph_t font[] = {
|
||||||
|
['A'] = {
|
||||||
|
.line_count = 2,
|
||||||
|
.line_lens = { 3, 2 },
|
||||||
|
.lines = {
|
||||||
|
{ { -1, -4 }, { 0, 4 }, { 1, -4 } },
|
||||||
|
{ { -0.75, -2 }, { 0.75, -2 } },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
['E'] = {
|
||||||
|
.line_count = 2,
|
||||||
|
.line_lens = { 4, 2 },
|
||||||
|
.lines = {
|
||||||
|
{ { 1, 4 }, { -1, 4 }, { -1, -4 }, { 1, -4 } },
|
||||||
|
{ { -1, -2 }, { 0, -2 } },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
['G'] = {
|
||||||
|
.line_count = 1,
|
||||||
|
.line_lens = { 5 },
|
||||||
|
.lines = {
|
||||||
|
{ { 1, 4 }, { -1, 4 }, { -1, -4 }, { 1, -4 }, { 1, -2 } },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
['M'] = {
|
||||||
|
.line_count = 1,
|
||||||
|
.line_lens = { 5 },
|
||||||
|
.lines = {
|
||||||
|
{ { -1, -4 }, { -1, 4 }, { 0, -4 }, { 1, 4 }, { 1, -4 } },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
['O'] = {
|
||||||
|
.line_count = 1,
|
||||||
|
.line_lens = { 5 },
|
||||||
|
.lines = {
|
||||||
|
{ { -1, 4 }, { -1, -4 }, { 1, -4 }, { 1, 4 }, { -1, 4 } },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
['R'] = {
|
||||||
|
.line_count = 1,
|
||||||
|
.line_lens = { 6 },
|
||||||
|
.lines = {
|
||||||
|
{
|
||||||
|
{ -1, -4 }, { -1, 4 }, { 1, 4 },
|
||||||
|
{ 1, -2 }, { -1, -2 }, { 1, -4 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
['V'] = {
|
||||||
|
.line_count = 1,
|
||||||
|
.line_lens = { 3 },
|
||||||
|
.lines = {
|
||||||
|
{ { -1, 4 }, { 0, -4 }, { 1, 4 } },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
void text_draw(const char *s)
|
||||||
|
{
|
||||||
|
int width = 0;
|
||||||
|
for (const char *p = s; *p != '\0'; ++p)
|
||||||
|
width += *p == ' ' ? SPACE_WIDTH : LETTER_WIDTH;
|
||||||
|
--width;
|
||||||
|
|
||||||
|
const vec2_t bg_size = {
|
||||||
|
.x = TEXT_SCALE * (width + 2),
|
||||||
|
.y = TEXT_SCALE * (TEXT_HEIGHT + 2),
|
||||||
|
};
|
||||||
|
renderer_clear_rect((vec2_t) { 0, 0 }, bg_size);
|
||||||
|
|
||||||
|
int x = -width / 2 + 1;
|
||||||
|
for (const char *p = s; *p != '\0'; ++p) {
|
||||||
|
if (*p == ' ') {
|
||||||
|
x += SPACE_WIDTH;
|
||||||
|
} else {
|
||||||
|
const unsigned c = (unsigned)*p;
|
||||||
|
assert(c < NELEMS(font) && font[c].line_count != 0);
|
||||||
|
const glyph_t *g = font + c;
|
||||||
|
|
||||||
|
const vec2_t t = { .x = x };
|
||||||
|
const mat3_t m
|
||||||
|
= mat3_mul_mat3(text_transform, mat3_translation(t));
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < g->line_count; ++i)
|
||||||
|
renderer_draw(g->lines[i], g->line_lens[i], m, false);
|
||||||
|
|
||||||
|
x += LETTER_WIDTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user