W późniejszych
etapach dodamy jeszcze poziomą baterię nad głową która się ładuje. O taki sobie
wymysł. Poza tym animacja wygląda jakby kogoś goniła, albo uciekała. Fajne
skojarzenie. A w końcu chcemy dorwać trochę słówek w języku obcym. A tu poniżej
bateria mojego autorstwa. Niby banał, a zajął ponad 1 godzinę. Zrobienie
zielonego ludka trwało by wieki. Zrobione przy użyciu darmowego narzędzia do
tworzenia grafiki wektorowej Inkscape.
Jak widać grafika
bohatera jest w różnych stadiach, to po to aby zrobić z tego animację. Ale o
tym w następnym wpisie. Bateria natomiast może być w osobnych plikach
graficznych ponieważ nie będzie animacją, a jedynie zmieniającym się stanem.
Narzędzia do sprit-ów
Mamy więc
grafiki, można powrzucać je do folderu asset projektu androidowego. W przypadku
wielu odrębnych plików do wczytania, dodatkowo istniałaby potrzeba wykorzystać
do tego libgdx assets managera. To jedna sprawa. Inna to aby mieć pewne
udogodnienie i móc korzystać szybciej i efektywniej w przyszłości, należy
tektury upakować w jeden plik graficzny, z dodatkowym plikiem, który zawiera
informacje o właściwościach grafik. Grafiki układa się tak, aby wykorzystać
każdą wolną przestrzeń w sposób najbardziej optymalny, czyli w praktyce jedna
obok drugiej możliwie ciasno. Poza tym narzędzie ma szereg dodatkowych opcji
jak skalowanie na różne urządzenia, czy kompresja w celu przyspieszenia gry. Można
skorzystać z dowolnego przeznaczonego do tego narzędzia, jest ich cała masa. My
skorzystamy z tego tutaj
wraz z GUI (graficznym interfejsem). Pobieramy i odpalamy
Tworzenie Pack’a
Tworzymy nowy
pakiet klikając New pack, a następnie wpisujemy nazwę (np. battery_enemy
Kolejną niezbędną
rzeczą będzie wskazać Input directory, czyli miejsce gdzie są wszystkie grafiki
które chcemy dodać. Output directory wskazujemy na miejsce zapisu, zapiszmy
więc od razu w folderze projektu androidowego assets. Po wskazaniu możemy
kliknąć Pack’em all, powinno być już dostępne. W projekcie w android studio
pojawiły dwa pliki. Obrazek .png oraz informacje o nim w pliku
battery_enemy.pack. Pozwoli to nawigować po konkretnych grafikach z całej
zapakowanej zawartości.
Wczytanie grafiki z atlasa
Zaczynamy więc od
zadeklarowania obiektu w klasie PlayScreen
private TextureAtlas atlas;
To do niego
wczytamy cały zbiór obrazków z utworzonego wcześniej pliku .pack zawierające
informacje o grafikach. Dokonujemy tego w konstruktorze, dzięki czemu będzie
następowało od razu utworzeniu ekranu gry
atlas = new TextureAtlas("battery_enemy.pack");
Chcemy skorzystać
z tego atlasu w klasie naszej postaci aby wybrać dla niej odpowiedni sprite,
musimy więc jej to umożliwić. Przy tworzeniu BatteryHero dodatkowo przesyłamy
wcześniej wczytany atlas
player = new BatteryHero(world, atlas);
Teraz przechodząc
do klasy BatteryHero zmieniamy konstruktor dodając kolejny przekazany parametr
atlas
public BatteryHero(World world, TextureAtlas at) {
Wycinanie Fragmentu
Aby móc wyciągnąć
interesującą nas grafikę należy najpierw z atlasu wskazać odpowiedni do tego
region (czyli nazwa grafiki)
this.batteryhero = at.findRegion("monsterSpriteSheet");
Później wyciągamy
textury z tego obszaru i przekazujemy jako jeden z parametrów obiektu
TextureRegion. Dodatkowe 4 parametry określają współrzędne obszaru jaki chcemy
wyciąć. Bez nich wczytamy cała grafikę z wszystkimi elementami.
batteryhero = new TextureRegion(batteryhero.getTexture(), 0, 133, 100, 100);
metodą setBounds
ustawimy pozycję i rozmiar rysowanego sprite, ponownie należy pamiętać o
przeskalowaniu o PPM.
setBounds(0, 0, 100 / WordCharger.PPM, 100 / WordCharger.PPM);
zaś set region()
ustawi textury i współrzędne obszaru który będzie wyświetlany
setRegion(batteryhero);
Wyświetlanie
Do obu metod mamy
dostęp ponieważ dziedziczymy z klasy Sprite I TextureRegion odpowidenio, które
sa częścią naszego obiektu BatteryHero.
Do wyświetlenia
pozostaje nam to wrzucić do pojemnika jak robiliśmy poprzednim razem. Najpierw
ustalamy w jaki sposób ma być wyświetlane to co zostanie dodane do pojemnika.
Jednocześnie podajemy przeskalowanie. Wczytany obrazem jest wymiar 100x100, my
jednak chcemy uzyskać wymiar 70x70 tak jak w przypadku reszty kafelek. Więc
100*0,7f=70
game.batch.setProjectionMatrix(camera.combined.scale(0.7f, 0.7f, 0));
Otwieramy puszkę
game.batch.begin();
wskazujemy aby na
obiekcie gracza wywołać metodę rysowania, metoda draw() znajduje się w klasie
sprite i dzięki dziedziczeniu możemy z niej skorzystać. Niezbędne jest podać w
parametrze puszkę całej gry
player.draw(game.batch);
na końcu zamykamy
całą puszkę gry
game.batch.end();
Omówione tutaj na
szybko, ponieważ rysowanie przy pomocy batcha zostało dokładnie opisane w wpisie
przy wyświetlaniu hud.
Obecnie wyświetla
się w prezentowany niżej sposób. Na razie ludek gdzieś poniżej platformy.
Jednak sprite nie podąża i nie porusza się jeszcze za pozycją debugowanego
gracza. Więc pora się tym zająć.
Podążanie sprita z graczem
Najpierw zróbmy
metodę do aktualizacji w klasie BatteryHero
public void update(float dt) { setPosition(b2dBody.getPosition().x / 0.7f - getWidth() / 2 , b2dBody.getPosition().y / 0.7f - getHeight() / 2); }
wewnątrz niej
chcemy ustawiać pozycję sprita w miejscu b2dBody czyli miejsca debugowania
(naszego bubla). Różnicą getWidth() / 2 ustalimy grafikę centralnie w środku.
Samym getPosition wskażemy krańcową współrzędną obszaru po prawej stronie i to
w niej pojawiłaby się nieprawidłowo grafika. Czyli 2x35=70. Różnicą cofniemy
postać do miejsca żółtego x. Podobnie sprawa wygląda w przypadku y.
I tu drugi
element który się pojawił czyli 0.7f. Pierwotnie w tym miejscu powinno być
skalowanie które użyliśmy wcześniej czyli 1 / 1.3f = 0.76.... Jednak obszary
minimalnie opóźniały się w pokrywaniu. Według mnie powodem jest utrata
dokładności z dzielenia, chociaż nie dam sobie za to ręki uciąć. Więc całe
skalowanie w grze zostało zmienione na 0.7f. Pojawiło się jak do tej pory około
7-8 razy. Najsprawniej miejsca zmian będzie można zerknąć w kod na githubie
umieszczonym w linku na końcu wpisu. Właściwie do tej pory nie mam pojęcia
dlaczego akurat wcześniej ustaliłem 1/1.3f.
Na końcu w klasie
PlayScreen w metodzie update dodajemy
player.update(dt);
przekazując
parametr czasu odświeżania.
Mission completed
na dzisiaj, efekt poniżej
Pozdrawiam
Brak komentarzy:
Prześlij komentarz