[Android][libGDX] To co początkującemu może się przydać

W tym poście mam zamiar opisać wszystkie podstawowe czynności, które będziemy mogli wykonywać przy użyciu biblioteki libGDX, oraz kilka porad. Będzie to między innymi:
- zamykanie aplikacji
- wczytywanie czcionek i obrazów
- wyświetlanie grafiki
- pisanie własną czcionką w naszej aplikacji
- konwersja typów
- zmienianie koloru i przeźroczystości grafiki
- przeliczanie osi Y myszy na układ Kartezjański, 
- obsługa przycisków
- Wyświetlanie FPS naszej aplikacji w konsoli



1. Na początek krótka porada o tym jak zamknąć naszą aplikacje.
Mianowicie w miejscu gdzie chcemy zamknąć naszą aplikację należy wstawić poniższą funkcję:

 
Gdx.app.exit();

Należy przy tym pamiętać że po wywołaniu tej funkcji aplikacja wywołuje kolejno funkcje Pause() i Dispose() w naszej aplikacji.

2. Kolejnym ważnym aspektem bez której nie byłoby możliwości tworzenia naszej gry/aplikacji jest wczytywanie zewnętrznych assetów takich jak dźwięki czy obrazki a także inne pliki jak np. ustawienia.
W libGDX odpowiada za tą czynność funkcja:

Gdx.files.internal("ścieżka_do_naszego_pliku.jego_rozszerzenie")
na przykład:

Gdx.files.internal("data/filename.png")

która wczytuje podany strumień do pamięci naszej aplikacji. Teraz podam 2 przykłady wczytania obrazka typu .png i czcionki .fnt
a) Wczytywanie obrazka:
- Tworzymy zmienną typu: Texture, a następnie wywołujemy jej konstruktor podając w nim funkcję służącą do wczytania zasobów i ścieżkę interesującego nas pliku:


texture =  new Texture(Gdx.files.internal("data/background.png"));

gdzie: "data/background.png" to adres ścieżki do naszego pliku z folderu "assets"
b) Aby wczytać czcionkę potrzebujemy wpierw plik PNG i FNT naszej czcionki
Plik PNG - zawiera graficzny wygląd naszych znaków
Plik FNT - zawiera ustawienia i ich konfigurację w pliku PNG
Najprostszą czynnością pozwalającą na wykonanie tego typu czcionki jest pobranie programu Hiero v3 z tąd:
Hiero v3
A następnie utworzenie nowej czcionki i zapisanie jej do jakiegoś folderu. Powstaną wtedy 2 pliki wymienione na początku(png i fnt) które dodajemy do naszego projektu i wczytujemy do zmiennej: BitmapFont poprzez poniższą instrukcję:


        font = new BitmapFont(Gdx.files.internal("data/font.fnt"),
                Gdx.files.internal("data/font.png"), false);

gdzie: "data/font.fnt" i "data/font.png" to adres ścieżki do naszych plików z folderu "assets"
3. Gdy mamy już możliwość wczytania własnej czcionki możemy przejść do pisania w naszej aplikacji. Aby to uczynić należy utworzyć nową instancję zmiennej globalnej typu SpriteBatch w funkcji Create():


spriteBatch = new SpriteBatch();

a następnie w funkcji Render() otworzyć "render" grafiki za pomocą funkcji:


spriteBatch.begin();

potem możemy już rysować, dodając instrukcje rysujące(warto poszukać także informacji na stronie libGDX o klasie Sprite i jej wywoływaniu):
Oto przykład wyświetlania obrazka wczytanego wcześniej przez nas do zmiennej texture:


spriteBatch.draw(texture, 0, 0, WIDTH, HEIGHT);
gdzie: WIDTH, HEIGHT to kolejno szerokość oraz wysokość naszego ekranu aplikacji, tutaj w kontekście długości i szerokość do jakiej ma być skalowany nasz obraz
A tutaj tekstu


font.draw(spriteBatch, "Nasz tekst lub zmienna typu String albo CharSequence" , 30, 60);

na koniec zaś należy zamknąć "render" grafiki


spriteBatch.end();

Uwaga: W celu zlikwidowania problemów wczytywania odpowiednio zformatowanych obrazków można w metodzie Create() wywołać poniższą instrukcję odnoszącą się do klasy Texture i wszystkich jej instancji w naszym programie:


Texture.setEnforcePotImages(false);

