Wczytywanie map o niezdefiniowanych rozmiarach

W jaki sposób wczytać mapę kafelkową o niezdefiniowanym rozmiarze w kodzie.

Jest to problem z którym przy pisaniu gier dość dużo osób się spotyka, ponieważ zazwyczaj chcemy mieć możliwość posiadania grze różnych rozmiarów poziomów, a nie tylko jeden ustalony na sztywno. Sam z tym problemem się kiedyś zmierzyłem i w końcu postanowiłem nieco napisać na ten temat. Sposób jest uniwersalny, lecz my napiszemy go w oparciu o SFML (w moim wypadku SFML 2.2).

 

Przygotowanie


Przed właściwym rozpoczęciem programowania musimy sobie przygotować kilka rzeczy.

Tak jak wspominałem będziemy pracowali (przynajmniej ja) na SFML 2.2, oprócz tego jako bazę użyjemy znanej nam klasy Level (chyba, że nie czytałeś mojego poradnika Piszemy grę w SFML’u). Prezentowana poniżej wersja jest wersją finalną wspomnianego poradnika, którą zmodyfikujemy pod nasze potrzeby.

 

Podczas tego poradnika będziemy korzystali z std::vector, więc fajnie jakbyś chociaż mniej więcej wiedział/a na jakiej zasadzie on działa.

 

Wczytywanie poziomów o różnych wymiarach


Skoro mamy już bazę na której stworzymy nasz kod do wczytywania poziomów o różnych wielkościach to przejdźmy do modyfikacji kodu źródłowego:

Oznaczone linie to linie w których dokonaliśmy zmian: dodaliśmy plik nagłówkowy, usunęliśmy przedrostki const static  z rozmiarów mapy, a także zamieniliśmy tradycyjną tablicę na vectorową 2-wymiarową, gdzie deklaracja 1-wymiarowej tablicy wygląda to: std::vector < typ_danych > nazwa_zmiennej . Tego pliku już nie będziemy zmieniać i właśnie zaczyna się dopiero teraz właściwa zabawa.

Przypominam, że działamy na koncepcji poziomu zbudowanego ze schematu z cyfr występujących po sobie w pliku tekstowym, tutaj z racji możliwości różnych rozmiarów dwie pierwsze cyfry to szerokość i wysokość w kaflach.

Przykładowy poziom może wyglądać w ten sposób:

W jaki sposób działa nasz kod? Otóż na początku wczytujemy width  i height , które są nam potrzebne w dalszej części pracy aby odpowiednio powiększyć tablicę.

Kolejnym krokiem jest powiększenie naszej tablicy o naszą wysokość poziomu i to ona będzie pierwszą współrzędną od której będziemy używać dane, wbrew pozorom to rozwiązanie ma sens, bo nawet kafelki wczytujemy wg tej reguły: na początku idziemy do pierwszego wiersza i wczytujemy z niego wszystkie dane, później przechodzimy do kolejnego, itd. jest to jak czytanie książki, której nie czytamy od góry do dołu, tylko od lewej do prawej.

Następnie powiększamy każdy kolejny „case” o szerokość, jest to koniecznie, aby nasza tablica na każdym poziomie wysokości miała taką samą szerokość.

Dalszym krokiem jest wczytanie wartości poszczególnych kafli i wczytanie ich do tablicy, zwróć uwagę na kolejność w jakiej wszystko jest wykonywana (najpierw jest y, później x), zarówno w pętlach jak i tablicach  [y][x] /* a nie */ [x][y] .

W zasadzie wszystko już mamy zrobione, pozostało nam jedynie wyświetlić to jako tablicę sprite’ów, ale nawet teraz możesz sprawdzić w konsoli poprawność wyświetlania danych (usuwając komentarze schowanego w ten sposób kodu).

 

Przykład użycia (SFML)


Do dalszej implementacji używam SFML i tutaj jeżeli używasz innego silnika będziesz musiał nieco pozmieniać swój kod.

Myślę, że kod nie potrzebuje dodatkowego komentarza, wszystko powinno być jasne nawet dla osób, które nie piszą w SFML, w razie pytań piszcie w komentarzach.

To tyle ode mnie, mam nadzieję że poradnik okaże się przydatny, a poniżej screen z efektem działania kodu powyżej dla mapy kwadratowej oraz prostokątnej.


  • Lukas

    Literówka „nie czytamy przecież od gówy do dołu” i nie zamknięty nawias „danych (usuwając komentarze” 😉