Я новичок в программировании на C ++ и в течение двух недель пишу сценарий для игры в космический шутер для двух игроков на одной клавиатуре.
Для отображения игры я использую NCURSES, а для ввода с клавиатуры я использую X11. Для начала, у меня есть постоянная проблема с вводом с клавиатуры.
С другом мы написали эту функцию:
//earlier in the script :
Display *dpy;
if (NULL==(dpy=XOpenDisplay(NULL))) {
perror("Connexion problem");
exit(1);
}
XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync, GrabModeAsync, CurrentTime);//the function (keysPressed is just an array to store keyboard inputs) :
void getKBinput(bool (&keysPressed)[128], Display* dpy){
XEvent ev;
int kc;
if (XPending(dpy)){
XNextEvent(dpy, &ev);
switch (ev.type) {
case KeyPress:
kc = ((XKeyPressedEvent*)&ev)->keycode;
keysPressed[kc] = true;
break;
case KeyRelease:
kc = ((XKeyReleasedEvent*)&ev)->keycode;
keysPressed[kc] = false;
break;
case Expose:
while (XCheckTypedEvent(dpy, Expose, &ev));
break;
case ButtonPress:
case ButtonRelease:
case MotionNotify:
case ConfigureNotify:
default:
break;
}
}
}
}//later in the script :
XUngrabKeyboard(dpy, CurrentTime);
if (XCloseDisplay(dpy)) {
perror("You can't deconnect to the server");
exit(1);
}
Я использую эту функцию внутри цикла, чтобы перемещать каждый космический корабль в зависимости от того, какие игроки нажимают на каждый кадр.
Однако, когда я использую определенные сочетания клавиш, программа не заботится о некоторых ключах (поэтому он не регистрирует их в логическом массиве keysPressed).
Например, когда игрок 1 нажимает клавишу «D» и клавишу «C» в одно и то же время, игрок 2 не может использовать клавишу «вверх» или клавишу «!» (но игрок 2 может использовать клавишу «влево» и клавишу «вниз» одновременно без проблем).
Чтобы лучше понять, что делает этот скрипт, я переписал эту часть во внешний файл для печати нажатых клавиш и отпущенных клавиш:
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv){
Display *dpy;
XEvent ev;
char * s;
unsigned int kc;
int quit = 0;
if (NULL==(dpy=XOpenDisplay(NULL))) {
perror(argv[0]);
exit(1);
}
XAutoRepeatOff(dpy);
XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync, GrabModeAsync, CurrentTime);
for (;!quit;) {
XNextEvent(dpy, &ev);
switch (ev.type) {
case KeyPress:
kc = ((XKeyPressedEvent*)&ev)->keycode;
s = XKeysymToString(XKeycodeToKeysym(dpy, kc, 0));
if (s) printf("KEY PRESS:%s\n", s);
if (!strcmp(s, "q")) quit=~0;
break;
case KeyRelease:
kc = ((XKeyReleasedEvent*)&ev)->keycode;
s = XKeysymToString(XKeycodeToKeysym(dpy, kc, 0));
if (s) printf("KEY RELEASE:%s\n", s);
case Expose:
while (XCheckTypedEvent(dpy, Expose, &ev));
break;
case ButtonPress:
case ButtonRelease:
case MotionNotify:
case ConfigureNotify:
default:
break;
}
}
XUngrabKeyboard(dpy, CurrentTime);
XAutoRepeatOn(dpy);
if (XCloseDisplay(dpy)) {
perror(argv[0]);
exit(1);
}
return 0;
}
Это подтвердило мою проблему. Поскольку мой компьютер старый (и некоторые ключи работают ужасно), я протестировал этот скрипт на других компьютерах, чтобы получить те же результаты.
Я искал в документации x11 (может быть, не правильно?) Функцию разблокировки всех миксов между клавишами или другой способ обойти это ограничение. Я ничего не нашел. Должен ли я использовать другую библиотеку для ввода с клавиатуры?
Извините за мой плохой английский (и потенциальные ошибки), я сделал все возможное, чтобы быть понятным. Спасибо за ваше чтение.
Задача ещё не решена.
Других решений пока нет …