4. Konwersja typów. Zapewne nieraz w naszej aplikacji będziemy chcieli wyświetlić jakąś wartość liczbową informującą gracza np. o wielkości jego funduszy w grze. W tym celu musimy dokonać konwersji naszego typu(float,int itd.) na typ przyjmowany przez klasę BitmapFont(String albo CharSequence), która daje nam możliwość pisania. Najprościej jest skonwertować zmienną na typ String i na tym się teraz skupimy:
- Najpierw należy wywołać w zależności od typu zmiennej jaką chcemy przekonwertować klasę zmiennej:
np. jeśli chcemy zmienić float na String robimy tak:


Float.toString(zmienna_typu_float);

jeśli chcemy zmienić int na String robimy analogicznie zmieniając jedynie klasę na tą jakiego typu zmienną chcemy prze-konwertować:


Integer.toString(zmienna_typu_int);


A oto przykład użycia w metodzie font.draw():
 
font.draw(spriteBatch, "X: " + Float.toString(Gdx.input.getX()) + "Y: " + Float.toString(kursorY), 30, 30);

Powyższa metoda wyświetla nam pozycje myszy albo ostatnio dotkniętego punktu w aplikacji
5. Czasem może przydać się nam możliwość określenia kanału alpha(przeźroczystości) lub koloru rysowanych przez nas obrazów lub tekstu. Jest to proste do uzyskania dzięki metodzie:


spriteBatch.setColor(1, 0, 0, 1);

gdzie argumentami funkcji są kolejno r,g,b,a - czerwony, zielony, niebieski, przeźroczystość
gdy chcemy wrócić do wartości domyślenj używamy instrukcji:


spriteBatch.setColor(Color.WHITE);

Należy pamiętać że po wywołaniu instrukcji zmieniającej kolor maski i kanału alpha będzie ona stosowana do każdego nowo malowanego rysunku czy tekstu, więc jeśli nie chcemy ciągle używać danego efektu należy wrócić do ustawień domyślnych wyżej podaną instrukcją.
6. Ponieważ odczyt Y-grekowej pomiędzy funkcjami Gdx.input a SpriteBatch jest dokładnie odwrotny żeby się nie trudzić w ręczne przeliczanie proponuję przyjąć zasadę aby dostosować Input do naszej klasy rysującej, czyli koordynaty myszy Y przeliczać na koordynat Y obrazka. Można to łatwo zrobić używając funkcji(albo przerobić ją na instrukcje - jak kto woli):


      public void GetYCursorPosition()
      {
            MousePositionY = HEIGHT - Gdx.input.getY();           
           
      }

Należy jeszcze utworzyć w klasie naszej gry zmienną:


private float MousePositionY;

I wywoływać naszą funkcję na samym początku funkcji Render() albo przed miejscem gdzie będzie nam potrzebny aktualny Y myszy.
7. W tym zagadnieniu przedstawię instrukcję warunkową którą można wykorzystać do tworzenia własnych buttonów:


if(Gdx.input.isButtonPressed(Input.Buttons.LEFT) && Gdx.input.justTouched() &&
Gdx.input.getX() <= pozycjaPrzyciskuX + szerokośćPrzycisku &&
                  Gdx.input.getX() >= pozycjaPrzyciskuX &&
                  kursorY <= pozycjaPrzyciskuY + wysokośćPrzycisku &&
                  kursorY >= pozycjaPrzyciskuY)           
                  {
                      // nasze instrukcje gdy użytkownik wciśnie ten przycisk 
                  }

Wszystko co wymagało wyjaśnienie myślę że zostało przedstawione w kodzie. Metoda justTouched() zwraca wartość true tylko raz po każdym dotknięciu.
8. Do testowania aplikacji przyda nam się również informacja o aktualnej szybkości wyświetlania grafiki. Dostęp do tej informacji możemy uzyskać w konsoli Eclipse dzięki klasie:


com.badlogic.gdx.graphics.FPSLogger

aby to zrobić należy utworzyć zmienną w naszej głównej klasie gry:
 
com.badlogic.gdx.graphics.FPSLogger log;

następnie w funkcji create() utworzyć nową instancję tej klasy


log  = new  com.badlogic.gdx.graphics.FPSLogger();

i wywoływać ją w metodzie Render():


log.log();

Teraz w konsoli co sekundę będziemy uzyskiwać informacje o ilości FPS w naszej aplikacji.
Dzięki za uwagę.
Silver