subota, 20 aprila, 2024
Kako da...?

LibGDX „Java game development framework” (2. dio)

Autor: Gavrilo Prodanović

U prošlom broju smo saznali da je LibGDXJavacross-platformframework za razvijanje igara, koji pomaže da svoju ideju lako pretočimo u nešto „opipljivo”. Saznali smo kako apstraktuje datotečni sistem između različitih platformi i na koji način nam pomaže da organizujemo naš kôd. Saznali smo za render() funkciju koja se poziva u krug, pa ćemo tako nastaviti izlaganje sa grafičkim mogućnostima koje LibGDX pruža.

Kao kamen temeljac LibGDX koristi OpenGLES. U poslednjoj stabilnoj verziji, podržani su OpenGLES 2.0 i 3.0. U nešto starijoj verziji ovog framework-a postojala je i podrška za OpenGL ES 1.1. Da bi sve OpenGL ES funkcije niskog nivoa bile dostupne u ovom framework-u, postoje dva wrapping interfejsa GL20 i GL30, a njihovo pozivanje se vrši preko statičkih članova klase Gdx koji ih implementiraju. Ovde nećemo trošiti vremena govoreći kako se koristi OpenGL (za to treba čitava jedna knjiga, prim.aut.), ali za one koji vole da zaobiđu OpenGL u najširem krugu, spomenućemo najčešći blok koda koji će za osnovnu boju pozadine postaviti crnu.

Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); Gdx.gl.glClearColor(0f, 0f, 0f,1);

Od klasa „višeg” nivoa, igra se vrti oko SpriteBatch-a, između čijih begin() i end() poziva se vrši potrebno iscrtavanje grafike. Često ćemo uz SpriteBatch postaviti ivice projekcije uz pomoć OrthographicCamera objekta. Texture, kao što i ime kaže, služi za čuvanje teksture. Pomoću različitih konstruktora, teksturu možete učitati iz fajla, ili iz prethodnog Pixmap objekta, takođe možete kreirati praznu teksturu određene širine i visine. Pixmap je klasa koja predstavlja sliku u memoriji i posjeduje nekoliko metoda za manipulisanje tom slikom kao što su crtanje piksela, linije, trougla, kvadrata i kruga. TextureRegion je klasa koja će biti od pomoći ako je potrebno sa neke teksture izdvojiti površinu koja treba biti iscrtana. U njoj je definisana statička funkcija split koja je od pomoći ako je određenu teksturu potrebno podjeliti na nekoliko jednakih regiona. Klasa /Sprite je tzv. helper klasa (eng. helper – ona koja pomaže) koja u svojim konstruktorima uzima Texture ili TextureRegion i čuva informacije gdje tekstura treba da bude iscrtana. Posjeduje metode za manipulaciju kao što su rotate, scale, translate, setColor i još mnoge koje mogu biti od pomoći. Animation klasa čuva listu TextureRegion objekata kojima manipuliše tako da bi se napravila animacija. U konstruktoru se zadaje dužina animacije, lista TextureRegion-a i konstanta iz enumeracije Animation.PlayMode-a koja definiše da li animacija ide normalno, u petlju ili obrnutim redosljedom. Poslije inicijalizacije ove klase dovoljno je da u svojoj render() funkciji pozovemo getKeyFrame(float stateTime) da dobijemo teksturu za taj ciklus renderovanja. NinePatch će biti koristan onima koji iscrtavaju teksturu u različitim dimenzijama, a da moraju odrediti djelove koji će ostati nepromjenjeni i djelove koji će se raširivati. U suštini, NinePatch podjeli teksturu u 3×3 matricu čijim se ćoškovima ne mjenja geometrija. Primjer NinePatch-a je dugme kontrola.

Prije nego što se izvrši neko crtanje teksture, potrebno ju je učitati u memoriju (eng. texture binding), kada je potrebno izvršiti crtanje druge teksture, onda se ona isto mora učitati. Učitavanje tekstura je dosta „skup” proces i oduzima mnogo vremena, zato se u praksi više manjih tekstura spaja u jednu veliku i onda se djelovi te velike teksture iscrtavaju i tako se dobija na performansama. LibGDX za ovaj problem ima alatku nazvanu TexturePacker koja će pretraživanjem zadate putanje upakovati teksture unutar atlasa. Za svaki direktorijum se može napisati fajl pack.json u kojem se nalazi konfiguracija o pakovanju fajlova unutar tog direktorijuma i njegovih poddirektorijuma. Takođe, kreiranje atlasa, barem po našem mišljenju, pomaže da se fajlovi bolje organizuju jer se unaprijed odredi čemu je namjenjena koja tekstura i zato što je sva grafika upakovana u jedan .atlas fajl. Da bismo približili kako izgleda korišćenje atlasa, poslužićemo se ovim kodom:

TextureAtlas atlas; atlas = new TextureAtlas(Gdx.files.internal("packedimages/pack.atlas")); Sprite sprite = atlas.createSprite("otherimagename"); NinePatch patch = atlas.createPatch("patchimagename");

U igricama se vizuelni doživljaj prenosi grafikom, ali natpisi i slova ipak su neizostavan dio igrice. LibGDX za tu namjenu nudi klasu BitmapFont. Klasa je dosta primitivna, ona posjeduje listu TextureRegion-a koji su povezani sa odgovarajućim slovima. Unutar assets direktorijuma, font je predstavljen u obliku dva fajla – jednog koji je tekstura i drugog koji opisuje karaktere koji se nalaze unutar teksture. Jedan od problema u BitmapFont-u (iz imena možemo naslutiti taj problem) jeste to što se ne može mjenjati veličina bez gubitka kvaliteta, pa zbog toga isti font mora imati više tekstura za različite veličine. LibGDX unutar svog koda i dalje nema podršku za TrueType fontove, ali postoji gdx-freetype biblioteka koja nam omogućuje da iz FreeType fontova kreiramo BitmapFont-ove različitih veličina u letu.

Za kraj, spomenućemo još da ovaj framework ima podršku za particle efekte i da posjeduje svoj editor za kreiranje ovih efekata kao i helper klase za učitavanje i upravljanje efektima. Pored 2D grafike postoji podrška za 3D grafiku u koju nećemo zalaziti zbog nešto veće kompleksnosti, ali smo iz drugih izvora i tuđih iskustava utvrdili da je 3D grafika isto veoma dobro podržana od strane ovog framework-a. U sljedećim brojevima nećemo ulaziti više u dubinsko razmatranje grafičkih mogućnosti LibGDX-a.