[SFML] Wczytywanie dużych poziomów (przewijana mapa)

Dzisiaj dowiesz się w jaki sposób można wczytywać poziomy zajmujące dużą ilość kafli jednak w bardziej oszczędny dla pamięci sposób, tak aby nie potrzebnych kafli po prostu nie wczytywać. W przykładzie poniżej korzystam z SFML’a w wersji 2.0, jednak kod powinien być łatwy w konwersji na inne biblioteki.

Tak jak wspomniałem zajmiemy się problemem wczytywania zbyt dużych poziomów, aby zmieściły się na ekranie oraz tak dużych że mogą spowolnić działanie gry, zobrazujmy sobie ten problem:

(kliknij aby powiększyć)

Przy wczytywaniu wszystkich kafli naraz (i rysowanej tablicy o tych samych rozmiarach) posiadamy jedynie 2 z 3 obszarów wyróżnionych na schemacie powyżej:

  • obszar niewidoczny dla użytkownika, na którym znajduje się cały wczytany poziom, tzn nawet te fragmenty, których nie widzimy
  • Scena gry, która wyświetla ten fragment poziomu na który zwrócona jest kamera.

Weźmy na ten przykład poziom który ma wymiary w kaflach 100 x 30, a ekran może wyświetlić 50×30 kafli. Tworzenie i wyświetlanie tablicy sprite’ów o tych samych rozmiarach co poziom jest bezużyteczne bo 49-50 kafli nie zostanie zobaczone przez gracza mimo że są rysowane. Olbrzymia strata pamięci dla komputera.

Rozwiązanie zbyt dużej ilości kafli na ekranie przychodzi za pomocą 3 pośredniej warstwy: obszar wczytywany do pamięci to obszar, który jest nieco większy niż scena (okno) gry o parę kafli więcej niż ekran po to aby przy ruchu gracza kamera mogła wyświetlić kafle dotychczas schowane za sceną.

Wracając do przykładu: jeżeli przy takich samych rozmiarach poziomu i ekranie mieszczących tyle samo kafli co wcześniej utworzymy tablicę do wyświetlania sprite’ów o nieco większych wymiarach (52 x 30) to zaoszczędzimy bardzo dużo pamięci, bo nie będziemy wczytywać całego poziomu lecz potrzebny nam fragment, w poziomie wczytujemy kafli nieco więcej bo musimy być gotowi do wyświetlenia kolejnych kafli gdyby gracz poszedł w prawo albo lewo (kamera nie musi obejmować całych kafli lecz np. połowę tego co wcześniej w całości za sceną).

Poniżej zamieszczam przykładową implementację takiego wczytywania poziomu jedynie fragmentami, zapraszam do samodzielnej implementacji, a w razie problemów, sugestii, wątpliwości zapraszam do systemu komentarzy (pamiętajmy że wszelkie komentarze zawsze są miło widziane).

Ostrzegam, że minimapa się przycina z tego powodu, że poruszamy się tam o 4 piksele, stąd to złudzenie (trzeba by odpowiednio prędkość gracza dopasować do delta time, wtedy powinno wszystko być ok).

Kod jest również dostępny w wersji na GitHub:

Zobacz kod na GitHub