// 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, ...);