2

I'm trying to make a simple game for the unix terminal, written in c. I've been looking for a way to poll the keyboard, but haven't had any luck.

Currently I'm using ncurses getch() function. It works okay but if the user holds a key, the keyboard repeat will take a moment to start - also it will halt if any other key is pressed. This causes problems when playing (especially in two player mode where both games are controlled from a single input thread).

For example, if player 1 holds down 'a' and player 2 holds down 'b', I need to poll the keyboard and handle a stream of input like this:

    abababababababab

As another example, if player 1 holds down the 'a' key and also presses the 'b' key, I need the input to be handled like this:

    aaaaaaabaaaaaaaa

This way the simultaneous key presses don't interrupt each other. So I basically need to poll the keys on the keyboard on a set interval, and create my own implementation of a key press repeater.

Is there a way in c (with or without ncurses) to simply poll the keyboard on a time interval and read in all keys that are currently being pressed? From there I can just design the keyboard input thread to manage repeating actions manually. Basically something along the lines of kbhit, so I can check the status of a given key. But that will also let me poll the arrow keys.

  • possibly helpful: [Receiving Key Press and Key Release Events in Linux Terminal Applications](https://stackoverflow.com/questions/1409216/receiving-key-press-and-key-release-events-in-linux-terminal-applications) – Patrick Apr 02 '19 at 16:55
  • 1
    Possible duplicate of [Is there an alternative to getch(); which won't pause the program?](https://stackoverflow.com/questions/44052176/is-there-an-alternative-to-getch-which-wont-pause-the-program) – Thomas Dickey Apr 02 '19 at 20:34
  • 1
    you know that this heavily depends on the hardware used? there are keyboards that cannot handle these kinds of button presses and the keyboard controller will only send the first key that has been sent to the computer? – Nidhoegger Apr 03 '19 at 13:02
  • Right but there must be a way to poll a specific key - then for every key I need I can just poll one after the other. Something like: `while true, poll('a'), poll('b'), poll('c'), doactions() ` –  Apr 03 '19 at 14:12

1 Answers1

1

It doesn't work that way:

Basically something along the lines of kbhit, so I can check the status of a given key. But that will also let me poll the arrow keys.

In any system that doesn't allow direct access to the hardware (MS-DOS is the only example you're likely to have encountered, others would include embedded systems), you're only able to read a sequence of characters (not keys) in a terminal application. GUI applications rely upon a server which does access some of the hardware (more) directly, but transforms the data.

In a terminal (such as used by ncurses), you can only check if the incoming characters includes the one that corresponds to the keyboard-key that you're interested in. Arrow keys send a sequence of characters: with ncurses you can either read the individual characters in the sequence, or rely upon ncurses to match the sequence to a known key in the terminal description.

Even with system-specific things such as the Linux console, you won't find much support for reading the keyboard as a whole: only character events. Read kbd_mode and console_ioctl to see what's available, keeping in mind this ancient caveat from the latter:

Warning: Do not regard this man page as documentation of the Linux console ioctls. This is provided for the curious only, as an alternative to reading the source. Ioctl's are undocumented Linux internals, liable to be changed without warning. (And indeed, this page more or less describes the situation as of kernel version 1.1.94; there are many minor and not-so-minor differences with earlier versions.)

The suggested link Receiving key press and key release events in Linux terminal applications? gives some useful information. But as noted, the question (aside from the last point mentioned) is a duplicate.

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105