Wejście sterowane odpytywaniem a zdarzeniem


19

Zajmuję się tworzeniem gry metodą odpytywania dla metody wprowadzania. Jednak teraz, gdy zagłębiam się w menu gry i inne elementy interfejsu użytkownika, stwierdzam, że prawdopodobnie chciałbym mieć dane sterowane zdarzeniami. Być może nawet posiadanie obu, używanie zdarzeń sterowanych dla interfejsu użytkownika i odpytywanie dla wejścia „świata”. Jestem ciekawy, jaka jest najlepsza droga.

Definiuję sondowanie jako: każdą pętlę aktualizacji sprawdzam, które klawisze są wciśnięte, gdzie znajduje się mysz, naciśnięte przyciski, a następnie je przeglądam i wykonuję działania na podstawie zebranych informacji.

Zdarzenie definiuję jako zdarzenie oparte na: przerwaniu, gdy zdarzenie ma miejsce, a przerwanie jest wyzwalane i blok kodu jest uruchamiany na podstawie zdarzenia.

Czy uważasz, że najlepiej jest kierować się wszystkimi zdarzeniami, wszystkimi ankietami, czy też połączenie obu jest dopuszczalne? Jeśli masz plusy i minusy, proszę wymienić je. Dzięki.

EDYTOWAĆ

Gra jest oparta na Javie / OpenGL, więc zostanie wydana na Windows / Mac / Linux. Możliwość rozszerzenia tego na urządzenia mobilne jest niska. Gra jest w stylu RTS, trzecia osoba w 3D.

EDYCJA 2

Nadal nie jestem do końca zadowolony ze sposobu, w jaki to zaimplementowałem, ale zmierzam do przechwytywania zdarzeń w moim interfejsie użytkownika, a jeśli nie są one obsługiwane przez żaden z moich składników interfejsu, przekazuję zdarzenie do „Świat” do wybierania / selekcji. Coś jak:

@Override  
private boolean handleEvent(Event event) {  
    if(hud.handleEvent(event)) {  
        return true;  
    }  
    return WORLD.handleEvent(event);  
}

W ten sposób nie dostaję kliknięć przez interfejs użytkownika, aby wybrać obiekty za przyciskami, a co nie.

Obecnie moje sterowanie kamerą wciąż opiera się na odpytywaniu, i wydaje się, że na razie działa, ale mogę to później zaktualizować.

Doceniam wszystkie odpowiedzi, przepraszam, że mogłem wybrać tylko jedną!


6
Nie jestem pewien w Javie, ale ogólnie zawsze musisz sondować dane wejściowe. Możesz wtedy publikować zdarzenia, gdy rzeczy się zmieniają, ale wciąż jest to oparte na systemie odpytywania.
— James

Moim zdaniem najważniejszym punktem zainteresowania jest zaprojektowanie pętli zdarzeń, która nie byłaby obciążona żadnymi innymi obciążeniami niż kolekcja danych wejściowych. Pozwól, że wyjaśnię: system operacyjny wykona przerwanie sterowane danymi wejściowymi i potraktuje je w globalnym „wątku wejściowym”, a następnie ten wątek systemu operacyjnego przekieruje wiadomości do aktualnie aktywnej aplikacji i zapisze dane wywiadowcze w kolejce komunikatów. Kolejka komunikatów musi zostać odpytana przez PeekMessage lub GetMessage. Najszybszym sposobem na uzyskanie tego jest użycie GetMessage i pozwolenie, aby harmonogram Cię obudził, a następnie możesz bardzo dokładnie oznaczyć datownik.
— v.oddou

Odpowiedzi:


17

To zależy od wymagań twojej gry i sprzętu. Większość gier jest zwykle zainteresowana zmianami stanu wejściowego, tj. Użytkownik naciska klawisz ognia, a broń zaczyna strzelać, użytkownik zwalnia klawisz ognia, a broń przestaje strzelać, użytkownik naciska klawisz ruchu i zaczyna się poruszać, zwalnia klawisz ruchu i przestaje się poruszać itd., więc system wprowadzania sterowany zdarzeniami ma w tych przypadkach największy sens, ponieważ informacje są już w odpowiednim formacie. Ponadto na platformie Windows już odbierasz zdarzenia dotyczące zmian stanu klawiatury i myszy, więc często jest to konwersja 1: 1 ze zdarzeń wejściowych niskiego poziomu na zdarzenia gier wysokiego poziomu. Dzięki sondowaniu często trzeba ręcznie generować takie zdarzenia, porównując stan między bieżącą a ostatnią klatką. Zasadniczo „które przyciski są teraz wciśnięte?”

