SFML i przechwytywanie znaków

O przechwytywaniu znaków z klawiatury i tworzeniu własnego „TextBox’a” w SFML.

Z pewnością wielu z Was chciałoby umożliwić graczowi podania np. swojego pseudonimu do tablicy wyników, albo do stworzenia profilu gracza o dowolnej nazwie (aby nie nazywać Slot 1, Slot 2, …). Jednakże jak się do tego zabrać?

W tym wpisie zajmiemy się przygotowaniem prostego kodu umożliwiającego użytkownikowi na wprowadzeniu tekstu z klawiatury, dodatkowo stworzymy ograniczenie ilości znaków jakie można wprowadzić oraz zabezpieczymy się przez wprowadzaniem niepożądanych przez nas znaków (np. znaków białych).

przechwytywanie-1

 

Implementacja


Proste przechwytywanie znaków

SFML umożliwia nam przechwytywanie znaków z klawiatury przy użyciu zdarzenia: TextEntered i najprostszy najbardziej ogólny kod służący do przechwytywania znaków może wyglądać mniej więcej w ten sposób.

To co tutaj widzimy to sprawdzenie czy wciśnięty znak ma wartość mniejszą niż 128 (czyli interesujące nas znaki, można zmniejszyć ten zakres, zalecam zajrzeć do tabeli Unicode aby dowiedzieć się jakie znaki mają jaki kod), następnie rzutujemy go na char (a zatem na ASCII) i dopisujemy go do obiektu string.

Oczywiście fajnie by było jeszcze widzieć, że faktycznie coś się dzieje po wciśnięciu klawiszy, więc po drobnych modyfikacjach kod prezentuje się następująco:

(pełny kod: gotowy do skopiowania, wklejenia i uruchomienia znajduje się na dole wpisu)

 

Ograniczenie ilości znaków

Dalsze modyfikacje są dość banalne i jak łatwo się domyślić tak można dość łatwo dodać maksymalną ilość znaków np w ten sposób:

 

Usuwanie znaków

Użytkownik może oczywiście zechcieć usunąć znak, całość można dość ładnie wszystko obsłużyć także wewnątrz TextEntered.

 

Wyłącznie standardowe znaki

Aby dopuścić do używania wyłącznie „normalnych” znaków, tzn liter i cyfr należy wprowadzić dozwolone przedziały: [48,57] + [65,90] + [97,122]. Aby dowiedzieć się skąd wzięły się te przedziały polecam zajrzeć na stronę z tabelą kodów unicode.

 

Kompletny kod

Dla leniwych poniżej przedstawiam kod zawierający wszystkie pokazane w tym wpisie featery. Kod jest gotowy do skopiowania, wklejenia i uruchomienia.

 

Posłowie


Dajcie znać co myślicie o tym wpisie, jeżeli chcielibyście rozwinięcia tego co zrobiliśmy lub chcielibyście zobaczyć więcej rzeczy tego typu (ciekawostek SFML, chociaż może być to także coś innego) to dajcie znać w komentarzach.

