Obsługa UI dowolnymi urządzeniami — chować kursor czy nie?

2

Kończę klepać kod obsługi UI w swoim silniku, na liście TODO zostało mi jeszcze kilka pozycji, w tym ta dotycząca kursora myszy. Nie mam bogatego doświadczenia z graniem w bardziej nowoczesne tytuły, dlatego potrzebuję porady w tej sprawie.

Otóż kernel UI, w obecnej formie, pozwala obsługiwać główne menu dowolnym urządzeniem — myszą, klawiaturą i gamepadami. Jeśli kursor znajduje się w obrębie kontenera UI, aktualizator sprawdza czy jakaś kontrolka znajduje się pod kursorem — jeśli tak to ją fokusuje i przekazuje jej zdarzenia myszy (ruch kursora, klikanie, scrollowanie itd.). Jeśli pod kursorem nie ma żadnej kontrolki, to żadna nie jest aktywna (nie ma fokusu) — jeśli kontrolka była sfokusowana, ale kursor wyjechał poza jej obszar, to traci ona fokus.

Ogólnie chodzi o to, że jeśli gracz rusza myszą i coś klika/scrolluje, to kontener UI będzie posiadał sfokusowaną (aktywną) kontrolkę tylko wtedy, gdy kursor nad jakąś kontrolką się znajduje. Jeśli kursor jest nad pustym obszarem kontenera, to nie ma fokusu.

Teraz zostało mi jeszcze dodać flagę, aby gdy mysz jest w użyciu i gracz wciśnie klawisz lub coś na gamepadzie, to mysz się deaktywuje, kursor się chowa i od tego momentu input myszy jest ignorowany. W ten sposób, jeśli gracz będzie chciał grać np. tylko gamepadem, będzie sobie sterował UI za pomocą gamepada (lub pomagał sobie klawiaturą), a kursor myszy nie będzie mu przeszkadzał (będzie ukryty).


Według mnie, jeśli ktoś nie chce używać myszy, bo woli klawiaturę lub gamepady, to kursor powinien być stale niewidoczny. Aby jednak móc w dowolnym momencie skorzystać z myszy, wystarczy ją ruszyć lub kliknąć, kursor się pokaże i kontener UI sfokusuje to co jest pod kursorem (jeśli nie ma pod nim kontrolki to usunie fokus z kontenera).

I tutaj mam pytanie — dla mnie takie zachowanie jest bardzo dobre, a dla was?

Mogę zrobić tak, że kursor myszy będzie stale widoczny i będzie zmieniał fokus tylko jeśli wjedzie się nim w obszar innej kontrolki niż aktualnie sfokusowana. Widziałem, że tak to działa w kilku grach, jednak są to gry, w które trzeba grać myszą. Moja gra taką nie będzie — gamepady i klawiatura będą najlepsze do grania, ale mapper dopuszcza użycie myszy dla praktycznie dowolnej akcji (w tym chodzenia). Jeśli więc gracz będzie chciał grać np. mysz+klawiatura, to nie ma problemu — wtedy obsługa wszystkich menu myszą będzie idealna, wręcz obowiązkowa.

Jak to widzicie? Wolelibyście cały czas widzieć kursor czy żeby był ukryty, jeśli nie chcielibyście używać myszy? A podczas korzystania z myszy w menu, wolelibyście aby mysz umożliwiała tylko aktywację kontrolki pod kursorem, czy aby też deaktywowała kontrolkę, jeśli przesunie się go w puste miejsce kontenera UI?

3

Ja bym to widział tak:
Kursor ma być widoczny tylko wtedy gdy gramy na klawiaturze/myszce. Zmiana schematu powinna następować w locie:

  1. Gram padem - widzę sterowanie dopasowane pod pada - nie widzę kursora (co najwyżej hovery nad opcjami/elementami gry)
  2. Grając padem - postanawiam odłożyć go na bok, macham myszką - sterowanie dopasowuje się do myszki (lub/i klawiatury) - kursor jest widoczny
  3. Biorę pada do ręki - naciskam dowolny przycisk - sterowanie przestawia się z powrotem na pada - kursora nie widać.

Spotkałem się z takim podejściem w wielu grach na steamie i lepszej opcji nie widzę.

0

Tutaj chodzi o obsługę głównego menu i wszystkich innych menu, które mają być obsługiwane dowolnym urządzeniem, bez uwzględniania mappingu (przypisanych triggerów do akcji gry). Np. każde ogólne menu może być sterowane klawiszami strzałek oraz Esc i Enter, jeśli chodzi o gamepady to nawigacja D-Padem lub gałkami analogowymi, a wybór i cofanie przyciskami 1 i 2 (opcjonalnie 3 i 4). Może też być myszą, tak samo jak w powłoce Windows — ruch kursora, klikanie, capturing itd.

axelbest napisał(a):

