window-managment

Zarządzanie oknem w SFML

Tworzenie okna


W SFML można utworzyć okno w bardzo łatwy sposób, najwygodniej jest je utworzyć poprzez konstruktor, dzięki czemu nie będziemy się musieli bawić w ustawianie go używając dużej ilości metod.

Aby móc używać okna można dodać <SFML/Graphics.hpp> zamiast Window.hpp.

Konstruktor ma kilka możliwych form, w przykładzie powyżej pierwszym argumentem jest konstruktor VideoMode, który przyjmuje argumenty: szerokość okna, wysokość okna, tryb kolorów (opcjonalnie), kolejnym jest nazwa okna, tzw „caption”, czyli napis wyświetlany na pasku tytułu.

Konstruktor może także przyjmować kolejny argument, którym są style okna:

  • Style::None – okno bez żadnych dodatków, nie może być łączony z innymi stylami
  • Style::Titlebar – okno z paskiem tytułu
  • Style::Resize – można zmieniać wielkość okna przez użytkownika, posiada także przycisk do maksymalizowania
  • Style::Close – okno posiada przycisk X (do zamykania)
  • Style::Fullscreen – okno uruchamia się w trybie pełnego ekranu, nie może być łączone z innymi stylami oraz wymaga odpowiednio ustawionego VideoMode
  • Style::Default – standardowy styl, połączenie Resize | Close | Titlebar

Ewentualnie możemy w konstruktorze podać uchwyt do okna i zostanie ono utworzone poprzez użycie np. openGL. Istnieje jeszcze jeden sposób poza konstruktorem który pozwoli nam w łatwy sposób utworzyć nasze okno:

 

Powoływanie okna do życia


Skoro nasz okno zostało już utworzone, przydałoby się je uruchomić. Poniżej mamy standardową główną pętlę gry w SFML

Prześledźmy działanie kodu, pierwsze linie są nam znane jednak dojdźmy do pierwszej pętli while, jest to tzw. pętla główna programu, która powtarza się dopóki nie zostanie utworzone żądanie zakończenia programu. W tym przykładzie używamy metody typu bool, która sprawdza czy okno jest wciąż otwarte.

Następną ciekawostką jest Event, który jest kontenerem zdarzeń i to w nim przechowuje się informacje o np. wciśnięciu określonych klawiszy. Dzięki temu możemy w odpowiedni sposób zareagować.

W kolejnej pętli jest sprawdzenie czy nasz kontener Event jest pełny, jeżeli tak to wykonywane są odpowiednie instrukcje. W tej pętli mamy warunek dla wciśnięcia X (Zamknij) na naszym oknie, konsekwencją tego jest zamknięcie okna. Mógłbyś się zapytać: „czemu okno po wciśnięciu X nie jest zamykane automatycznie?”, a to dlatego że w ten sposób gracz mógłby stracić postępy w grze, dlatego w ten sposób możemy najpierw wywołać funkcję zapisującą grę i dopiero później zamknąć okno.

 

Przykłady niektórych metod


SFML może przyjmować także okna które przygotowaliśmy wcześniej w QT, wxWidgets, czy openGL, jednak nie posiada obsługi niektórych zaawansowanych elementów. Pamiętajmy, że SFML został zbudowany na openGL. Dlatego istnieje także parę metod, które być może będziesz musiał użyć, gdy użyjesz okien z innych bibliotek

Jeżeli jesteś ciekawy działania i użycia innych metod zapraszam do dokumentacji sf::Window.

Tak jak wspomniałem można podać uchwyt (handle) do innego okna. Robi się to w następujący sposób:

Możesz także pobrać uchwyt do okna stworzonego w SFML i użyć w ten sposób funkcji specyficznych dla danego OS.

Instrukcje jak należy to zrobić znajdziesz na różnych stronach, czy też forach. Nie będę się tutaj nad tym rozpisywał.

 

Kontrola FPS


Może się zdarzyć, że podczas działania okna, gdy będzie aplikacja działała szybko będziesz mógł doznać tzw. artefaktów, które będą powodowane przez niezsynchronizowanie odświeżania twojej aplikacji z monitorem. Można to łatwo naprawić:

Po tym wywołaniu twoja aplikacja będzie działała na równi z odświeżaniem monitora czyli 60 fps. Jeżeli chcesz możesz użyć także funkcji:

 

Rzeczy, które powinieneś wiedzieć o oknach


 

  • zamiast sf::Window preferuje się używanie sf::RenderWindow, jego użycie jest takie samo jak metod powyżej
  • możesz stworzyć i mieć uruchomionych więcej niż jedno okno w jednej aplikacji
  • w tej wersji SFML nie jest wspierane wiele monitorów
  • metoda pollEvent musi zostać wywołane w tym samym wątku, w którym zostało utworzone okno
  • na OS X okna i eventy muszą być tworzone (okna) i obsługiwane (eventy) w głównym wątku (main thread)
  • na systemie Windows okno, które jest większe niż pulpit nie zachowuje się prawidłowo, tzn są większe niż okno

Oryginalny artykuł


  • Atki

    chciałbym wiedzieć, jak dwukrotnie wyczyścić okno. Mam kod, w którym mam dwie funkcje, jedną wywołującą menu a drugą wywołującą gre (po naciśnięciu na przycisk start), w obu mam „okno.clear();” po kompilacji pokazuje się menu, klikam przycisk „start” i wtedy zawartość okna jakby się zawiesza, nie mogę nic zrobić w tym menu. Przy wyłączaniu natomiast widzę jak mignie mi ekran który rysuje się jakby pod spodem (z tej drugiej funkcji). Szukałem w google sposobów, ale nic nie znalazłem.

    • Jak rozumiem w jakiś sposób przekazujesz to okno do tych funkcji (np jako argument?), prawdopodobnie przekazujesz kopię okna, a nie oryginał (powinieneś to zrobić przy użyciu &)

      • Atki

        Mam to okno zadeklarowane (nie jestem pewien czy to dobre słowo) globalnie, nie przekazuje okna do funkcji jako argument

        • Podrzuć linka (do np pastebin) z problematycznymi fragmentami, tzn te funkcje gdzie masz .clear()

          • Atki

            http://pastebin.pl/view/6b4eb598

            Korzystałem z twojego poradnika „Piszemy grę w SFML’u: Lekcja 1”, a potem już samemu próbowałem dalej pisać

          • Znalazłem problem w funkcji game(): linie okno.clear(), okno.draw(…), itd są poza pętlą while, a powinny być wewnątrz tej z warunkiem: state == Game

          • Atki

            Dzięki! Wszystko działa 😀