Code ON!


  • pw1602

    Czy nie powinno być sf::String, zamiast std::string? Zupełnie inne metody(tak?) posiada wersja std niż ta SFML i inaczej się jej używa?

    • Tutaj celowo użyłem standardowego stringa, zależy którego wolisz używać.

  • Adam Pajkert

    Jak ty to robisz że zawsze trafisz w moje potrzeby 😉 Bardzo fajny i przejrzysty poradnik.

    Szkoda że nie pokazałeś obsługi większej ilości znaków ( ąęść | wstring ), ale każdy ogarnięty sam się domyśli jak to zrobić 🙂 Poza tym nie podoba mi się brak przedrostków przestrzeni nazw, no ale już tak mam xD

    Pozdrawiam i czekam na kolejne ciekawe wpisy! 😀

    • Większość kodu z tego wpisu powstała w ramach pomocy dla @pw1602:disqus więc ten wpis powstał głównie dzięki niemu.

      Zazwyczaj jestem otwarty na propozycje wpisów więc jeżeli ktoś chciałby zobaczyć wpis na konkretny temat to wystarczy do mnie napisać, a prawdopodobnie się pojawi.

      Co do twojej uwagi to faktycznie dobrze by było, gdyby pojawiły się przestrzenie nazw w poradnikach, aby każdy mógł się połapać z jakiej biblioteki jest dana klasa (co za chwilę poprawię).

      Pozdrawiam.

      • Adam Pajkert

        W sumie to bardzo zainteresowałbym się kolizjami + poruszaniem się w grze platformowej.

        U siebie robię to używając aż 6 prostokątów! Głównie w użyciu jest ich 5, ale ten szósty jest do optymalizacji. Mój sposób działa, ale ma dwa minusy: 1.wydajność (niby nie zauważalne przy współczesnych komputerach ) 2.niechciane działanie – gdy postać spadnie / skoczy rogiem w kolizję, to jest takie szarpnięcie w lewo lub w prawo, zależy od strony. Trudno mi to opisać.

        W każdym razie chętnie zobaczyłbym twoją wizję na ten temat 🙂
        Tutaj kilka materiałów jak to u mnie wygląda ( obecnie jest w fazie testów, wygląda żałośnie, ale spokojnie, to tylko tak tymczasowo 😀 )

        Screen: https://www.dropbox.com/s/q4kg651by1mxgyk/Kolizja.PNG?dl=0
        Kod: http://pastebin.com/QqdWvD20
        Bin: https://www.dropbox.com/s/qfdbhgv4zb82g2n/AA.rar?dl=1 (F3 Debug Screen | Win32)

        Pozdrawiam 🙂

        • Możesz mi wyjaśnić po co użyłeś aż tylu collider’ów? Btw ładnie wykonane demo

          • Adam Pajkert

            Właśnie o to mi chodzi – przesadziłem z ich ilością. Było to pierwsze co mi przyszło do głowy i chciałem poeksperymentować. Udało mi się po części 😀 Głównym celem był brak efektu tunnelingu. W sumie to dalej nie wiem jak zmniejszyć ich ilość :C Dlatego właśnie z wielką chęcią zobaczyłbym inną wizję na te kolizję ( ale rymy, woah ) 🙂

          • Nie jestem żadnym specjalistą od pisania fizyki 2D i moje propozycje na rozwiązania nie muszą być wydajne, ani optymalne, ale mam kilka intuicji:
            1) Nie podoba mi się idea sprawdzania kolizji wszystkich kolidujących bloków, więc tutaj można by było wprowadzić system który dzieli całą mapę na mniejsze obszary i do nich przypisuje obiekty, które mogą wchodzić w kolizje (przypisuje obiekty statyczne), następnie wykrywamy na jakich obszarach znajdują się obiekty dynamiczne i generujące kolizje, następnie tylko na obszarach z obiektami dynamicznymi sprawdzamy kolizję (mam nadzieję, że potrafisz sobie wyobrazić o co mi chodzi).
            2) Jeżeli poziom to mapa kafelkowa to można napisać inteligentny edytor poziomów, który zastosuje twój sposób na przechowywanie informacji o kaflu i kolizji i przypisze kolizje jedynie tym blokom, które są na krawędziach (czyli blok który normalnie generuje kolizję gdy zostanie otoczony colliderami straci tą własność), co nieco zwiększy problem tunelowania, coś za coś.
            3) Zazwyczaj jesteśmy w stanie przewidzieć, które obiekty będą się poruszały z na tyle dużą prędkością, że wejdą w „tryb ducha” i po prostu zignorują kolizje, więc tutaj można albo u nich częściej sprawdzać kolizje, albo zacząć ją sprawdzać częściej od osiągnięcia pewnej prędkości.

            4) Jeżeli mam obiekt składający się z wielu colliderów, a nam zależy na dość dokładnej kolizji to można na niego nałożyć collider „ogólny” (taki trigger, który jedynie informuje o wykryciu kolizji), który jest sporym uproszczeniem kolizji, a w razie jej wykrycia uruchamiamy kolejne collidery w celu dokładniejszego jej zbadania.

            Mówiąc szczerze początkowo byłem dość sceptyczny czy faktycznie poruszę ten temat na blogu (bo nie przepadam za tym tematem), ale zagadnienie okazało się na tyle ciekawe że doczeka się swojego wpisu z serii „howTo”, ale to dopiero po (!SPOILER ALERT!)edytorze poziomów, który będzie kolejnym poradnikiem z tej serii.

          • Adam Pajkert

            1) QuadTree -> w planach 😀
            2) Czekam na twoje howTo 😉
            3) To nie jest problemem, mój aktualny system nie ma takiego błędu 😀
            4) To właśnie robi ten największy z colliderów ( eCoAll )
            5) Powinienieś sprawić może jakiś Shoutbox lub inny szybki sposób na komunikację ( może jakiś facebook? ),ponieważ komentarze są męczące 😉
            6) Dziękuję Ci za poświęcenie mi czasu, pozdrawiam! 😀

          • Do rozmowy o projektach zazwyczaj używam maila, więc i tak nie jest źle, zdarza mi się też bywać na czacie Mirosława Zelenta więc jak coś to tam, może zrobię w wolnej chwili jakiś skrypt sprawdzający czy można mnie tak złapać i wtedy pogadać (wtedy stosowne info by się pojawiało tutaj na blogu), bo po prostu mam za mało osób do takiego ewentualnego czatu.

  • Kamil Kowalski

    Myślałeś nad jakimś tutkiem do Directa?

    • Nie, nigdy mnie nie interesował, a że nie jest multiplatformowy to raczej nie zainteresuje.