4. diel - Programujeme Android hru - Render, delta a FPS
ahoj,
urobíme si kávu, hodíme sa do pohody a pozvoľna nadviažeme na minulý,
teda tretí diel, z ktorého už poznáme metódy:
- Gdx.app.log ( "tag", "nase sprava");
- Gdx.graphics.getWidth ();
- Gdx.graphics.getHeight ();
a triedy:
- BitmapFont;
- SpriteBatch;
V dnešnom diele si vysvetlíme základné pojmy render, delta a fps, ale najskôr začneme menší "úmluvičkou", pretože na ňu prichádza čas práve teraz.
ÚMLUVIČKA
Aby som nemusel neustále dookola opakovať to isté, tak sa dohodneme, že keď napíšem:
- "Pridáme importy", tak to bude znamenať, že jednoducho stlačíme klávesovú skratku ctrl + shift + O a Eclipse si potrebné importy vykoná samo.
- "Vytvoríme si nový balík", bude o tom, že v projektovej zložke core, klikneme pravým tlačidlom myši na podpriečinok src a tým vyvoláme ponuku, z ktorej vyberieme položku New a potom Package, do kolónky name zadáme meno balíčka a potvrdíme. Vyskúšajte si vytvoriť balíček s ľubovoľným názvom a potom ho vymažte kliknutím naň pravým tlačidlom a položkou delete.
- "Vytvoríme si novú triedu", znamená, že v projektovej zložke core, klikneme pravým tlačidlom myši na balíček, v ktorom chceme triedu vytvoriť. Vyskočí na nás ponuka, z ktorej vyberieme položku New a potom Class, do kolónky name zadáme meno našej novej triedy, ktoré bude vždy začínať veľkým písmenom a potvrdíme. Opäť si vyskúšajte, vytvoriť balíček a do neho triedu a potom celé vymazať. Je jasné, že keď vymažeme balíček, tak vymažeme aj všetky triedy v ňom obsiahnuté. V jazyku Java je konvencií, že sa niečím sebe spoločné triedy umiestňujú do balíkov.
- "Pridať zdroj (e), obrázok, zvuk alebo hudbu", bude to vždy pridanie súboru do projektovej zložky android do podzložky assets, všimnite si, že je tam vstavaný súbor badlogic.jpg a je to práve ten smajlík, ktorý sa nám objavil v druhom diele, v prípade, že sa nám projekt vygenerovaný knižnicou Libgdx podarilo v Eclipse rozbehnúť.
- "Spustíme", myslím tým, že spustíme zložku destkop ako Java aplikáciu priamo v Eclipse (Run as - Java Application)
Prejdeme teda ďalej. Spustíme Eclipse a v projektovej zložke core si otvoríme našej triedu WackyChicken.java a vykonáme niekoľko úprav, na nasledujúci kód:
package com.wackychicken; import com.badlogic.gdx.Game; import com.badlogic.gdx.Gdx; public class WackyChicken extends Game { @Override public void create () { Gdx.app.log("WackyChicken", "started Libgdx"); setScreen(new GameScreen()); } @Override public void render () { super.render(); //dulezity!!! } @Override public void dispose() { super.dispose(); } }
Prepíšeme kód uvedený vyššie do našej triedy WackyChicken.java (ctrl + c & ctrl + v), nezabudne pridať importy a uložiť. Eclipse nám vyčíta, že nepozná triedu GameScreen - to je zatiaľ v poriadku.
Len podrobne čo sme zmenili a prečo. Namiesto ApplicationAdapter sme dali Game, pretože trieda Game je v Libgdx špeciálny trieda pre hry, obsahujúci metódu setScreen, zatiaľ čo ApplicationAdapter ju neobsahuje. Metóda setScreen nám vytvorí hernú obrazovku podľa našich požiadaviek. Odstránili sme premenné, ktoré už nepotrebujeme. Zmenili a odstránili sme Gdx.app.log. V metóde render () sme všetko zmazali a nechali iba riadok super.render (), kľúčovým slovíčkom super voláme metódu v nadtřídě, ale tým sa teraz nezaoberajme. Ako posledný sme pridali metódu dispose (), ktorá volá metódu rovnakého mena v nadtřídě a slúžia na vypratanie pamäti od nepotrebných zvukových a grafických objektov.
Teraz otestujeme, či si pamätáte dohodičku o balíku / triede. Vytvoríme si nový balík, pomenujeme ho com.wackychicken.screens a do tohto balíka si rovno vytvoríme novú triedu, ktorú pomenujeme GameScreen. Ako už sami názvy vypovedajú, balíček bude obsahovať triedy starajúci sa o obrazovky a trieda GameScreen potom (nielen) o herné obrazovku. Túto triedu si otvoríme a za slová public class GameScreen dopíšeme Implements Screen. Eclipse vyhodí chybu, že rozhranie Screen nepozná, pridáme teda importy.
Avšak Eclipse vyhodí ďalšie hlášku, že GameScreen musí implementovať isté metódy, urobíme to automaticky a to tak, že klikneme ľavým tlačidlom myši na žiarovku. Vyskočí na nás ponuka az nej vyberieme Add unimplemented methods, potvrdíme a Eclipse za nás požadované metódy doplní. Uložíme si.
Preskočíme späť do triedy WackyChicken.java a pridáme importy. Eclipse nám pridá riadok import com.wackychicken.screens.GameScreen s našou triedou, ktorá sa nám bude starať nielen o obrazovku. Uložíme a mali by nám zmiznúť všetky chyby. Ak sa tak stalo, môžeme triedu WackyChicken.java zatiaľ zavrieť a venovať sa sľúbeným pojmom uvedeným na začiatku tohto dielu. Dnes sa už budeme venovať iba nami vytvorené triede GameScreen.java, prejdeme do nej a do začiatku triedy si pridáme nám už známe premenné:
private BitmapFont font; private SpriteBatch batcher; private String ourText; private float storedDelta; private int counter;
a ďalej konštruktor, v ktorom si tieto premenné inicializujeme:
public GameScreen(){ font = new BitmapFont(); batcher = new SpriteBatch(); ourText = "Toto je nas prvni text, ktery vypiseme na obrazovku."; storedDelta=0; counter=0; }
do metódy render napíšeme:
public void render(float delta) { Gdx.gl.glClearColor(0, 0, 0, 1); // pozadi nastavime na pozadovanou barvu Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); batcher.begin(); batcher.setColor(1, 1, 1, 1); font.draw(batcher, ourText ,50,450); batcher.end(); if(counter<100) { storedDelta+=delta; counter++; } else { batcher.begin(); font.draw(batcher, "Delta: "+ storedDelta/100 ,50,400); batcher.end(); } }
Uložíme, pridáme importy a spustíme. Očakávam, že to funguje tak, že do premennej storedDelta uložíme akýsi súčet sto hodnôt delta. Po zvýšení premenné counter na hodnotu 100 tento súčet vydelený hodnotou 100 vypíšeme na obrazovku a obdržíme akýsi priemer hodnoty delta. V mojom prípade na tabletu to bolo nejakých 0.0184 sekundy.
Delta je krátky časový úsek, ktorý uplynie medzi dvoma po sebe nasledujúcimi volaniami funkcie render. Z tohto si odvodíme počet snímok za sekundu otázkou, koľko týchto krátkych časových úsekov sa zmestí do jednej sekundy? V mojom prípade to bolo 1 / 0.0184 teda približne 54 snímok za sekundu. Musíme si ale uvedomiť, že toto volanie je zatiaľ naprázdno, nič moc sa zatiaľ nevykresľuje a zatiaľ sa neobsluhujú žiadne herné objekty. Delta má normalizačné schopnosť, predstavte si, že na násobok delty nadviažete pohyb treba autíčka v hre, no a keď bude horšie hardware, tak sa delta zväčší, tým sa zväčší aj tento súčin a tým sa urýchli aj pohyb autíčka. V opačnom prípade, kedy bude silný hardvér, bude síce delta menšie, ale zato bude funkcia render volaná častejšie, takže autíčko sa na rozdielnom hardvéru bude pohybovať podobne. Samozrejme toto funguje do určitej miery, v extrému by pohyb bol silne trhaný a naša hra by nebola hrateľná.
To je pre dnešok všetko, nabudúce si vykreslíme na obrazovku pár základných obrazcov. Nižšie nechávam výpis, ako by mala vyzerať celá naša trieda GameScreen.java, celý zdrojový kód je k stiahnutiu.
package com.wackychicken.screens; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Screen; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.SpriteBatch; public class GameScreen implements Screen{ private BitmapFont font; private SpriteBatch batcher; private String ourText; private float storedDelta; private int counter; public GameScreen(){ font = new BitmapFont(); batcher = new SpriteBatch(); ourText = "Toto je nas prvni text, ktery vypiseme na obrazovku."; storedDelta=0; counter=0; } @Override public void show() { // TODO Auto-generated method stub } @Override public void render(float delta) { Gdx.gl.glClearColor(0, 0, 0, 1); // pozadi nastavime na pozadovanou barvu Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); batcher.begin(); batcher.setColor(1, 1, 1, 1); font.draw(batcher, ourText ,50,450); batcher.end(); if(counter<100) { storedDelta+=delta; counter++; } else { batcher.begin(); font.draw(batcher, "Delta: "+ storedDelta/100 ,50,400); batcher.end(); } } @Override public void resize(int width, int height) { // TODO Auto-generated method stub } @Override public void pause() { // TODO Auto-generated method stub } @Override public void resume() { // TODO Auto-generated method stub } @Override public void hide() { // TODO Auto-generated method stub } @Override public void dispose() { // TODO Auto-generated method stub } }
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 21x (626.84 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Java