Spotkałem się z takim podejściem w wielu grach na steamie i lepszej opcji nie widzę.

Do czasu aż zechcesz pograć retro-kontrolerem, który np. posiada tylko D-Pad i sześć przycisków. Ciekawe jak te genialne, automatyczne mappery przypiszą do takiego funkcje gry. A będzie jeszcze ciekawiej, jeśli — tak jak w przypadku moich retro-kontrolerów — wszystkie posiadają ten sam numer Vendor i Product oraz identyczną nazwę, przez co nie da się ich odróżnić z poziomu software'u, choć mają różną liczbę osi i przycisków.


Zapytałem was o opinię dotyczącą tego, czy lepiej by było gdyby kursor znikał, gdy nawiguje się klawiaturą/gamepadami, czy lepiej by było gdyby był cały czas widoczny (i czy kursor w pustym miejscu kontenera ma deaktywować kontrolki czy nie). Proszę, abyście się skupili na zachowaniu kursora myszy, bo opinie na ten temat będą mi pomocne, nie na mapperze.

Z drugiej strony, już na początku prac nad tym silnikiem ustanowiłem, że nie będę korzystał z żadnych automatycznych mapperów, tym bardziej, że są one z założenia niepoprawne i problematyczne. Mapper własnego pomysłu mam już zaimplementowany i z niego nie zrezygnuję. Ten wątek dotyczy tylko zachowania kursora myszy w trakcie obsługi UI.

0
axelbest napisał(a):
  1. Gram padem - widzę sterowanie dopasowane pod pada - nie widzę kursora (co najwyżej hovery nad opcjami/elementami gry)
  2. Grając padem - postanawiam odłożyć go na bok, macham myszką - sterowanie dopasowuje się do myszki (lub/i klawiatury) - kursor jest widoczny
  3. Biorę pada do ręki - naciskam dowolny przycisk - sterowanie przestawia się z powrotem na pada - kursora nie widać.

Tak jak tutaj napisane, tak to się aktualnie robi i takiego rozwiązania oczekiwaliby gracze

0

Czyli automatyczne pokazywanie i ukrywanie kursora wg was i innych jest spodziewane. Spoko.

Pozostaje jeszcze druga kwestia — czy ruch kursora nad pustym obszarem ma deaktywować aktualnie aktywną kontrolkę, czy powinna ona być cały czas aktywna, dotąd, aż kursor najedzie na inną kontrolkę. IMO pierwsza opcja, czyli dezaktywacja kontrolki, gdy kursor opuści jej obszar, jest intuicyjna.

1

Ja u siebie nie wchodziłem aż w takie szczegóły, ale robiłem tak jak mi najwygodniej i to jak to finalnie działa jest tylko konsekwencją mojej radosnej twórczości.

Kursor pokazuje się tylko w menu oraz podczas pauzy.
Kiedy najadę kursorem na przycisk to ma on focus, który może się tylko zmienić gdy najadę kursorem na inny przycisk lub użyję klawisza nawigacji.
Kiedy kursor znajduje się nad przyciskiem, klawisze nawigacji wtedy nie mają efektu.

Filmik z gierki:

BTW. w starych gierkach (NES) twórcy poszli o krok dalej i kursor myszy jest poruszany przy użyciu innych kontrolerów ;)
np.:

To by wiele ułatwiało, bo bindingi nawigacji byś po prostu podpiął pod zmianę pozycji wirtualnego kursora.

1
Spine napisał(a):

Ja u siebie nie wchodziłem aż w takie szczegóły, ale robiłem tak jak mi najwygodniej i to jak to finalnie działa jest tylko konsekwencją mojej radosnej twórczości.

Dla mnie wchodzenie w szczegóły jest codziennością — dbam o każdy. ;)

Kursor pokazuje się tylko w menu oraz podczas pauzy.

U mnie tak samo by to działało, ale tylko wtedy, gdy gracz lub któryś z dwóch graczy ma przypisane akcje do triggerów myszy (i jej ruchu). Wtedy wejście w któreś główne menu spowoduje automatyczne pokazanie się kursora.

Po drugie, musi to też działać w trakcie gry. Jeśli któryś gracz ma przypisane akcje do myszy, to wejście w zasobnik z przedmiotami (wąskie menu, wysuwane z boku) również będzie sterowane za pomocą myszy, więc kursor też powinien się sam pokazywać i, dodatkowo, być obsługiwanym bez uwzględnienia mappingu (lewy przycisk służy do klikania, nieważne która akcja jest pod niego podpięta i czy w ogóle).

Kiedy najadę kursorem na przycisk to ma on focus, który może się tylko zmienić gdy najadę kursorem na inny przycisk lub użyję klawisza nawigacji.
Kiedy kursor znajduje się nad przyciskiem, klawisze nawigacji wtedy nie mają efektu.

