#include #include #include #include #include #include #include namespace tgu { inline struct termios orig_termios; inline std::string newline = "\n\r"; enum class GameKey { INVALID, LEFTARROW, DOWNARROW, UPARROW, RIGHTARROW, ESCAPE, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, SPACE, }; inline std::map KeyMap = {{"a", GameKey::A}, {"b", GameKey::B}, {"c", GameKey::C}, {"d", GameKey::D}, {"e", GameKey::E}, {"f", GameKey::F}, {"g", GameKey::G}, {"h", GameKey::H}, {"i", GameKey::I}, {"j", GameKey::J}, {"k", GameKey::K}, {"l", GameKey::L}, {"m", GameKey::M}, {"n", GameKey::N}, {"o", GameKey::O}, {"p", GameKey::P}, {"q", GameKey::Q}, {"r", GameKey::R}, {"s", GameKey::S}, {"t", GameKey::T}, {"u", GameKey::U}, {"v", GameKey::V}, {"w", GameKey::W}, {"x", GameKey::X}, {"y", GameKey::Y}, {"z", GameKey::Z}, {"A", GameKey::A}, {"B", GameKey::B}, {"C", GameKey::C}, {"D", GameKey::D}, {"E", GameKey::E}, {"F", GameKey::F}, {"G", GameKey::G}, {"H", GameKey::H}, {"I", GameKey::I}, {"J", GameKey::J}, {"K", GameKey::K}, {"L", GameKey::L}, {"M", GameKey::M}, {"N", GameKey::N}, {"O", GameKey::O}, {"P", GameKey::P}, {"Q", GameKey::Q}, {"R", GameKey::R}, {"S", GameKey::S}, {"T", GameKey::T}, {"U", GameKey::U}, {"V", GameKey::V}, {"W", GameKey::W}, {"X", GameKey::X}, {"Y", GameKey::Y}, {"Z", GameKey::Z}, {"\x1b", GameKey::ESCAPE}, {"\x1b[D", GameKey::LEFTARROW}, {"\x1b[B", GameKey::DOWNARROW}, {"\x1b[A", GameKey::UPARROW}, {"\x1b[C", GameKey::RIGHTARROW}, {" ", GameKey::SPACE}}; inline void DisableRawMode() { tcsetattr(0, TCSAFLUSH, &orig_termios); } inline void EnableRawMode() { tcgetattr(0, &orig_termios); atexit(DisableRawMode); struct termios raw = orig_termios; raw.c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON); raw.c_oflag &= ~(OPOST); raw.c_cflag |= (CS8); raw.c_lflag &= ~(ECHO | ICANON | IEXTEN); raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; tcsetattr(0, TCSAFLUSH, &raw); } inline bool InputAvailable(int timeout_ms) { pollfd pfd{}; pfd.fd = STDIN_FILENO; pfd.events = POLLIN; return poll(&pfd, 1, timeout_ms) > 0; } inline GameKey GetKeyPress() { std::string keypress_string; char c; read(STDIN_FILENO, &c, 1); keypress_string += c; if (c == 27) while (InputAvailable(10)) { read(STDIN_FILENO, &c, 1); keypress_string += c; } if (KeyMap.count(keypress_string)) return KeyMap[keypress_string]; return KeyMap[keypress_string]; } // Text printers: inline void TextGreen() { std::cout << "\033[32m"; } inline void TextRed() { std::cout << "\033[31m"; } inline void TextBlue() { std::cout << "\033[34m"; } inline void TextRGB(int r, int g, int b) { std::cout << std::format("\033[38;2;{};{};{}m", r, g, b); }; // Background printers: inline void BGGreen() { std::cout << "\033[42m"; } inline void BGRed() { std::cout << "\033[41m"; } inline void BGBlue() { std::cout << "\033[44m"; } inline void BGRGB(int r, int g, int b) { std::cout << std::format("\033[48;2;{};{};{}m", r, g, b); } inline void TerminalColorReset() { std::cout << "\033[0m"; } // Game buffer printers: inline void EnterGameBuffer() { std::cout << "\033[?1049h"; } inline void LeaveGameBuffer() { std::cout << "\033[?1049l"; } inline void MoveCursor(int row, int col) { std::cout << "\033[" << row << ";" << col << "H" << std::flush; } }; // namespace tgu