From 6d31c3c492d53b95444aa60daa4ca6f1741f266c Mon Sep 17 00:00:00 2001 From: Miloslav Ciz Date: Tue, 17 Dec 2024 00:56:51 +0100 Subject: [PATCH] Start text --- assets.h | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++ constants.h | 2 ++ game.h | 2 ++ renderer.h | 54 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 125 insertions(+) diff --git a/assets.h b/assets.h index 59c89f4..072cb03 100644 --- a/assets.h +++ b/assets.h @@ -67,6 +67,73 @@ struct const uint8_t *image; } LCR_currentImage; +/* + Font characters are kind of "segmented display" characters, encoded with 16 + bits (each for one segment) like this (numbered from LSB): + + __0__ __2__ + |\12 |\13 | + 1| \ 5| \ 9| + | \ | \ | + |__4\_|__6\_| + |\14 |\15 | + 3| \ 7| \ 11| + | \ | \ | + |__8\_|_10\_| +*/ + +uint16_t LCR_getFontChar(char c) +{ +#define _F(a,b,c,d,e,f,g,h,i,j) return (1 << a) | (1 << b) | (1 << c) | (1 <<\ + d) | (1 << e) | (1 << f) | (1 << g) | (1 << h) | (1 << i) | (1 << j); break; + + switch (c) + { + case 'O': case 'o': + case '0': _F( 0, 2, 1, 9, 3,11, 8,10,10,10) + case '1': _F( 0, 5, 7, 8,10,10,10,10,10,10) + case 'Z': case 'z': + case '2': _F( 0, 2, 9, 4, 6, 3, 8,10,10,10) + case '3': _F( 0, 2, 9, 6,11, 8,10,10,10,10) + case '4': _F( 1, 4, 6, 9,11,11,11,11,11,11) + case 'S': case 's': + case '5': _F( 0, 2, 1, 4, 6,11, 8,10,10,10) + case '6': _F( 0, 2, 1, 3, 8,10,11, 6, 4, 4) + case '7': _F( 0, 2, 9,11,11,11,11,11,11,11) + case '8': _F( 0, 2, 1, 9, 4, 6, 3,11, 8,10) + case '9': _F( 0, 2, 1, 9, 4, 6,11, 8,10,10) + case 'A': case 'a': _F( 0, 1,13, 4, 6, 3,11,11,11,11) + case 'B': case 'b': _F( 0, 1,13, 4, 6, 3,11, 8,10,10) + case 'C': case 'c': _F( 0, 2, 1, 3, 8,10,10,10,10,10) + case 'D': case 'd': _F( 0, 1, 3, 8,10,13,11,11,11,11) + case 'E': case 'e': _F( 0, 2, 1, 3, 4, 8,10,10,10,10) + case 'F': case 'f': _F( 0, 2, 1, 3, 4, 4, 4, 4, 4, 4) + case 'G': case 'g': _F( 0, 2, 1, 3, 8,10,11, 6, 6, 6) + case 'H': case 'h': _F( 1, 3, 4, 6, 9,11,11,11,11,11) + case 'I': case 'i': _F( 0, 2, 5, 7, 8,10,10,10,10,10) + case 'J': case 'j': _F( 9,11,10,14,14,14,14,14,14,14) + case 'K': case 'k': _F( 1, 3, 4,15, 5, 2, 2, 2, 2, 2) + case 'L': case 'l': _F( 1, 3, 8,10,10,10,10,10,10,10) + case 'M': case 'm': _F( 1, 3,12, 5, 2, 9,11,11,11,11) + case 'N': case 'n': _F( 1, 3,12,15, 9,11,11,11,11,11) + case 'P': case 'p': _F( 0, 2, 1, 9, 4, 6, 3, 3, 3, 3) + case 'Q': case 'q': _F( 0, 2, 1, 9, 3,11, 8,10,15,15) + case 'R': case 'r': _F( 0, 2, 1, 9, 4, 6, 3,15,15,15) + case 'T': case 't': _F( 0, 2, 5, 7, 7, 7, 7, 7, 7, 7) + case 'U': case 'u': _F( 1, 3, 8,10,11, 9, 9, 9, 9, 9) + case 'V': case 'v': _F( 1,14,10,11, 9, 9, 9, 9, 9, 9) + case 'W': case 'w': _F( 1,14,10,11, 7, 9, 9, 9, 9, 9) + case 'X': case 'x': _F(12,15, 3, 4, 6, 9, 9, 9, 9, 9) + case 'Y': case 'y': _F(12, 6, 9, 7, 8, 8, 8, 8, 8, 8) + case ':': _F( 4, 8, 8, 8, 8, 8, 8, 8, 8, 8) + case '.': _F( 8, 8, 8, 8, 8, 8, 8, 8, 8, 8) + case ',': _F( 7, 7, 7, 7, 7, 7, 7, 7, 7, 7) + default: return 0; break; + } + +#undef _F +} + #define LCR_IMAGE_WALL_CONCRETE 0 #define LCR_IMAGE_WALL_WOOD 1 #define LCR_IMAGE_GROUND_CONCRETE 2 diff --git a/constants.h b/constants.h index 5b4ad80..a2fd24a 100644 --- a/constants.h +++ b/constants.h @@ -31,4 +31,6 @@ /** Maximum number of triangles of a block shape. */ #define LCR_MAP_BLOCK_SHAPE_MAX_BYTES 80 +#define LCR_FONT_PIXEL_SIZE (1 + LCR_EFFECTIVE_RESOLUTION_X / 512) + #endif diff --git a/game.h b/game.h index fd65413..6d5ca53 100644 --- a/game.h +++ b/game.h @@ -365,6 +365,8 @@ LCR_GameUnit physicsInterpolationParam = LCR_GAME_UNIT - LCR_rendererDraw(); +LCR_rendererDrawText("abcdefghijklmnopqrstuvwxyz",10,20,0,2); + if (LCR_game.debugDraw) { LCR_GameUnit camTr[7]; diff --git a/renderer.h b/renderer.h index 45acc3e..586ba41 100644 --- a/renderer.h +++ b/renderer.h @@ -31,6 +31,8 @@ #define LCR_RENDERER_MODEL_COUNT 10 #define LCR_RENDERER_CAR_SCALE (LCR_RENDERER_UNIT / 4) +#define LCR_RENDERER_FONT_SEGMENT_SIZE 4 + /** For some reason the map model is a bit misaligned with physics world, this kinda hotfixes it -- later try to discover source of this bug. TODO */ #define _LCR_MAP_MODEL_SCALE 1034 @@ -112,6 +114,58 @@ void LCR_rendererSetCarTransform(LCR_GameUnit position[3], S3L_F) / LCR_GAME_UNIT,S3L_F); } +void _LCR_rendererDrawFontPixel(int x, int y, uint16_t color) +{ +#if LCR_FONT_PIXEL_SIZE == 1 + LCR_drawPixelXYSafe(x,y,color); +#else + if ((x >= 0) && (y >= 0) && + (x < LCR_EFFECTIVE_RESOLUTION_X - LCR_FONT_PIXEL_SIZE) && + (y < LCR_EFFECTIVE_RESOLUTION_Y - LCR_FONT_PIXEL_SIZE)) + for (int i = x; i < x + LCR_FONT_PIXEL_SIZE; ++i) + for (int j = y; j < y + LCR_FONT_PIXEL_SIZE; ++j) + LCR_drawPixelXYSafe(i,j,color); +#endif +} + +void LCR_rendererDrawText(const char *text, int x, int y, uint16_t color, + int size) +{ + size *= LCR_RENDERER_FONT_SEGMENT_SIZE; + + while (*text) + { + uint16_t c = LCR_getFontChar(*text); + + for (int b = 0; b < 3; ++b) // horizontal and vertical segments + for (int a = 0; a < 2; ++a) + { + if (c & 0x01) + for (int i = 0; i < size; ++i) + _LCR_rendererDrawFontPixel(x + a * size + i,y + b * size,color); + + if (c & 0x02) + for (int i = 0; i < size; ++i) + _LCR_rendererDrawFontPixel(x + b * size,y + a * size + i,color); + + c >>= 2; + } + + for (int b = 0; b < 2; ++b) // diagonal segments + for (int a = 0; a < 2; ++a) + { + if (c & 0x01) + for (int i = 0; i < size; ++i) + _LCR_rendererDrawFontPixel(x + a * size + i,y + b * size + i,color); + + c >>= 1; + } + + x += 2 * size + 3 * size / 4; + text++; + } +} + void _LCR_pixelFunc3D(S3L_PixelInfo *pixel) { // once we get a new triangle, we precompute things for it: