Make TTY and Raylib identical
This commit is contained in:
		| @@ -3,6 +3,6 @@ | ||||
| # This software is released under the MIT License. | ||||
| # https://opensource.org/licenses/MIT | ||||
|  | ||||
| add_subdirectory(raylib) | ||||
| # add_subdirectory(raylib) | ||||
| add_subdirectory(term) | ||||
| #add_subdirectory(term) | ||||
| add_subdirectory(tty) | ||||
| @@ -6,19 +6,20 @@ | ||||
|  */ | ||||
|  | ||||
| #include "input.h" | ||||
| #include "platformraylib.h" | ||||
|    | ||||
| bool_t inputDown(const uint8_t action) { | ||||
|   return false; | ||||
|   return (PLATFORM_RAYLIB.inputCurrent & action) != 0; | ||||
| } | ||||
|  | ||||
| bool_t inputUp(const uint8_t action) { | ||||
|   return true; | ||||
|   return (PLATFORM_RAYLIB.inputCurrent & action) == 0; | ||||
| } | ||||
|  | ||||
| bool_t inputWasDown(const uint8_t action) { | ||||
|   return false; | ||||
|   return (PLATFORM_RAYLIB.inputPrevious & action) != 0; | ||||
| } | ||||
|  | ||||
| bool_t inputWasUp(const uint8_t action) { | ||||
|   return true; | ||||
|   return (PLATFORM_RAYLIB.inputPrevious & action) == 0; | ||||
| } | ||||
| @@ -6,18 +6,61 @@ | ||||
|  */ | ||||
|  | ||||
| #include "platform/platform.h" | ||||
| #include "platform/raylib/platformraylib.h" | ||||
| #include <raylib.h> | ||||
| #include "font.h" | ||||
| #include "platform/term/term.h" | ||||
| #include "input.h" | ||||
| #include "game.h" | ||||
| #include "gametime.h" | ||||
| #include <time.h> | ||||
|  | ||||
| typedef struct rlkeyboardmap_t { | ||||
|   uint8_t action; | ||||
|   int32_t raylibKey; | ||||
| } rlkeyboardmap_t; | ||||
|  | ||||
| static const rlkeyboardmap_t RL_KEYBOARD_MAP[] = { | ||||
|   { INPUT_ACTION_UP, KEY_W }, | ||||
|   { INPUT_ACTION_UP, KEY_UP }, | ||||
|   { INPUT_ACTION_DOWN, KEY_S }, | ||||
|   { INPUT_ACTION_DOWN, KEY_DOWN }, | ||||
|   { INPUT_ACTION_LEFT, KEY_A }, | ||||
|   { INPUT_ACTION_LEFT, KEY_LEFT }, | ||||
|   { INPUT_ACTION_RIGHT, KEY_D }, | ||||
|   { INPUT_ACTION_RIGHT, KEY_RIGHT }, | ||||
|   { INPUT_ACTION_A, KEY_E }, | ||||
|   { INPUT_ACTION_B, KEY_Q }, | ||||
|   { INPUT_ACTION_START, KEY_ENTER }, | ||||
|   { INPUT_ACTION_START, KEY_SPACE }, | ||||
|   { INPUT_ACTION_SELECT, KEY_BACKSPACE }, | ||||
|   { 0x00, 0x00 } | ||||
| }; | ||||
|  | ||||
| platformraylib_t PLATFORM_RAYLIB; | ||||
|  | ||||
| uint8_t platformInit(void) { | ||||
|   memset(&PLATFORM_RAYLIB, 0, sizeof(platformraylib_t)); | ||||
|  | ||||
|   // Init raylib. | ||||
|   InitWindow(800, 600, "Micro JRPG"); | ||||
|   SetTargetFPS(60); | ||||
|  | ||||
|   // Load font | ||||
|   if(fontInit() != 0) return PLATFORM_ERROR; | ||||
|  | ||||
|   // Resize window | ||||
|   SetWindowSize(40 * FONT.charWidth, 30 * FONT.charHeight); | ||||
|  | ||||
|   // Set in-game time to real world time. | ||||
|   time_t now = time(NULL); | ||||
|   struct tm *t = localtime(&now); | ||||
|  | ||||
|   GAME.time.days = t->tm_wday; | ||||
|   GAME.time.hours = t->tm_hour; | ||||
|   GAME.time.minutes = t->tm_min; | ||||
|   GAME.time.seconds = t->tm_sec; | ||||
|  | ||||
|   return PLATFORM_OK; | ||||
| } | ||||
|  | ||||
| @@ -25,7 +68,18 @@ uint8_t platformUpdate() { | ||||
|   if(WindowShouldClose()) { | ||||
|     return PLATFORM_EXIT; | ||||
|   } | ||||
|    | ||||
|  | ||||
|   // Update input state. | ||||
|   PLATFORM_RAYLIB.inputPrevious = PLATFORM_RAYLIB.inputCurrent; | ||||
|   PLATFORM_RAYLIB.inputCurrent = 0; | ||||
|   rlkeyboardmap_t *map = RL_KEYBOARD_MAP; | ||||
|   do { | ||||
|     if(IsKeyDown(map->raylibKey)) { | ||||
|       PLATFORM_RAYLIB.inputCurrent |= map->action; | ||||
|     } | ||||
|     map++; | ||||
|   } while(map->action != 0x00); | ||||
|  | ||||
|   return PLATFORM_OK; | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										16
									
								
								src/platform/raylib/platformraylib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/platform/raylib/platformraylib.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| /** | ||||
|  * Copyright (c) 2025 Dominic Masters | ||||
|  *  | ||||
|  * This software is released under the MIT License. | ||||
|  * https://opensource.org/licenses/MIT | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
| #include "microrpg.h" | ||||
|  | ||||
| typedef struct platformraylib_s { | ||||
|   uint8_t inputCurrent; | ||||
|   uint8_t inputPrevious; | ||||
| } platformraylib_t; | ||||
|  | ||||
| extern platformraylib_t PLATFORM_RAYLIB; | ||||
| @@ -6,6 +6,7 @@ | ||||
| # Sources | ||||
| target_sources(microrpg PRIVATE | ||||
|   term.c | ||||
|   termoverworld.c | ||||
| ) | ||||
|  | ||||
| # Compiler flags | ||||
|   | ||||
| @@ -6,49 +6,50 @@ | ||||
|  */ | ||||
|  | ||||
| #include "term.h" | ||||
| #include "game.h" | ||||
|  | ||||
| void termDrawOverworld() { | ||||
|   // Draw map. | ||||
|  | ||||
|   termDrawEntity(&GAME.player); | ||||
|  | ||||
|   entity_t *start = GAME.overworld.map.entities; | ||||
|   entity_t *end = start + MAP_ENTITY_COUNT; | ||||
|   while(start < end) { | ||||
|     if(start->type != ENTITY_TYPE_NULL) termDrawEntity(start); | ||||
|     start++; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void termDrawEntity(const entity_t *ent) { | ||||
|   // Placeholder: Draw entity at its position | ||||
|   char c; | ||||
|   switch(ent->direction) { | ||||
|     case DIRECTION_NORTH: | ||||
|       c = '^'; | ||||
|       break; | ||||
|     case DIRECTION_EAST: | ||||
|       c = '>'; | ||||
|       break; | ||||
|     case DIRECTION_SOUTH: | ||||
|       c = 'v'; | ||||
|       break; | ||||
|     case DIRECTION_WEST: | ||||
|       c = '<'; | ||||
|       break; | ||||
|     default: | ||||
|       c = '@'; | ||||
|       break; | ||||
|   } | ||||
|  | ||||
|   termPushChar | ||||
| } | ||||
| #include "termoverworld.h" | ||||
|  | ||||
| void termDraw() { | ||||
|   termClear(); | ||||
|  | ||||
|   int32_t width, height, x, y; | ||||
|   width = termGetColumnCount(); | ||||
|   height = termGetRowCount(); | ||||
|  | ||||
|   // Create buffers | ||||
|   char_t *chars = malloc(width * height * sizeof(char_t)); | ||||
|   if(chars == NULL) { | ||||
|     printf("termDrawOverworld: Out of memory!\n"); | ||||
|     abort(); | ||||
|     return; | ||||
|   } | ||||
|   memset(chars, ' ', width * height * sizeof(char_t)); | ||||
|  | ||||
|   termcolor_t *colors = malloc(width * height * sizeof(termcolor_t)); | ||||
|   if(colors == NULL) { | ||||
|     printf("termDrawOverworld: Out of memory!\n"); | ||||
|     free(chars); | ||||
|     abort(); | ||||
|     return; | ||||
|   } | ||||
|   memset(colors, TERM_COLOR_WHITE, width * height * sizeof(termcolor_t)); | ||||
|  | ||||
|   // Draw | ||||
|   termDrawOverworld(chars, colors, width, height); | ||||
|  | ||||
|   // Print | ||||
|   size_t i; | ||||
|   termcolor_t curColor = TERM_COLOR_WHITE; | ||||
|   for(size_t i = 0; i < width * height; i++) { | ||||
|     if(colors[i] != curColor) { | ||||
|       termPushColor(colors[i]); | ||||
|       curColor = colors[i]; | ||||
|     } | ||||
|     termPushChar(chars[i]); | ||||
|   } | ||||
|    | ||||
|   // Clean up | ||||
|   free(chars); | ||||
|   free(colors); | ||||
|  | ||||
|   termFlush(); | ||||
| } | ||||
							
								
								
									
										46
									
								
								src/platform/term/termoverworld.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/platform/term/termoverworld.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| /** | ||||
|  * Copyright (c) 2025 Dominic Masters | ||||
|  *  | ||||
|  * This software is released under the MIT License. | ||||
|  * https://opensource.org/licenses/MIT | ||||
|  */ | ||||
|  | ||||
| #include "termoverworld.h" | ||||
|  | ||||
| void termDrawOverworld( | ||||
|   char_t *chars, | ||||
|   termcolor_t *colors, | ||||
|   const int32_t w, | ||||
|   const int32_t h | ||||
| ) { | ||||
|   // Draw the ground | ||||
|   for(int32_t x = 0; x < w; x++) { | ||||
|     for(int32_t y = 0; y < h; y++) { | ||||
|       size_t index = y * w + x; | ||||
|       chars[index] = '.'; | ||||
|       colors[index] = TERM_COLOR_GREEN; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // Draw entities | ||||
|   termDrawEntity(&GAME.player, chars, colors, w, h); | ||||
| } | ||||
|  | ||||
| void termDrawEntity( | ||||
|   const entity_t *ent, | ||||
|   char_t *chars, | ||||
|   termcolor_t *colors, | ||||
|   const int32_t w, | ||||
|   const int32_t h | ||||
| ) { | ||||
|   if(ent->type == ENTITY_TYPE_NULL) return; | ||||
|  | ||||
|   if(ent->position.x >= w || ent->position.y >= h) return; | ||||
|  | ||||
|   int32_t index = ent->position.y * w + ent->position.x; | ||||
|  | ||||
|   if(ent->type == ENTITY_TYPE_PLAYER) { | ||||
|     chars[index] = '@'; | ||||
|     colors[index] = TERM_COLOR_YELLOW; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										42
									
								
								src/platform/term/termoverworld.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/platform/term/termoverworld.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| /** | ||||
|  * Copyright (c) 2025 Dominic Masters | ||||
|  *  | ||||
|  * This software is released under the MIT License. | ||||
|  * https://opensource.org/licenses/MIT | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
| #include "term.h" | ||||
| #include "game.h" | ||||
|  | ||||
| /** | ||||
|  * Draw the overworld SCENE to the terminal. | ||||
|  *  | ||||
|  * @param chars Buffer of characters to write to. | ||||
|  * @param colors Buffer of colors to write to. | ||||
|  * @param w Width of the terminal in characters. | ||||
|  * @param h Height of the terminal in characters. | ||||
|  */ | ||||
| void termDrawOverworld( | ||||
|   char_t *chars, | ||||
|   termcolor_t *colors, | ||||
|   const int32_t w, | ||||
|   const int32_t h | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * Draw an entity to the terminal. | ||||
|  *  | ||||
|  * @param ent The entity to draw. | ||||
|  * @param chars Buffer of characters to write to. | ||||
|  * @param colors Buffer of colors to write to. | ||||
|  * @param w Width of the terminal in characters. | ||||
|  * @param h Height of the terminal in characters. | ||||
|  */ | ||||
| void termDrawEntity( | ||||
|   const entity_t *ent, | ||||
|   char_t *chars, | ||||
|   termcolor_t *colors, | ||||
|   const int32_t w, | ||||
|   const int32_t h | ||||
| ); | ||||
| @@ -18,12 +18,12 @@ target_link_libraries(microrpg PRIVATE | ||||
|  | ||||
| # Sources | ||||
| target_sources(microrpg PRIVATE | ||||
|   term.c | ||||
|   inputterm.c | ||||
|   platform.c | ||||
|   termtty.c | ||||
| ) | ||||
|  | ||||
| # Compiler flags | ||||
| target_compile_definitions(microrpg PRIVATE | ||||
|   RPG_TERM=1 | ||||
|   RPG_TTY=1 | ||||
| ) | ||||
| @@ -5,20 +5,20 @@ | ||||
|  * https://opensource.org/licenses/MIT | ||||
|  */ | ||||
|  | ||||
| #include "term.h" | ||||
| #include "platformtty.h" | ||||
|    | ||||
| bool_t inputDown(const uint8_t action) { | ||||
|   return (TERM.inputCurrent & action) != 0; | ||||
|   return (PLATFORM_TTY.inputCurrent & action) != 0; | ||||
| } | ||||
|  | ||||
| bool_t inputUp(const uint8_t action) { | ||||
|   return (TERM.inputCurrent & action) == 0; | ||||
|   return (PLATFORM_TTY.inputCurrent & action) == 0; | ||||
| } | ||||
|  | ||||
| bool_t inputWasDown(const uint8_t action) { | ||||
|   return (TERM.inputPrevious & action) != 0; | ||||
|   return (PLATFORM_TTY.inputPrevious & action) != 0; | ||||
| } | ||||
|  | ||||
| bool_t inputWasUp(const uint8_t action) { | ||||
|   return (TERM.inputPrevious & action) == 0; | ||||
|   return (PLATFORM_TTY.inputPrevious & action) == 0; | ||||
| } | ||||
| @@ -7,19 +7,109 @@ | ||||
|  | ||||
| #include "platform/platform.h" | ||||
| #include "platform/term/term.h" | ||||
| #include "platform/tty/platformtty.h" | ||||
| #include "input.h" | ||||
| #include <time.h> | ||||
|  | ||||
| void platformInit() { | ||||
|   termInit(); | ||||
| typedef struct ttyinputmap_s { | ||||
|   int key; | ||||
|   uint8_t action; | ||||
| } ttyinputmap_t; | ||||
|  | ||||
| static const ttyinputmap_t TERM_INPUT_MAP[] = { | ||||
|   { KEY_UP, INPUT_ACTION_UP }, | ||||
|   { 'w', INPUT_ACTION_UP }, | ||||
|   { KEY_DOWN, INPUT_ACTION_DOWN }, | ||||
|   { 's', INPUT_ACTION_DOWN }, | ||||
|   { KEY_LEFT, INPUT_ACTION_LEFT }, | ||||
|   { 'a', INPUT_ACTION_LEFT }, | ||||
|   { KEY_RIGHT, INPUT_ACTION_RIGHT }, | ||||
|   { 'd', INPUT_ACTION_RIGHT }, | ||||
|   { 'j', INPUT_ACTION_A }, | ||||
|   { 'e', INPUT_ACTION_A }, | ||||
|   { 'k', INPUT_ACTION_B }, | ||||
|   { 'q', INPUT_ACTION_B }, | ||||
|   { KEY_ENTER, INPUT_ACTION_START }, | ||||
|   { ' ', INPUT_ACTION_SELECT }, | ||||
|   { -1, 0 } | ||||
| }; | ||||
|  | ||||
| platformtty_t PLATFORM_TTY; | ||||
|  | ||||
| uint8_t platformInit() { | ||||
|   memset(&PLATFORM_TTY, 0, sizeof(platformtty_t)); | ||||
|  | ||||
|   initscr(); | ||||
|   cbreak(); | ||||
|   noecho(); | ||||
|   keypad(stdscr, TRUE); | ||||
|   nodelay(stdscr, TRUE); | ||||
|   curs_set(0); | ||||
|   start_color(); | ||||
|   use_default_colors(); | ||||
|  | ||||
|   // Color Pairs | ||||
|   init_pair(TERM_COLOR_BLACK, COLOR_BLACK, -1); | ||||
|   init_pair(TERM_COLOR_RED, COLOR_RED, -1); | ||||
|   init_pair(TERM_COLOR_GREEN, COLOR_GREEN, -1); | ||||
|   init_pair(TERM_COLOR_YELLOW, COLOR_YELLOW, -1); | ||||
|   init_pair(TERM_COLOR_BLUE, COLOR_BLUE, -1); | ||||
|   init_pair(TERM_COLOR_MAGENTA, COLOR_MAGENTA, -1); | ||||
|   init_pair(TERM_COLOR_CYAN, COLOR_CYAN, -1); | ||||
|   init_pair(TERM_COLOR_WHITE, COLOR_WHITE, -1); | ||||
|    | ||||
|  | ||||
|   // Set in-game time to real world time. | ||||
|   time_t now = time(NULL); | ||||
|   struct tm *t = localtime(&now); | ||||
|  | ||||
|   GAME.time.days = t->tm_wday; | ||||
|   GAME.time.hours = t->tm_hour; | ||||
|   GAME.time.minutes = t->tm_min; | ||||
|   GAME.time.seconds = t->tm_sec; | ||||
|  | ||||
|   return PLATFORM_OK; | ||||
| } | ||||
|  | ||||
| void platformUpdate() { | ||||
|   termUpdate(); | ||||
| uint8_t platformUpdate() { | ||||
|   PLATFORM_TTY.inputPrevious = PLATFORM_TTY.inputCurrent; | ||||
|   PLATFORM_TTY.inputCurrent = 0; | ||||
|  | ||||
|   int ch = getch(); | ||||
|   if(ch == ERR) { | ||||
|     PLATFORM_TTY.lastch = ERR; | ||||
|     return PLATFORM_OK; | ||||
|   } | ||||
|  | ||||
|   if(ch == PLATFORM_TTY.lastch) { | ||||
|     return PLATFORM_OK; | ||||
|   } | ||||
|   PLATFORM_TTY.lastch = ch; | ||||
|  | ||||
|   const ttyinputmap_t *map = TERM_INPUT_MAP; | ||||
|   while(map->key != -1) { | ||||
|     if(map->key == ch) { | ||||
|       PLATFORM_TTY.inputCurrent |= map->action; | ||||
|       break; | ||||
|     } | ||||
|     map++; | ||||
|   } | ||||
|  | ||||
|   return PLATFORM_OK; | ||||
| } | ||||
|  | ||||
| void platformDraw() { | ||||
|   clear(); | ||||
|    | ||||
|   termDraw(); | ||||
|  | ||||
|   attroff(COLOR_PAIR(1)); | ||||
|   refresh(); | ||||
|    | ||||
|   // 16ms delay (60FPS) | ||||
|   napms(16); | ||||
| } | ||||
|  | ||||
| void platformDispose() { | ||||
|   termDispose(); | ||||
|   endwin(); | ||||
| } | ||||
							
								
								
									
										19
									
								
								src/platform/tty/platformtty.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										19
									
								
								src/platform/tty/platformtty.h
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| /** | ||||
|  * Copyright (c) 2025 Dominic Masters | ||||
|  *  | ||||
|  * This software is released under the MIT License. | ||||
|  * https://opensource.org/licenses/MIT | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
| #include "microrpg.h" | ||||
| #include "game.h" | ||||
| #include <ncurses.h> | ||||
|  | ||||
| typedef struct platformtty_s { | ||||
|   uint8_t inputCurrent; | ||||
|   uint8_t inputPrevious; | ||||
|   int lastch; | ||||
| } platformtty_t; | ||||
|  | ||||
| extern platformtty_t PLATFORM_TTY; | ||||
| @@ -1,146 +0,0 @@ | ||||
| /** | ||||
|  * Copyright (c) 2025 Dominic Masters | ||||
|  *  | ||||
|  * This software is released under the MIT License. | ||||
|  * https://opensource.org/licenses/MIT | ||||
|  */ | ||||
|  | ||||
| #include "term.h" | ||||
| #include "input.h" | ||||
| #include <time.h> | ||||
|  | ||||
| typedef struct terminputmap_s { | ||||
|   int key; | ||||
|   uint8_t action; | ||||
| } terminputmap_t; | ||||
|  | ||||
| static const terminputmap_t TERM_INPUT_MAP[] = { | ||||
|   { KEY_UP, INPUT_ACTION_UP }, | ||||
|   { 'w', INPUT_ACTION_UP }, | ||||
|   { KEY_DOWN, INPUT_ACTION_DOWN }, | ||||
|   { 's', INPUT_ACTION_DOWN }, | ||||
|   { KEY_LEFT, INPUT_ACTION_LEFT }, | ||||
|   { 'a', INPUT_ACTION_LEFT }, | ||||
|   { KEY_RIGHT, INPUT_ACTION_RIGHT }, | ||||
|   { 'd', INPUT_ACTION_RIGHT }, | ||||
|   { 'j', INPUT_ACTION_A }, | ||||
|   { 'e', INPUT_ACTION_A }, | ||||
|   { 'k', INPUT_ACTION_B }, | ||||
|   { 'q', INPUT_ACTION_B }, | ||||
|   { KEY_ENTER, INPUT_ACTION_START }, | ||||
|   { ' ', INPUT_ACTION_SELECT }, | ||||
|   { -1, 0 } | ||||
| }; | ||||
|  | ||||
| term_t TERM; | ||||
|  | ||||
| void termInit() { | ||||
|   memset(&TERM, 0, sizeof(TERM)); | ||||
|  | ||||
|   initscr(); | ||||
|   cbreak(); | ||||
|   noecho(); | ||||
|   keypad(stdscr, TRUE); | ||||
|   nodelay(stdscr, TRUE); | ||||
|   curs_set(0); | ||||
|   start_color(); | ||||
|   use_default_colors(); | ||||
|  | ||||
|   init_pair(1, COLOR_GREEN, -1); | ||||
|  | ||||
|   // Set in-game time to real world time. | ||||
|   time_t now = time(NULL); | ||||
|   struct tm *t = localtime(&now); | ||||
|  | ||||
|   GAME.time.days = t->tm_wday; | ||||
|   GAME.time.hours = t->tm_hour; | ||||
|   GAME.time.minutes = t->tm_min; | ||||
|   GAME.time.seconds = t->tm_sec; | ||||
| } | ||||
|  | ||||
| void termUpdate() { | ||||
|   TERM.inputPrevious = TERM.inputCurrent; | ||||
|   TERM.inputCurrent = 0; | ||||
|  | ||||
|   int ch = getch(); | ||||
|   if(ch == ERR) { | ||||
|     TERM.lastch = ERR; | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   if(ch == TERM.lastch) { | ||||
|     return; | ||||
|   } | ||||
|   TERM.lastch = ch; | ||||
|  | ||||
|   const terminputmap_t *map = TERM_INPUT_MAP; | ||||
|   while(map->key != -1) { | ||||
|     if(map->key == ch) { | ||||
|       TERM.inputCurrent |= map->action; | ||||
|       break; | ||||
|     } | ||||
|     map++; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void termDraw() { | ||||
|   clear(); | ||||
|  | ||||
|   switch(GAME.scene) { | ||||
|     case SCENE_OVERWORLD: | ||||
|       termDrawOverworld(); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       break; | ||||
|   } | ||||
|  | ||||
|   attroff(COLOR_PAIR(1)); | ||||
|   refresh(); | ||||
|    | ||||
|   // 16ms delay (60FPS) | ||||
|   napms(16); | ||||
| } | ||||
|  | ||||
| void termDrawOverworld() { | ||||
|   // Draw map. | ||||
|  | ||||
|   // Draw entities. | ||||
|   attron(COLOR_PAIR(1)); | ||||
|   termDrawEntity(&GAME.player); | ||||
|  | ||||
|   entity_t *start = GAME.overworld.map.entities; | ||||
|   entity_t *end = start + MAP_ENTITY_COUNT; | ||||
|   while(start < end) { | ||||
|     if(start->type != ENTITY_TYPE_NULL) termDrawEntity(start); | ||||
|     start++; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void termDrawEntity(const entity_t *ent) { | ||||
|   // Placeholder: Draw entity at its position | ||||
|   char c; | ||||
|   switch(ent->direction) { | ||||
|     case DIRECTION_NORTH: | ||||
|       c = '^'; | ||||
|       break; | ||||
|     case DIRECTION_EAST: | ||||
|       c = '>'; | ||||
|       break; | ||||
|     case DIRECTION_SOUTH: | ||||
|       c = 'v'; | ||||
|       break; | ||||
|     case DIRECTION_WEST: | ||||
|       c = '<'; | ||||
|       break; | ||||
|     default: | ||||
|       c = '@'; | ||||
|       break; | ||||
|   } | ||||
|  | ||||
|   mvaddch(ent->position.y, ent->position.x, c); | ||||
| } | ||||
|  | ||||
| void termDispose() { | ||||
|   endwin(); | ||||
| } | ||||
| @@ -1,51 +0,0 @@ | ||||
| /** | ||||
|  * Copyright (c) 2025 Dominic Masters | ||||
|  *  | ||||
|  * This software is released under the MIT License. | ||||
|  * https://opensource.org/licenses/MIT | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
| #include "microrpg.h" | ||||
| #include "game.h" | ||||
| #include <ncurses.h> | ||||
|  | ||||
| typedef struct term_s { | ||||
|   uint8_t inputCurrent; | ||||
|   uint8_t inputPrevious; | ||||
|   int lastch; | ||||
| } term_t; | ||||
|  | ||||
| extern term_t TERM; | ||||
|  | ||||
| /**  | ||||
|  * Initialize the terminal subsystem. | ||||
|  */ | ||||
| void termInit(); | ||||
|  | ||||
| /**  | ||||
|  * Update the terminal prior to game update. | ||||
|  */ | ||||
| void termUpdate(); | ||||
|  | ||||
| /**  | ||||
|  * Draw the terminal game. | ||||
|  */ | ||||
| void termDraw(); | ||||
|  | ||||
| /**  | ||||
|  * Draw the overworld scene. | ||||
|  */ | ||||
| void termDrawOverworld(); | ||||
|  | ||||
| /**  | ||||
|  * Draw an entity to the terminal. | ||||
|  *  | ||||
|  * @param ent The entity to draw. | ||||
|  */ | ||||
| void termDrawEntity(const entity_t *ent); | ||||
|  | ||||
| /**  | ||||
|  * Dispose of the terminal subsystem. | ||||
|  */ | ||||
| void termDispose(); | ||||
							
								
								
									
										37
									
								
								src/platform/tty/termtty.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/platform/tty/termtty.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| /** | ||||
|  * Copyright (c) 2025 Dominic Masters | ||||
|  *  | ||||
|  * This software is released under the MIT License. | ||||
|  * https://opensource.org/licenses/MIT | ||||
|  */ | ||||
|  | ||||
| #include "platform/term/term.h" | ||||
| #include <ncurses.h> | ||||
|  | ||||
| void termClear() { | ||||
|   clear(); | ||||
|   refresh(); | ||||
| } | ||||
|  | ||||
| void termFlush() { | ||||
|   // Nothing to do | ||||
| } | ||||
|  | ||||
| uint8_t termGetColumnCount() { | ||||
|   int cols = getmaxx(stdscr); | ||||
|   return (uint8_t)cols; | ||||
| } | ||||
|  | ||||
| uint8_t termGetRowCount() { | ||||
|   int rows = getmaxy(stdscr); | ||||
|   return (uint8_t)rows; | ||||
| } | ||||
|  | ||||
| void termPushColor(termcolor_t color) { | ||||
|   // Map the termcolor_t to the ncurses color pair | ||||
|   attron(COLOR_PAIR((int)color)); | ||||
| } | ||||
|  | ||||
| void termPushChar(char_t c) { | ||||
|   addch(c); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user