Вопрос или проблема
Я новичок в программировании и хотел попробовать использовать этот код для джойстика SDL, который я нашел на GitHub. Я пытаюсь изменить код, чтобы он выводил сообщение только при нажатии на D-pad
static void test_joystick(int joy_idx)
{
SDL_Joystick* joy = SDL_JoystickOpen(joy_idx);
if (!joy)
{
fprintf(stderr, "Невозможно открыть джойстик %d\n", joy_idx);
}
else
{
initscr();
//cbreak();
noecho();
nodelay(stdscr, TRUE);
//nonl();
curs_set(0);
int num_axes = SDL_JoystickNumAxes(joy);
if (num_axes < 0) {
fprintf(stderr, "Невозможно получить количество осей SDL: %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
int num_buttons = SDL_JoystickNumButtons(joy);
if (num_buttons < 0) {
fprintf(stderr, "Невозможно получить количество кнопок SDL: %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
int num_hats = SDL_JoystickNumHats(joy);
if (num_hats < 0) {
fprintf(stderr, "Невозможно получить количество хэтов SDL: %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
int num_balls = SDL_JoystickNumBalls(joy);
if (num_balls < 0) {
fprintf(stderr, "Невозможно получить количество шариков SDL: %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
Sint16* axes = calloc((size_t)num_axes, sizeof(Sint16));
Uint8* buttons = calloc((size_t)num_buttons, sizeof(Uint8));
Uint8* hats = calloc((size_t)num_hats, sizeof(Uint8));
Sint16* balls = calloc((size_t)num_balls, 2*sizeof(Sint16));
int quit = 0;
SDL_Event event;
while(!quit)
{
SDL_Delay(10);
bool something_new = FALSE;
while (SDL_PollEvent(&event)) {
something_new = TRUE;
switch(event.type)
{
case SDL_JOYAXISMOTION:
assert(event.jaxis.axis < num_axes);
axes[event.jaxis.axis] = event.jaxis.value;
break;
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
assert(event.jbutton.button < num_buttons);
buttons[event.jbutton.button] = event.jbutton.state;
break;
case SDL_JOYHATMOTION:
assert(event.jhat.hat < num_hats);
hats[event.jhat.hat] = event.jhat.value;
break;
case SDL_JOYBALLMOTION:
assert(event.jball.ball < num_balls);
balls[2*event.jball.ball + 0] = event.jball.xrel;
balls[2*event.jball.ball + 1] = event.jball.yrel;
break;
case SDL_QUIT:
quit = 1;
printf("Получен прерывающий сигнал, выход\n");
break;
default:
fprintf(stderr, "Ошибка: Необработанный тип события: %d\n", event.type);
}
}
if (something_new)
{
//clear();
move(0,0);
printw("Имя джойстика: '%s'\n", SDL_JoystickName(joy));
printw("Номер джойстика: %d\n", joy_idx);
printw("\n");
printw("Оси %2d:\n", num_axes);
for(int i = 0; i < num_axes; ++i)
{
int len = COLS - 20;
printw(" %2d: %6d ", i, axes[i]);
print_bar((axes[i] + 32767) * (len-1) / 65534, len);
addch('\n');
}
printw("\n");
printw("Кнопки %2d:\n", num_buttons);
for(int i = 0; i < num_buttons; ++i)
{
printw(" %2d: %d %s\n", i, buttons[i], buttons[i] ? "[#]":"[ ]");
}
printw("\n");
printw("Хэты %2d:\n", num_hats);
for(int i = 0; i < num_hats; ++i)
{
printw(" %2d: значение: %d\n", i, hats[i]);
printw(" +-----+ вверх: %c\n"
" |%c %c %c| вниз: %c\n"
" |%c %c %c| влево: %c\n"
" |%c %c %c| вправо: %c\n"
" +-----+\n",
(hats[i] & SDL_HAT_UP)?'1':'0',
((hats[i] & SDL_HAT_UP) && (hats[i] & SDL_HAT_LEFT)) ? 'O' : ' ',
((hats[i] & SDL_HAT_UP) && !(hats[i] & (SDL_HAT_LEFT | SDL_HAT_RIGHT))) ? 'O' : ' ',
((hats[i] & SDL_HAT_UP) && (hats[i] & SDL_HAT_RIGHT)) ? 'O' : ' ',
(hats[i] & SDL_HAT_DOWN)?'1':'0',
(!(hats[i] & (SDL_HAT_UP | SDL_HAT_DOWN)) && (hats[i] & SDL_HAT_LEFT)) ? 'O' : ' ',
(!(hats[i] & (SDL_HAT_UP | SDL_HAT_DOWN)) && !(hats[i] & (SDL_HAT_LEFT | SDL_HAT_RIGHT))) ? 'O' : ' ',
(!(hats[i] & (SDL_HAT_UP | SDL_HAT_DOWN)) && (hats[i] & SDL_HAT_RIGHT)) ? 'O' : ' ',
(hats[i] & SDL_HAT_LEFT)?'1':'0',
((hats[i] & SDL_HAT_DOWN) && (hats[i] & SDL_HAT_LEFT)) ? 'O' : ' ',
((hats[i] & SDL_HAT_DOWN) && !(hats[i] & (SDL_HAT_LEFT | SDL_HAT_RIGHT))) ? 'O' : ' ',
((hats[i] & SDL_HAT_DOWN) && (hats[i] & SDL_HAT_RIGHT)) ? 'O' : ' ',
(hats[i] & SDL_HAT_RIGHT)?'1':'0');
}
printw("\n");
printw("Шарики %2d: ", num_balls);
for(int i = 0; i < num_balls; ++i)
{
printw(" %2d: %6d %6d\n", i, balls[2*i+0], balls[2*i+1]);
}
printw("\n");
printw("\n");
printw("Нажмите Ctrl-c для выхода\n");
refresh();
}
if ( getch() == 3 ) // Ctrl-c
{
quit = 1;
}
} // while
free(balls);
free(hats);
free(buttons);
free(axes);
endwin();
}
}
Вот ссылка на весь код, если это поможет: https://github.com/Grumbel/sdl-jstest.git
Я просто хочу вывести SDL_JOYHATMOTION в терминал.
Я надеюсь, что это будет выведено в терминал, вместо этого:
введите описание изображения здесь
Ответ или решение
Чтобы модифицировать код SDL для печати сообщения только при нажатии на D-pad (или "кнопку-хат") джойстика, вам необходимо внести несколько изменений в функции обработки событий в вашем коде. Я предоставлю вам подробные шаги, а также измененный код.
Изменения в коде
-
Удаление ненужной информации: Вам не нужно печатать всю информацию о джойстике. Вместо этого мы сосредоточимся на обработке событий, связанных только с D-pad.
-
Добавление вывода сообщений для D-pad: Вам необходимо добавить соответствующий вывод для события
SDL_JOYHATMOTION
.
Обновленный код
Вот измененная версия вашего кода, которая удовлетворяет указанным требованиям:
#include <SDL2/SDL.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <ncurses.h>
static void test_joystick(int joy_idx)
{
SDL_Joystick* joy = SDL_JoystickOpen(joy_idx);
if (!joy)
{
fprintf(stderr, "Unable to open joystick %d\n", joy_idx);
return; // Закрываем функцию, если не удалось открыть джойстик
}
initscr();
noecho();
nodelay(stdscr, TRUE);
curs_set(0);
int num_hats = SDL_JoystickNumHats(joy);
if (num_hats < 0) {
fprintf(stderr, "Unable to get SDL hats count: %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
Uint8* hats = calloc((size_t)num_hats, sizeof(Uint8));
int quit = 0;
SDL_Event event;
while (!quit)
{
SDL_Delay(10);
while (SDL_PollEvent(&event)) {
switch (event.type)
{
case SDL_JOYHATMOTION:
assert(event.jhat.hat < num_hats);
hats[event.jhat.hat] = event.jhat.value;
// Печатаем сообщение о состоянии D-pad
printw("D-pad state changed: %d\n", hats[event.jhat.hat]);
refresh(); // Обновляем окно ncurses
break;
case SDL_QUIT:
quit = 1;
printf("Received interrupt, exiting\n");
break;
default:
// Не обрабатываем другие события
break;
}
}
if (getch() == 3) // Ctrl-c
{
quit = 1;
}
}
free(hats);
endwin();
}
Объяснение изменений
-
Удаление ненужной информации: Все части кода, связанного с осями и кнопками, были удалены, так как они не соответствуют вашей цели. Мы оставили только обработку D-pad.
-
Вывод сообщения: Теперь, когда D-pad изменяет свое состояние, программа отвечает, выводя состояние (например, значение D-pad).
-
Упрощение: Мы упростили цикл обработки событий, чтобы он сосредоточился на событии
SDL_JOYHATMOTION
. Это делает код более лаконичным и легким для понимания, особенно для начинающих программистов.
Заключение
Теперь программа будет выводить на терминал только информацию о состоянии D-pad при его изменении. Убедитесь, что у вас установлена библиотека SDL и компилируйте код с нужными флагами. Если у вас есть дополнительные вопросы или вам нужна помощь с установкой, не стесняйтесь обращаться.
Этот подход не только улучшит вашу практику программирования, но и позволит сосредоточиться на том, как события обрабатываются в SDL. Успехов вам в ваших усилиях!