niedziela, 26 marca 2017

Wyświetlamy mapę w oknie gry

Aby móc podpiąć logikę do podłoża i platform potrzeba teraz stworzyć dodatkową warstwę tym razem Object Layer. Po wyświetleniu interesującej nas warstwy w okienku warstw zaznaczamy stworzoną nową warstwę obiektową, z paska narzędzi wybieramy Wstaw Prostokąt (bądź wciskając przycisk R) i zaznaczamy wszystkie elementy na mapie które chcemy uwzględnić. Przytrzymując przy zaznaczaniu przycisk Ctrl, automatycznie będzie nam dopasowywać ramkę zaznaczania do wielkości całych kafelek. Efekt powinien wyglądać jak poniżej. Być może nie wygląda jeszcze piorunująco, ale na ten moment chcemy skupić się na podpięciu wszystkich elementów które chcemy użyć, a dopiero później można się zająć estetyką.


Wczytujemy mapę do projektu android

Na początku zadeklarujemy 3 nowe elementy niezbędne do wczytania i wyświetlenia mapy na ekranie naszej gry. Umieszczamy je na początku klasy PlayScreen.

private TmxMapLoader maploader;
private TiledMap map;
private OrthogonalTiledMapRenderer renderer;

Pierwszy element jest klasa która posłuży do wczytania mapy z pliku .tmx. Klasa TiledMap będzie służyć do przechowywania map. Zaś OrthogonalTiledMapRenderer za zadanie ma wyświetlać  mapę, bądź poszczególne warstwy na ekranie.

Następnie w konstruktorze poniżej miejsca gdzie stworzyliśmy nowy HUD umieszczamy

maploader = new TmxMapLoader();
map = maploader.load("untitled.tmx");
renderer = new OrthogonalTiledMapRenderer(map);

To co tu wykonujemy to tworzymy nowy obiekt klasy TmxMapLoader() i przypisujemy w wcześniej zarezerwowane miejsce. Później do zmiennej map wczytujemy mapę z pliku który wcześniej stworzyliśmy. Mapę untitled.tmx należy przenieść do folderu assets w drzewku projektu android. W tym samym miejscu gdzie znajduje się badlogic.jpg. Wykonuje się to w prosty sposób w miejscu na dysku gdzie znajduje się plik .tmx klikamy go ppm (prawy przycisk myszy) i wybieramy kopiuj, a następnie w drzewku projektu w android studio na folderze assets ppm i wybieramy paste. Zmiennej renderer  przypisujemy nowy obiekt OrthogonalTiledMapRenderer przekazując również wczytaną wcześniej mapę, aby obiekt w późniejszej metodzie wyświetlania wiedział o którą mapę chodzi.

W metodzie render musimy dopisać aby renderowało wczytaną mapę, a następnie ustawiamy projekcje kamery na mapę.

renderer.render();
renderer.setView(camera);

Przesunięcie kamery

Domyślnie kamera którą stworzyliśmy skupia środek w punkcie współrzędnych 0 na x oraz 0 na y. Przez to widzimy tylko fragment mapy (czerwona ramka) który wczytaliśmy i czarne tło znajdujące się poza. Rozwiązaniem jest ustawienia środka kamery dokładnie w połowie świata który widzimy. Robimy to następującą linią, czego efektem ma być widok ten zaznaczony ramką żółtą. Trzecim parametrem jest współrzędna „z” której nie używamy, dlatego w jej miejsce wstawiamy 0.

camera.position.set(view.getScreenWidth() / 2, view.getScreenHeight() / 2, 0);

  
Skalowanie mapy

Następną rzeczą którą warto zrobić w tym miejscu to trochę pomniejszyć wielkość mapy, poskutkuje to większym obszarem mapy który jest widoczny. Poza tym wygląda to o wiele przyzwoiciej i lepiej jak na platformówkę. Zmieniamy poprzedni kod dopisując po przecinku 1 / 3f

renderer.setView(camera, 1 / 3f);

Może tu paść pytanie co robi ta literka f przy trójce. Już tłumaczę. Jest to jednoznaczne wskazanie że jest to liczba float. Dzięki temu przy podzieleniu nie zostanie ucięta końcówka liczby po przecinku tak jak ma to miejsce w przypadku typu int. Poniżej 2 sytuacje które to rozjaśnią.

1 / 3 = 3
1 / 3f = 3.3(3)

Na obecnym etapie to co mamy wygląda tak


Przesuwanie po mapie

Póki co widzimy jedynie fragment całej mapy, chcemy natomiast zobaczyć całość. Normalnie w takich typach grach następuje podążanie kamery za postacią. Postaci jeszcze jednak nie mamy, co możemy zrobić to przesuwać środek kamery na inne pozycje x i y dzięki czemu uzyskamy bardzo podobny efekt. Aby to zrobić potrzeba w metodzie render aktualizować kamerę. Tworzymy więc metodę którą nazywamy update.

public void update(float dt) {
        handleInput(dt);

        camera.update();
    }

Metoda będzie wymagać jeszcze zmiennej delta (dt). Delta jest to czas jaki zajęło wyrenderowanie ostatniej klatki. Renderowanie wykonuje się ciągle, tzn. co chwilę wykonuje się na nowo, tak aby obraz był widziany stale. Inaczej gdyby wykonało się to tylko jednokrotnie zobaczylibyśmy go lub nie przez ułamek sekundy. My chcemy aby pozycja naszej kamery zmieniała się również ciągle, gdy pojawi się do tego bodziec np. ruch postaci. Daje to efekt płynnej przejścia i nie jest to zmiana skokowa.

Zanim wykonamy update na kamerze potrzebujemy wyłapywać sygnały wejściowe sterowania (początkowo zrobimy strzałkami na klawiaturze). Tworzymy więc nową metodę którą zwiemy handleInput i tam również przesyłamy delta. Wewnątrz uwzględniamy cztery sytuacje jakie mogą nastąpić (prawo, lewo, góra, dół) korzystamy do tego z metody libgdx isKeyPressed która wykonuje się gdy klawisz został wciśnięty. Zmieniamy pozycję kamery odpowiednio dla lewo i prawo na osi x oraz góra, dół na osi y. Jako że renderowanie wykonuje się bardzo szybko możemy przemnożyć przez 100, co daje nam akceptowalną prędkość przesuwania kamery.

public void handleInput(float dt) {
        if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
            camera.position.x += 100 * dt;
        }
        if(Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
            camera.position.x -= 100 * dt;
        }
        if(Gdx.input.isKeyPressed(Input.Keys.UP)) {
            camera.position.y += 100 * dt;
        }
        if(Gdx.input.isKeyPressed(Input.Keys.DOWN)) {
            camera.position.y -= 100 * dt;
        }
    }

Pozostaje jeszcze wywołać tą metodę w innej metodzie update, co widać we wcześniejszej kodzie tamtej metody. Od tego momentu możemy dowolnie przesuwać się po całej mapie.

https://github.com/KrzysztofPawlak/WordCharger/tree/wpis7

Na dziś to tyle

Do zobaczenia

Brak komentarzy:

Prześlij komentarz