Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 4 - Programujeme Android hru - Render, delta a FPS

V minulé lekci, Programujeme Android hru - Základní vestavěné třídy, jsme si ukázali vestavěné třídy a metody.

Uděláme si kafe, hodíme se do pohody a pozvolna navážeme na minulý, tedy třetí díl, ze kterého již známe metody:

  • Gdx.app.log("tag", "nase zprava");
  • Gdx.graphics.get­Width();
  • Gdx.graphics.get­Height();

a třídy:

  • BitmapFont;
  • SpriteBatch;

V dnešním díle si vysvětlíme základní pojmy render, delta a fps, ale nejdříve začneme menší "úmluvičkou", protože na ní přichází čas právě teď.

ÚMLUVIČKA

Abych nemusel neustále dokola opakovat to samé, tak se dohodněme, že když napíšu:

  1. "Přidáme importy", tak to bude znamenat, že prostě stiskneme klávesovou zkratku ctrl + shift + O a Eclipse si potřebné importy provede samo.
  2. "Vytvoříme si nový balíček", bude o tom, že v projektové složce core, klikneme pravým tlačítkem myši na podsložku src a tím vyvoláme nabídku, ze které vybereme položku New a poté Package, do kolonky name zadáme jméno balíčku a potvrdíme. Vyzkoušejte si vytvořit balíček s libovolným názvem a pak ho vymažte kliknutím na něj pravým tlačítkem a položkou delete.
  3. "Vytvoříme si novou třídu", znamená, že v projektové složce core, klikneme pravým tlačítkem myši na balíček, ve kterém chceme třídu vytvořit. Vyskočí na nás nabídka, ze které vybereme položku New a poté Class, do kolonky name zadáme jméno naší nové třídy, které bude vždy začínat velkým písmenem a potvrdíme. Opět si vyzkoušejte, vytvořit balíček a do něj třídu a pak celé vymazat. Je jasné, že když vymažeme balíček, tak vymažeme i všechny třídy v něm obsažené. V jazyce Java je konvencí, že se něčím sobě společné třídy umisťují do balíků.
  4. "Přidat zdroj(e), obrázek, zvuk nebo hudbu", bude to vždy přidání souboru do projektové složky android do podsložky assets, všimněte si, že je tam vestavěný soubor badlogic.jpg a je to právě ten smajlík, který se nám objevil v druhém díle, v případě, že se nám projekt vygenerovaný knihovnou Libgdx podařilo v Eclipse rozjet.
  5. "Spustíme", myslím tím, že spustíme složku destkop jako Java aplikaci přímo v Eclipse (Run as - Java Application)

Přejdeme tedy dále. Spustíme Eclipse a v projektové složce core si otevřeme naší třídu WackyChicken.java a provedeme několik úprav, na následující 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();
    }
}

Přepíšeme kód uvedený výše do naší třídy WackyChicken.java (ctrl+c & ctrl+v), nezapomene přidat importy a uložit. Eclipse nám vyčte, že nezná třídu GameScreen - to je zatím v pořádku.

Neexistuje třída GameScreen - Programujeme Android hru

Jen zevrubně co jsme změnili a proč. Namísto ApplicationAdapter jsme dali Game, protože třída Game je v Libgdx speciální třída pro hry, obsahující metodu setScreen, zatímco ApplicationAdapter ji neobsahuje. Metoda setScreen nám vytvoří herní obrazovku podle našich požadavků. Odstranili jsme proměnné, které již nepotřebujeme. Změnili a odstranili jsme Gdx.app.log. V metodě render() jsme vše smazali a nechali pouze řádek super.render(), klíčovým slovíčkem super voláme metodu v nadtřídě, ale tím se nyní nezabývejme. Jako poslední jsme přidali metodu dispose(), která volá metodu stejného jména v nadtřídě a slouží k vyklizení paměti od nepotřebných zvukových a grafických objektů.

