1

Backstory: I'm making a C++ game (2 dimensional grid game) only using the Terminal on my Mac. So far I have code written that will initialize a map and code that will allow my character (an '&') to move by having a 2D array as a grid: array[11][44], and store each obstacle in a space in the array while any space the character can enter is a ' ' (character can't traverse onto any space there is an obstacle). When the grid/map is printed, the char input you give will determine if your character moves, which is basically setting the location you're at in the array to ' ' and the new space to '&' and then clearing and printing the new map. All this code works.

Question: When I input a, s, d, or w my character will move, however, you must press 'Enter'. I'm looking for a way to input one of these inputs and it be immediately read rather than have to press 'Enter' each time I want to move. Just finished my freshman year of college so thats why my knowledge of C++ is pretty basic and I don't know how to go about tackling this myself. I've looked into solutions including conio.h and the getch_() function but I don't know how to use them.

Glory
  • 11
  • 1
  • You need to put the terminal in `raw` mode (non-canonical) mode. Input on terminals is generally *line-buffered* by default (requiring an `[Enter]` be pressed before input is provided to the OS). You can use `tcsetattr()` to change the terminal buffering and put the terminal in raw unbuffered mode. Then simply tapping `s` will simultaneously be seen by your program without the need to press `[Enter]`. Do not use `conio.h` that is an archaic DOS header for DOS/windows only. Just search `"[c] non-canonical raw mode"`in the search box at the top of the page. (without the quotes) – David C. Rankin May 20 '23 at 21:51
  • Here is a short example on text entry in raw mode showing how to put the terminal in raw mode and how to restore it. [short example](https://stackoverflow.com/a/53249714/3422102). It also provides minimal editing so you can change the input. (you won't need that part for the `s, d, ...` movement keys you want.) – David C. Rankin May 20 '23 at 22:01
  • Alright thanks. The examples I looked through didn't seem to work when I tested so I followed a guide here: https://viewsourcecode.org/snaptoken/kilo/02.enteringRawMode.html#:~:text=Unfortunately%2C%20there%20is%20no%20simple,reached%20the%20end%20of%20file. The examples they showed didn't work well at all so I ended up using only the stuff I needed. The function I made that works is as follows: (next comment). I set my input to the getch() function and my code didn't need to be changed at all. If conio.h worked this well I'm confused on why it wouldn't at least be updated to newer libraries. – Glory May 21 '23 at 03:53
  • `char getch() { struct termios oldTermios, newTermios; tcgetattr(STDIN_FILENO, &oldTermios); newTermios = oldTermios; newTermios.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &newTermios); char ch; read(STDIN_FILENO, &ch, 1); tcsetattr(STDIN_FILENO, TCSANOW, &oldTermios); return ch; }` – Glory May 21 '23 at 03:53
  • The issue with terminal buffering control is it is NON-portable between operating systems. So it has to be OS specific (e.g. Linux, windows, etc..) I presumed Mac (being a Linux variant) would use the `tcsetattr()` approach -- but I have no mac to test on. Your function looks fine. Don't forget, in non-canonical mode you have to test for `VEOF`, not `EOF` -- if you need that. Glad you have it working `:)` – David C. Rankin May 21 '23 at 05:16

0 Answers0