Nooncraft/src/render.h

84 lines
3.2 KiB
C

// nooncraft.render: Grid-like text rendering
//
// Owing to the CPC constraint, the entire rendering system for this game is
// just text with a single font. We make two adjustments on the grid model:
//
// 1. We group rows and columns by pairs, so that the row/column spacing
// alternates between 1 and 3. This allows blocks to be represented by
// "clusters" of 4 characters.
// 2. To keep text natural, we provide a text function which forces column
// spacing to 2, offsetting every other character by 1 pixel. Rows remain
// irregularly spaced.
//---
#pragma once
using Glyph = char;
/* Non-ASCII glyphs */
enum {
GLYPH_FOUR_DOT = 1, /* U+2058 FOUR DOT PUNCTUATION */
GLYPH_MIDDLE_DOT = 2, /* U+00B7 MIDDLE DOT */
GLYPH_PARALLEL_TO = 3, /* U+2225 PARALLEL TO */
GLYPH_CURRENCY_SIGN = 4, /* U+00A4 CURRENCY SIGN */
GLYPH_NORTH_EAST_ARROW = 5, /* U+2197 NORTH EAST ARROW */
GLYPH_RIGHT_GUILLEMET = 6, /* U+00BB RIGHT GUILLEMET */
GLYPH_DOWN_ARROW = 7, /* U+2193 DOWNARDS ARROW */
GLYPH_I_CIRCUMFLEX = 8, /* U+00EE SMALL LATIN I WITH CIRCUMFLEX */
GLYPH_INTEGRAL = 9, /* U+222B INTEGRAL */
GLYPH_SMALL_SQUARE = 10, /* U+25AB WHITE SMALL SQUARE */
GLYPH_STAR = 11, /* U+2605 BLACK STAR */
GLYPH_CIRCLE = 12, /* U+25CF BLACK CIRCLE */
GLYPH_UP_ARROW_BAR = 13, /* U+21A5 UPWARDS ARROW FROM BAR */
GLYPH_CAPITAL_LAMBDA = 14, /* U+039B GREEK CAPITAL LETTER LAMBDA */
GLYPH_DEGREE_UNDERLINE = 15, /* U+00B0 U+0331 */
GLYPH_OPLUS = 16, /* U+2295 CIRCLED PLUS */
};
/* A cluster of 4 glyphs. Can be conversion-constructed from a multi-byte
character literal like 'AXE '. */
struct GlyphCluster
{
GlyphCluster(): glyphs {0,0,0,0} {}
GlyphCluster(Glyph g1, Glyph g2, Glyph g3, Glyph g4):
glyphs {g1, g2, g3, g4} {}
GlyphCluster(int mbliteral) {
this->glyphs[0] = mbliteral >> 24;
this->glyphs[1] = (mbliteral >> 16) & 0xff;
this->glyphs[2] = (mbliteral >> 8) & 0xff;
this->glyphs[3] = mbliteral & 0xff;
}
GlyphCluster applyOver(GlyphCluster const &other) {
return GlyphCluster(
this->glyphs[0] ? this->glyphs[0] : other.glyphs[0],
this->glyphs[1] ? this->glyphs[1] : other.glyphs[1],
this->glyphs[2] ? this->glyphs[2] : other.glyphs[2],
this->glyphs[3] ? this->glyphs[3] : other.glyphs[3]);
}
Glyph glyphs[4];
};
/* Enable or disable night mode (black-on-white). */
void renderSetNight(bool night);
/* Clear the screen. */
void renderClear(void);
/* Update the screen. */
void renderUpdate(void);
/* Render a single character with text alignment (2-pixel column spacing).
The position (x,y) is counted in characters units with (0,0) top-left. */
void renderGlyph(int x, int y, Glyph g);
/* Render a 2x2 cluster of 4 characters. The position (x,y) should be even on
both axes. */
void renderCluster(int x, int y, GlyphCluster c);
/* Render a string with text alignment. */
void renderText(int x, int y, char const *text);
/* Same with printf() formatting. */
void renderFormat(int x, int y, char const *fmt, ...);