💾 Archived View for gemini.ctrl-c.club › ~fleg › gemlog › 2010-12-13-sdl-joystick.gmi captured on 2023-07-22 at 17:51:50. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2021-12-03)
-=-=-=-=-=-=-
SDL jest dość przyjemną biblioteką. Jest wieloplatformowa (i to *naprawdę* wieloplatformowa, obsługuje[1] mnóstwo[2] dziwnych[3] platform[4] jak i te normalniejsze, oszczędzając programiście wiele pracy) i prosta w obsłudze. Za zadanie miałem napisać obsługę joystika - wypisanie listy dostępnych urządzeń tego typu w systemie i obsłużenie joystika. Na początku myślałem o zrobieniu tego w typowo linuksowy sposób[5], jednak po chwili w internecie okazało się, że SDL nie tylko potrafi ułatwić mi pracę, ale jeszcze sprawi, że kod będzie (przynajmniej w założeniu, nie testowałem poza Linuksem) działał wszędzie.
Kod znajduje się poniżej, a tutaj ja postaram się opisać po kolei, co się dzieje.
W liniach **8 i 9** pobieramy liczbę joystików w systemie za pomocą funkcji `SDL_NumJoysticks()`, a następnie wyświetlamy nazwę każdego za pomocą funkcji `SDL_JoystickName(i)`, gdzie parametrem jest numer joystika. Linii tej nie podświetlałem, bo w sumie nie ma tam nic ciekawego.
W **linii 18** włączamy tryb zdarzeń w obsłudze joystika. O co chodzi? Sprawa jest w sumie prosta. Normalnie można joystick obsłużyć *na chama*, wywołując nieskończoną pętlę, w każdej iteracji aktualizując stan joystika i robiąc z tym co trzeba. Takie rozwiązanie ma jednak kilka wad:
O wiele lepszym rozwiązaniem jest system oparty na *Zdarzeniach* (ang. *Event*). Jak to działa? Również możemy wykorzystać nieskończoną pętlę (chociaż możemy też sprawdzać, czy mamy jeszcze jakieś zdarzenie do obsłużenia, to nie będziemy się tym tutaj zajmować). Róznica polega jednak na tym, że w tym wypadku wywołanie funkcji `SDL_WaitEvent()` powoduje uśpienie programu do momentu otrzymania zdarzenia. Po otrzymaniu zdarzenia (którego źródłem może być nie tylko joystick, ale i np. klawiatura, ale my włączyliśmy jedynie joystick) za pomocą switcha obsługujemy zdarzenie - w tym wypadku jedynie ruch osi joystika. W podobny sposób można obsłużyć przyciski na joysticku[6], jednak jako że urządzenie, którym dysponuję przycisków nie posiada, to tego nie zaimplementowałem.
#include <iostream>; #include <SDL/SDL.h>; int main(int argc, char **argv) { if (SDL_Init(SDL_INIT_EVERYTHING) == -1) { std::cerr << "SDL nie inicjalizuje się"; return 1; } // Wypisujemy nazwy wszystkich joystików w systemie for (int i=0;i<SDL_NumJoysticks();i++) { std::cout << i << ": " << SDL_JoystickName(i) << std::endl; } // Otwieramy joystick SDL_Joystick *joy = SDL_JoystickOpen(0); SDL_JoystickEventState(SDL_ENABLE); SDL_Event event; while (true) { SDL_WaitEvent(&amp;event); // Czekamy na zdarzenie od joystika switch (event.type) { case SDL_JOYAXISMOTION: // Ruch osią joystika std::cout << "axis: " << event.jaxis.axis << " val: " << event.jaxis.value << std::endl; default: break; } } // Zamykamy joystick if (SDL_JoystickOpened(0)) SDL_JoystickClose(joy); return 0; }
Jak widać, sprawa jest bardzo prosta - pozostaje jedynie dorobienie praktycznej funkcjonalności do naszego programu. Więcej informacji o obsłudze joystika można znaleźć w dokumentacji SDL[7], tam też znajdują się przykładowe kody źródłowe. Oczywiście, obsługę zdarzeń najlepiej byłoby wykonać na osobnym wątku, aby nasza aplikacja nie usypiała się całkowicie co chwilę, ale to również wybiega poza ramy tego, co chciałem tutaj przedstawić.
=> http://gpf.dcemu.co.uk/ndsSDL.shtml 1
=> http://koti.mbnet.fi/mertama/sdl.html 2
=> http://code.google.com/p/iphone-sdl-1-3/ 3
=> http://jiggawatt.org/badc0de/android/index.html 4
=> http://archives.seul.org/linuxgames/Aug-1999/msg00107.html 5
=> http://www.libsdl.org/docs/html/sdljoybuttonevent.html 6
=> http://www.libsdl.org/docs/html/joystick.html 7