Nyní otestujeme, zda si pamatujete dohodičku o balíčku/třídě. Vytvoříme si nový balíček, pojmenujeme ho com.wackychic­ken.screens a do tohoto balíčku si rovnou vytvoříme novou třídu, kterou pojmenujeme GameScreen. Jak již sami názvy vypovídají, balíček bude obsahovat třídy starající se o obrazovky a třída GameScreen potom (nejen) o herní obrazovku. Tuto třídu si otevřeme a za slova public class GameScreen dopíšeme implements Screen. Eclipse vyhodí chybu, že rozhranní Screen nezná, přidáme tedy importy.

Nicméně Eclipse vyhodí další hlášku, že GameScreen musí implementovat jisté metody, uděláme to automaticky a to tak, že klikneme levým tlačítkem myši na žárovku. Vyskočí na nás nabídka a z ní vybereme Add unimplemented methods, potvrdíme a Eclipse za nás požadované metody doplní. Uložíme si.

Přidat neimplementované metody - Programujeme Android hru

Přeskočíme zpět do třídy WackyChicken.java a přidáme importy. Eclipse nám přidá řádek import com.wackychic­ken.screens.Ga­meScreen s naší třídou, která se nám bude starat nejen o obrazovku. Uložíme a měli by nám zmizet všechny chyby. Pokud se tak stalo, můžeme třídu WackyChicken.java zatím zavřít a věnovat se slíbeným pojmům uvedeným na začátku tohoto dílu. Dnes se již budeme věnovat pouze námi vytvořené třídě GameScreen.java, přejdeme do ní a do začátku třídy si přidáme nám již známé proměnné:

private BitmapFont font;
private SpriteBatch batcher;
private String ourText;
private float storedDelta;
private int counter;

a dále konstruktor, ve kterém si tyto proměnné inicializujeme:

public GameScreen(){
font = new BitmapFont();
batcher = new SpriteBatch();
ourText = "Toto je nas prvni text, ktery vypiseme na obrazovku.";
storedDelta=0;
counter=0;
}

do metody 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, přidáme importy a spustíme. Očekávám, že to funguje tak, že do proměnné storedDelta uložíme jakýsi součet sta hodnot delta. Po zvýšení proměnné counter na hodnotu 100 tento součet vydělený hodnotou 100 vypíšeme na obrazovku a obdržíme jakýsi průměr hodnoty delta. V mém případě na tabletu to bylo nějakých 0.0184 sekundy.

Delta time - Programujeme Android hru

Delta je krátký časový úsek, který uběhne mezi dvěma po sobě jdoucími voláními funkce render. Z tohoto si odvodíme počet snímků za sekundu otázkou, kolik těchto krátkých časových úseků se vejde do jedné sekundy? V mém případě to bylo 1 / 0.0184 tedy přibližně 54 snímků za sekundu. Musíme si ale uvědomit, že toto volání je zatím naprázdno, nic moc se zatím nevykresluje a zatím se neobsluhují žádné herní objekty. Delta má normalizační schopnost, představte si, že na násobek delty navážete pohyb třeba autíčka ve hře, no a když bude horší hardware, tak se delta zvětší, tím se zvětší i tento součin a tím se urychlí i pohyb autíčka. V opačném případě, kdy bude silný hardware, bude sice delta menší, ale zato bude funkce render volána častěji, takže autíčko se na rozdílném hardwaru bude pohybovat podobně. Samozřejmě tohle funguje do určité míry, v extrému by pohyb byl silně trhaný a naše hra by nebyla hratelná.

To je pro dnešek vše, příště si vykreslíme na obrazovku pár základních obrazců. Níže nechávám výpis, jak by měla vypadat celá naše třída GameScreen.java, celý zdrojový kód je ke stažení.

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

    }

}

V příští lekci, Programujeme Android hru - Základní vestavěné třídy podruhé, si ukážeme vykreslování základních geometrických tvarů.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 20x (626.84 kB)
Aplikace je včetně zdrojových kódů v jazyce Java

 

Předchozí článek
Programujeme Android hru - Základní vestavěné třídy
Všechny články v sekci
Programujeme Android hru
Přeskočit článek
(nedoporučujeme)
Programujeme Android hru - Základní vestavěné třídy podruhé
Článek pro vás napsal Jaroslav Polívka
Avatar
Uživatelské hodnocení:
1 hlasů
Autor se věnuje převážně jazykům JAVA a C++
Aktivity