Oglądnąłem twoje demo — fajnie to działa. Tyle że u ciebie kursor jest widoczny cały czas, nawet jeśli użyje się klawiatury. Podobnie działa menu np. w Nuclear Throne, tyle że tam jest ciut inaczej, bo jeśli kursor jest nad kontrolką i wciśnie się klawisz, to fokus się przenosi. Jeśli ruszy się myszą to nic się nie dzieje, kontrolka pod kursorem nie dostaje fokusu. Dopiero po zabraniu kursora znad tej nieaktywnej kontrolki i najechaniu na nią jeszcze raz, otrzyma ona fokus.

BTW. w starych gierkach (NES) twórcy poszli o krok dalej i kursor myszy jest poruszany przy użyciu innych kontrolerów ;)

[...]

To by wiele ułatwiało, bo bindingi nawigacji byś po prostu podpiął pod zmianę pozycji wirtualnego kursora.

Dałoby się to zrobić, np. używać prawej gałki analogowej do obsługi kursora. Ale nie wiem czy jest sens, skoro zdecydowanie szybciej da się przenieść fokus używając D-Pada lub gałki analogowej po prostu przeskakując po kontrolkach.

0
furious programming napisał(a):

Pozostaje jeszcze druga kwestia — czy ruch kursora nad pustym obszarem ma deaktywować aktualnie aktywną kontrolkę, czy powinna ona być cały czas aktywna, dotąd, aż kursor najedzie na inną kontrolkę. IMO pierwsza opcja, czyli dezaktywacja kontrolki, gdy kursor opuści jej obszar, jest intuicyjna.

Tylko pierwsza opcja, tak aktualnie się robi.
Jeśli byłaby druga opcja, to jakie byłoby działanie, jeżeli najedziesz na przycisk, a później poza niego, np. na tło i kliknalbys LMB? Skoro byłby ciągle podświetlony jakiś przycisk, to wydawałoby się, że musiałaby się zadziać wtedy taka sama akcja, jakbyś kliknął w przycisk, a to byłoby mylące

0
tmk3 napisał(a):

Tylko pierwsza opcja, tak aktualnie się robi.

Druga opcja też jest używana — dlatego właśnie dopytuję.

Jeśli byłaby druga opcja, to jakie byłoby działanie, jeżeli najedziesz na przycisk, a później poza niego, np. na tło i kliknalbys LMB? Skoro byłby ciągle podświetlony jakiś przycisk, to wydawałoby się, że musiałaby się zadziać wtedy taka sama akcja, jakbyś kliknął w przycisk, a to byłoby mylące

Jeśli mam kursor nad kontrolką i wyjadę poza obszar, to ta kontrolka się nie odznacza. Jeśli kliknę w pusty obszar, to zostaje wykonana akcja tej aktywnej kontrolki. Dziwne to, ale w niektórych przypadkach nawet działa to sensownie.

Np. w Nuclear Throne tak to działa. Co kilka poziomów pokazuje się ekran z wyborem jednej spośród czterech losowych mutacji — cztery karty są wyświetlone na dole. Można najechać kursorem na jedną z nich i kliknąć w nią, aby ją wybrać. Druga opcja — klawiszami kierunku (np. WSAD) ustawić fokus na wybranej karcie i kliknąć w pustym miejscu — też zostanie wybrana aktywna karta. I o ile przydatne to jest na tym ekranie, tak niestety dokładnie tak samo działa to w menu głównym, co przyprawiało mnie o ból głowy — nie mogłem za bardzo ogarnąć co się dzieje. Dopiero po dłuższej chwili sprawdziłem jak to działa i ogarnąłem. Tego typu dziwactw chcę uniknąć.


Dla mnie intuicyjne jest to, że jeśli kursor jest nad kontrolką to ta się aktywuje, a jeśli się go zabierze znad niej to się deaktywuje — na razie tak to mam zaimplementowane (pomijając obsługę mouse capture, bo to specjalny ficzer). Tak samo dla mnie intuicyjne jest to, że kliknięcie w coś powinno być zaliczane, jeśli nad kontrolką wcisnę i puszczę przycisk myszy, nie przesuwając za bardzo kursora, a tym bardziej nie zabierając go znad obszaru kontrolki.

Problem pojawia się wtedy, gdy kursor zabierze się w puste miejsce i wciśnie coś na klawiaturze/gamepadzie. Nie ma sfokusowanej kontrolki, więc trzeba nową jakoś wyznaczyć. Obecnie mam to zrobione tak, że aktywuje się ta najbliżej środka obszaru kontenera UI (ignorując kontrolki ukryte, zablokowane i te, które nie akceptują fokusu) — działa to dość fajnie, efekt jest intuicyjny. Wszystko dlatego, że kontener może być większy niż widoczny obszar na ekranie i to pozwala aktywować coś co jest widoczne na ekranie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1