To powiedziawszy, na niektórych platformach utknąłeś na wejściach z ankietami na niskim poziomie i nie ma możliwości obejrzenia się od krawędzi. Jednak zawsze osiągałem najlepsze wyniki, wykorzystując zdarzenia dla całej logiki wysokiego poziomu, ponieważ w naturalny sposób działają te systemy.


Dzięki, zamieściłem dodatkowe informacje na temat platformy i celu gry.
— MichaelHouse

1
Zauważ, że GetAsyncKeyStatejest to prosty sposób na użycie odpytywania w Win32.
— Macke,

Derp, zadałem pytanie w komentarzach Nate'a Brossa, z którym masz tu do czynienia, więc chyba poprawię to. Czy wszystkie komputery oferują przerwanie sprzętowe 1: 1 w związku ze zdarzeniem związanym z klawiaturą systemu operacyjnego i jakie platformy są ograniczone do odpytywania niskiego poziomu?
— michael.bartnett

@Macke: czasami programy antywirusowe zgłaszają programy korzystające z tego interfejsu API, ponieważ mogą otrzymywać naciśnięcia klawiszy z całego systemu globalnego, umożliwiając w ten sposób złośliwe rejestrowanie klawiatury. Najbardziej niesamowity artykuł na ten temat w całym Internecie (wiem o tym) to: securelist.com/analysis/publications/36358/…
— v.oddou

7

Nie widzę powodu, dla którego nie możesz zrobić obu i uzyskać to, co najlepsze z obu światów.

Zdarzenia wejściowe są generowane przez odpytywanie (na pewnym poziomie sterownik odpytuje sprzęt, aby zobaczyć, w jakim jest stanie), a ponieważ główna pętla odpytuje wszystkie urządzenia wejściowe, możesz łatwo wdrożyć własne. Coś prostego, takiego jak poniżej, używałem w przeszłości.

mouseInput = GetMouse();
kbInput = GetKeyboard();


// refactor this out to its own method if it makes sense
if menuState == Showing
    if mouseInput.LeftButton == State.Pressed
        LeftButton(mouseInput.X, mouseInput.Y)

// rest of game input code processing

void LeftButton(int x, int y)
{
    // left button event handler
}

Wiem, że zdefiniowałeś zdarzenia jako zakłócenia, a to, co tu umieściłem, nie jest „oparte na prawdziwych zdarzeniach”, ale nie rozumiem, co nie daje ci powyższe, że zakłócenia dają - większość użytkowników nie zauważy utrata pojedynczej klatki, chyba że gra działa z bardzo małą liczbą klatek.


1
Jestem ciekaw natury otrzymywania danych wejściowych z urządzeń. Czy zdarzenia klawiatury wysyłane przez system operacyjny są wynikiem odpytywania na poziomie sterownika urządzenia? Czy zdarzenie na klawiaturze odpowiada przerwaniu? A może występują przerwania, ale system operacyjny buforuje je i wysyła, gdy uzna to za stosowne?
— michael.bartnett

Nie jestem pewien, jak działa na tym poziomie, ale jest to najbardziej podstawowe, niektóre programy działają w pętli i sprawdzają stan klawiatury i porównują ją z poprzednim stanem, jeśli zmiana ulegnie zmianie.
— Nate

5

Istnieją tutaj dwa różne problemy:

  1. Jak odczytujesz dane wejściowe użytkownika z systemu operacyjnego / sprzętu?

  2. Jak przetwarzasz dane wejściowe użytkownika w silniku?

Jeśli chodzi o czytanie, zależy to wyraźnie od platformy i rodzaju danych, które chcesz przeczytać. Zauważ, że łatwo jest przekonwertować jedną rzecz na drugą w warstwie wejściowej. (Tj. Odpytuje i emituje zdarzenia do silnika lub nasłuchuje zdarzeń i emituje stan do silnika).

Do przetwarzania istnieje kilka różnych opcji:

  • W przypadku kontroli ruchu gracza (i podobnych schematów) odpytywanie może być prostsze, ponieważ trzeba ponownie obliczyć prędkość każdej klatki. Jest bardzo prawdopodobne, że Twoja wewnętrzna pętla będzie oparta na sondowaniu:

    tj. coś podobnego speed += 1 if button.down else -1; clamp(speed, 0, 42);

  • W przypadku zdarzeń dyskretnych (pocisk ognia, gra pauzy, teleportacja na drugą stronę planety) przetwarzanie zdarzeń jest preferowane, w przeciwnym razie twój kod będzie pełen maybeLaunchMissile(key_state);połączeń, a to po prostu ... źle, dobrze. ;)

Mam nadzieję, że to pomoże.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.