camera

Kontrolowanie kamery przy użyciu View

Czym jest view?


View jak nazwa wskazuje jest podglądem poziomu, a konkretnie jakiegoś mniejszego obszaru. Stosuje się go w grach gdzie poziom gry jest większy niż ekran, dzięki czemu możemy decydować, który kawałek poziomu ma być wyświetlany.

W SFML istnieją 2 podstawowe założenia odnośnie view: możesz decydować jaki kawałek poziomu będzie wyświetlany, a także gdzie jest wyświetlany oraz w jaki sposób (czy jest powiększony itd).

Podsumowując view pozwoli ci powiększać, obracać i przewijać poziom. Jest on także przydatny przy robieniu split screenów oraz mini mapach.

 

Definiowanie podglądu view


Klasa służąca do podglądu w SFML została zhermetyzowana w sf::View. Możemy jeszcze w konstruktorze zdecydować co ma wyświetlać:

Obie definicje powyżej tworzą podgląd na obszar mapy o środku na pozycji (350,300) oraz wielkości 300×200.

Możesz także edytować je poza konstruktorem:

Teraz kiedy zdefiniowałeś już swój podgląd (view) to możesz go transformować w dowolny sposób.

 

Poruszanie podglądem (przewijanie/scrolling)

W przeciwieństwie to obiektów Drawable, których pozycja standardowo była umieszczona w lewym górnym rogu to w klasie View umieszczana jest ona zawsze w centrum obiektu. To jest także powodem dla którego ustawianie pozycji w tej klasie brzmi setCenter, a nie setPosition.

Obracanie view

Czyli przechylanie naszej kamery. Jako argument podajemy wartości w stopniach.

 

Powiększanie (zoomowanie/skalowanie)

Zoomowanie jest odpowiednikiem zmiany rozmiaru, a więc używamy tutaj setSize.

 

Definiowanie gdzie view ma być wyświetlane


Skoro już wiemy jak ustawić co view ma wyświetlać, czas zająć się tym jak ustawić gdzie ma być wyświetlane. Standardowo view zajmuje cały ekran, jeżeli podgląd jest tej samej wielkości co okno wszystko jest renderowane w stosunku 1:1. Jezeli jest innych wymiarów wszystkie obiekty są odpowiednio skalowane.

Standardowe zachowanie tej klasy jest odpowiednie dla większości przypadków jednak czasami chcemy aby było inne, np w przypadku gry multiplayer gdzie chcemy użyć dzielenia ekranu (split screen) poprzez użycie dwóch viewów, które będą zajmowały jedynie po połowie ekranu. Możesz także tego użyć to wyświetlania mapy, która będzie pomniejszoną wersją wyświetlanego obszaru. Do zrobienia czegoś takiego używamy viewPort.

Aby zdefiniować viewPort musisz użyć funkcji setViewPort.

Jak możesz zauważyć viewport nie jest definiowany w pikselach lecz za pomocą faktora size. Takie zastosowanie ma swoje powody, dzięki temu nie musisz pilnować czy nastąpił event resize, aby zaktualizować jego wielkość.

Użycie viewport dla split screena w większości gier wygląda podobnie.

lub dla minimapy:

 

Użycie View


Aby narysować coś za pomocą View, musisz wcześniej ustawić View w obiekcie, który może renderować inne obiekty (RenderWindow, RenderTexture)

Jeżeli nie chcesz używać już ustawionego przez siebie View, lecz chcesz skorzystać z normalnego poglądu okna możesz to zrobić w ten sposób:

Podczas uruchamiania setView jest tworzona kopia view, a nie wskaźnik do niego co oznacza, że po każdej zmianie na View (np skalowanie) musisz wywołać ponownie setView.

 

Zmiana zachowania view


Standardowo po zmianie rozmiaru okna wszystkie obiekty są obiekty są rysowane na tych samych pozycjach tylko odpowiednio przeskalowane do nowej wielkości okna.

Możliwe że będziesz chciał zmienić ten sposób zachowania i np. przy powiększeniu okna chciałbyś aby był widoczny większy obszar mapy. Wszystko co musisz w tym wypadku zrobić to zsynchronizować view do wielkości okna.

 

Konwersja współrzędnych


Podczas gdy używasz view piksele będą mogły nie pasować do pozycji swojej pozycji, ponieważ ich pozycja będzie zależna od przeskalowania. Np klikając na pozycję (10,40) będzie mogło się okazać, że kliknęliśmy rzekomo na pozycję (30, -40) w świecie gry. Aby to poprawić musisz skonwertować pozycję na ekranie do pozycji w świecie gry: mapPixelToCoords.

Standardowo mapPixelToCoords używa obecnie używanego view, jeżeli chcesz użyć view, które nie jest obecnie aktywne, możesz to zrobić poprzez podanie go jako argument tej funkcji.

Możesz także przeprowadzić konwersję w drugą stronę: mapCoordsToPixel.

Oryginalny artykuł