IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
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 6 - Programujeme Android hru - Úvaha nad obrazovkami

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

Při tvorbě jakékoli appky pro Android narazíme na problém s přizpůsobením pro mnoho displejů. Musíme se vypořádat s tím, že naše hra bude běžet na zařízeních s rozdílným rozlišením a poměrem obrazovky. Uvažujme tři konkrétní příklady tabletů:

  • Prestigio Multipad PMP 5780D s rozlišením 1024 x 768 pixelů tj. poměr 4:3
  • Samsung Galaxy Tab SM-T535NYKAXEZ s obrazovkou 1280 x 800 px tj. poměr 16:10
  • Alcatel One Touch Pop7 P310X s 1024 x 600 tj. téměř poměr 16:9

Problém nám v libgdx pomáhá řešit třída OrthographicCamera, díky které si v její instanci můžeme nastavil virtuální rozlišení, v této souvislosti mě napadají tři možnosti, jak orthocameru nastavit:

1. Nic neřešit a prostě orthokameře poručit svoje rozlišení. V tomhle vidím velký nedostatek, pokud například na obrazovce se skutečným poměrem obrazovky 16:9 nastavím rozlišení s poměrem 4:3, tak se obrázek neúměrně roztáhne, pokud to udělám opačně, tak se neúměrně smrskne a také se deformuje.

Kružnice se zobrazí jako elipsa - Programujeme Android hru

2. Ve virtuálním rozlišení využít prostě pouze poměr 4:3, protože předpokládám, že valná většina displejů je právě minimálně v poměru 4:3 (Všechny? Patří sem přece i množina 16:9.). No a zbývající pixely, které zůstanou navíc nad tento poměr, prostě nechat prázdné, či do nich umístit reklamu. Nazval bych to "preferovat obrazovky s poměrem 4:3". Jako výhodu tohoto postupu vidím jednoduchost, jako nevýhodu vidím to, že naše appka nechá na displejích s poměrem obrazovky větším než 4:3 nevyužité místo.

Obrazovku 4:3 zobrazíme na obrazovce 16:9 - Programujeme Android hru

3. Další možnost bych nazval "preferovat širokoúhlé obrazovky" a spočívala by v tom, že obrázek v poměru např. 16:9 bych na obrazovce např. 4:3 zobrazil tak, že ho celý výrazně zmenším, ale stále bude v poměru 16:9, avšak dosti zmenšený na to, aby se vešel na obrazovku 4:3. Nevýhodu tohoto postupu vidím v tom, že uživatelé s displeji např. 4:3 uvidí obrázek dosti zmenšený (přijdou o mnoho detailů) a také v tom, že bude zbývat nějaké nevyužité místo. Naopak velkou výhodu spatřuji v tom, že budou využity "širokoúhlé" obrazovky v plné své síle a to bude také cesta, kterou se vydám, přičemž co je "širokoúhlé" a co už není, jsem si stanovil sám a to tak, že obrazovku, která má poměr 1,6 a více považuji za "širokoúhlou" a obrázky na ní nezmenšuji a na obrazovce, která je pod touto hodnotou obrázky zmenšuji. Tuto hodnotu jsem zvolil záměrně, protože výrobci tabletů, se kolem tohoto čísla točí opravdu často a také protože osobně považuji obrazovky s poměrovou hodnotou pod 1,6 za jakýsi "podstandard". Takže obrazovky 16:9 nebudou o detaily ochuzeny. Obrazovky 16:10 budou plně využity a to co je více a více pod 16:10 bude více a více ochuzeno, avšak stále funkční.

Na obrazovce 4:3 zobrazíme 16:9 - Programujeme Android hru

Už jsem toho zase napsal dost, je čas jít něco nakódovat. Otevřeme si třídu GameScreen.java z minulého dílu a odstraníme v ní všechny proměnné, všechno z konstruktoru a vše také vyprázdníme z metody render (float delta). Přidáme importy (klávesová zkratka, aby nám naopak zmizely), takže to máme nějak takhle:

package com.wackychicken.screens;

import com.badlogic.gdx.Screen;

public class GameScreen implements Screen{

    public GameScreen(){

    }

    @Override
    public void show() {
    // TODO Auto-generated method stub

    }

    @Override
    public void render(float delta) {

    }

    @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

    }

}

Do třídy si přidáme kód pro obsluhu nastavení obrazovky a celá třída GameScreen.java tak bude vypadat následovně:

package com.wackychicken.screens;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.math.Vector2;

public class GameScreen implements Screen{

private final float SCREENRATIO = 1.6f;
private float orthoWidth,orthoHeight;
private final Vector2 DEMANDED_SCREEN,SCREEN_BOUND_BEGIN,SCREEN_BOUND_END;

public GameScreen(){

        DEMANDED_SCREEN=new Vector2(800,500);

        float w = Gdx.graphics.getWidth();
        float h = Gdx.graphics.getHeight();

        if(w/h>=SCREENRATIO)//je to sirokouhly?
        {
        orthoWidth = w * (DEMANDED_SCREEN.y / h);
        orthoHeight = DEMANDED_SCREEN.y;
        SCREEN_BOUND_BEGIN=new Vector2( (orthoWidth - DEMANDED_SCREEN.x)/2, 0);
        SCREEN_BOUND_END=new Vector2(SCREEN_BOUND_BEGIN.cpy().add(DEMANDED_SCREEN));
        }

        else
        {
        orthoHeight = h * (DEMANDED_SCREEN.x / w);
        orthoWidth = DEMANDED_SCREEN.x;
        SCREEN_BOUND_BEGIN=new Vector2(0, (orthoHeight - DEMANDED_SCREEN.y) / 2);
        SCREEN_BOUND_END=new Vector2(SCREEN_BOUND_BEGIN.cpy().add(DEMANDED_SCREEN));
        }
}

    @Override
    public void show() {
    // TODO Auto-generated method stub

    }

    @Override
    public void render(float delta) {

    }

    @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

    }

}

Uložíme, přidáme importy a zkusíme si spustit, zda nám Eclipse nevyhodí chybu. Zatím nebude v okně nic vidět, zatím nic nevykreslujeme. Virtuální rozlišení máme tímto ošetřené a jdeme trošku plánovat naší hru více do tříd. Podle naší dohody vytvořte:

  1. nový balík com.wackychic­ken.gameobjec­ts a v něm třídu Chicken.java
  2. nový balík com.wackychic­ken.managers a v něm třídy AssetManager.java, GameManager.java, InputManager.java, ObjectManager.java
  3. nový balík com.wackychic­ken.rendering a v něm třídu Renderer.java

tady je obrázek pro orientaci:

Balíčky a v nich třídy… - Programujeme Android hru

Třídy zatím ponecháme prázdné, psát do nich budeme od dalšího dílu, dnes si ještě řekneme, co budou mít jednotlivé třídy na starost, i když už je to patrné z jejich názvů.

  • Chicken.java - vytvoří instanci našeho hloupého kuřete
  • AssetManager.java - stará se o naloadování zdrojů do paměti (obrázky, zvuky)
  • GameManager.java - stará se o enum stav hry (ready,running,game over), počítá skóre
  • InputManager.java - obsluhuje události uživatelského vstupu, v našem případě to bude klik myší nebo dotyk prstem
  • ObjectManager.java - obsluhuje všechny pohyblivé objekty ve hře (slepici a žrádlo)
  • Renderer.java - promítačka, vykreslovač na virtuální obrazovku

Téměř všechny instance těchto tříd nám rozhýbe již předtím vytvořená třída GameScreen.java. To by bylo pro dnešek vše.

Příště, Programujeme Android hru - Rozdělení hry do tříd I, navážeme. Celý zdrojový kód je samozřejmě přiložen.


 

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 16x (631.92 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 podruhé
Všechny články v sekci
Programujeme Android hru
Přeskočit článek
(nedoporučujeme)
Programujeme Android hru - Rozdělení hry do tříd I
Č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