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 11 - Programujeme Android hru - Grafika II

V minulé lekci, Programujeme Android hru - Grafika I, jsme na obrazovku promítli slepici a pozadí.

Jak tedy pomocí metody turnChicken(int x,int y) provádíme natáčení kuřete?

Představme si, že máme souřadnicovou soustavu podobnou té kartézské. Úmyslně zdůrazňuji podobnou, protože v naší virtuální obrazovce máme pod osou x na ose y kladné hodnoty. Ostatní parametry naší soustavy již definici kartézské soustavy vyhovují: osy jsou vzájemně kolmé, jednotky na nich mají stejnou velikost (vzdálenost v px), počátek soustavy je v bodě [0,0].

Jak to tedy funguje? Obrázek nám řekne více než mnoho slov:

Přenesené souřadnice - Programujeme Android hru
  1. Odečtením souřadnic kuřete od souřadnic kliku uživatele posuneme souřadnice kuřete do počátku souřadnicového systému - tedy do bodu [0,0] a o tuto stejnou vzdálenost zároveň posuneme souřadnice kliku uživatele.
  2. Spočítáme proměnnou rt (zkratka ratio) stejným způsobem jako sinus v pravoúhlém trojúhelníku. Úmyslně jsem proměnnou nepojmenoval sinus, protože tím, že nejsme v kartézské soustavě - máme jinak osu y, by znaménka neodpovídala jednotlivým kvadrantům.
  3. Dle hodnoty proměnné rt a zároveň dle toho, zda proměnná transformedPo­sitionX je menší nebo větší než nula, určíme úhel a směr rotace slepice.

Pojďme konečně promítat, otevřeme si třídu Renderer.java, kterou máme vyplněnou z 8. dílu tak, že se nám zobrazuje místo slepice žlutý obdélník. Abychom neduplikovali text, třídu rovnou vyplníme do níže uvedeného tvaru a příště si vše vysvětlíme.

public class Renderer {

    private OrthographicCamera cam;
    private ShapeRenderer shapeRenderer;
    private SpriteBatch batcher;
    private final Vector2 demandedScreen,screenBoundBegin;
    private final GameScreen gameScreen;
    private Chicken chicken;
    private GameManager gameMng;

    private Texture left1,left2,leftSideDown1,leftSideDown2,leftSideUp1,leftSideUp2,leftUp1,leftUp2,leftDown1,leftDown2;
    private Texture right1,right2,rightSideDown1,rightSideDown2,rightSideUp1,rightSideUp2,rightUp1,rightUp2,rightDown1,rightDown2;
    private TextureRegion rBackground;
    private Animation standLeftAnime,standRightAnime;

    private int counter;
    private float runTime;
    private final int COUNTERBEGIN = 20,COUNTEREND =40, BEGINYCONSTANT;

    public Renderer(GameManager gameManager, float orthoHeight, float orthoWidth) {
        this.gameMng=gameManager;
        this.gameScreen=gameMng.getGameScreen();
        this.demandedScreen=gameScreen.DEMANDED_SCREEN;
        this.screenBoundBegin=gameScreen.SCREEN_BOUND_BEGIN;
        this.BEGINYCONSTANT=gameMng.getObjectManager().getBEGINYCONSTANT();
        this.cam = new OrthographicCamera();
        this.cam.setToOrtho(true, orthoWidth,orthoHeight);
        this.shapeRenderer = new ShapeRenderer();
        this.shapeRenderer.setProjectionMatrix(cam.combined);
        this.batcher = new SpriteBatch();
        this.batcher.setProjectionMatrix(cam.combined);

        counter=0;
        runTime=0;
        initAssetsObjects();
    }


    public void render(float delta) {

    Gdx.gl.glClearColor(0, 0, 0, 1); // black background reduce flashing
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    batcher.begin();
    //batcher.enableBlending(); //!!!!!!pruhlednost
    batcher.draw(rBackground,screenBoundBegin.x, screenBoundBegin.y, demandedScreen.x, demandedScreen.y); //pozadi
    drawChicken(delta);
    batcher.end();
    }

    private void drawChicken(float delta) {
        counter+=delta*250*(chicken.getWholeSpeed()/180); // korekce animace pri zrychlovani chicken
        if(!chicken.isStanding()) {
            if(chicken.getMovingState()==MovingState.LEFT)
            {
                if((int)counter<COUNTERBEGIN)           batcher.draw(left1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                if((int)counter>=COUNTERBEGIN)
                {
            batcher.draw(left2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                    if((int)counter>COUNTEREND)counter=0;
                }
            }
            else if (chicken.getMovingState()==MovingState.RIGHT)
            {
                if((int)counter<COUNTERBEGIN)
                batcher.draw(right1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                if((int)counter>=COUNTERBEGIN)
                {           batcher.draw(right2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                    if((int)counter>COUNTEREND)
                        counter=0;
                }
            }
            else if (chicken.getMovingState()==MovingState.LEFTSIDEDOWN)
            {
                if((int)counter<COUNTERBEGIN)           batcher.draw(leftSideDown1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                if((int)counter>=COUNTERBEGIN)
                {
            batcher.draw(leftSideDown2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                    if((int)counter>COUNTEREND)
                        counter=0;
                }
            }
            else if (chicken.getMovingState()==MovingState.LEFTSIDEUP)
            {
                if((int)counter<COUNTERBEGIN)
            batcher.draw(leftSideUp1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                if((int)counter>=COUNTERBEGIN)
                {
            batcher.draw(leftSideUp2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                if((int)counter>COUNTEREND)
                    counter=0;
                }
            }
            else if (chicken.getMovingState()==MovingState.RIGHTSIDEUP)
            {
                if((int)counter<COUNTERBEGIN)
            batcher.draw(rightSideUp1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                if((int)counter>=COUNTERBEGIN)
                {
            batcher.draw(rightSideUp2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                if((int)counter>COUNTEREND)counter=0;
                }
            }
            else if (chicken.getMovingState()==MovingState.RIGHTSIDEDOWN)
            {
                if((int)counter<COUNTERBEGIN)
            batcher.draw(rightSideDown1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                if((int)counter>=COUNTERBEGIN)
                {
            batcher.draw(rightSideDown2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                    if((int)counter>COUNTEREND)
                        counter=0;
                }
            }
            else if(chicken.getMovingState()==MovingState.LEFTUP)
            {
                if((int)counter<COUNTERBEGIN)
            batcher.draw(leftUp1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                if((int)counter>=COUNTERBEGIN)
                {
            batcher.draw(leftUp2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                if((int)counter>COUNTEREND)counter=0;
                }
            }
            else if(chicken.getMovingState()==MovingState.LEFTDOWN)
            {
                if((int)counter<COUNTERBEGIN)
            batcher.draw(leftDown1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                if((int)counter>=COUNTERBEGIN)
                {
            batcher.draw(leftDown2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                if((int)counter>COUNTEREND)
                    counter=0;
                }
            }
            else if (chicken.getMovingState()==MovingState.RIGHTUP)
            {
                if((int)counter<COUNTERBEGIN)
            batcher.draw(rightUp1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                if((int)counter>=COUNTERBEGIN)
                {
            batcher.draw(rightUp2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                if((int)counter>COUNTEREND)
                    counter=0;
                }
            }
            else if (chicken.getMovingState()==MovingState.RIGHTDOWN)
            {
                if((int)counter<COUNTERBEGIN)
            batcher.draw(rightDown1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                if((int)counter>=COUNTERBEGIN)
                {
            batcher.draw(rightDown2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
                    if((int)counter>COUNTEREND)
                        counter=0;
                }
            }
            else
                Gdx.app.log("renderer:", "Sem by se rizeni nemelo dostat.");
        }
        else {
            runTime+=delta; //kvuli animaci
            if(chicken.getStandingState()==StandingState.STANDLEFT)
            batcher.draw(standLeftAnime.getKeyFrame(runTime),chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());

            else if(chicken.getStandingState()==StandingState.STANDRIGHT)
            batcher.draw(standRightAnime.getKeyFrame(runTime),chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());

            else
                Gdx.app.log("renderer:", "Sem by se rizeni nemelo dostat.");
        }
    } //end of drawChicken

    private void initAssetsObjects() {
        this.rBackground=AssetManager.rBackground;
        this.right1=AssetManager.right1;
        this.right2=AssetManager.right2;
        this.rightSideDown1=AssetManager.rightSideDown1;
        this.rightSideDown2=AssetManager.rightSideDown2;
        this.rightSideUp1=AssetManager.rightSideUp1;
        this.rightSideUp2=AssetManager.rightSideUp2;
        this.rightUp1=rightDown1=AssetManager.right1;
        this.rightUp2=rightDown2=AssetManager.right2;

        this.left1=AssetManager.left1;
        this.left2=AssetManager.left2;
        this.leftSideDown1=AssetManager.leftSideDown1;
        this.leftSideDown2=AssetManager.leftSideDown2;
        this.leftSideUp1=AssetManager.leftSideUp1;
        this.leftSideUp2=AssetManager.leftSideUp2;
        this.leftDown1=leftUp1=AssetManager.left1;
        this.leftDown2=leftUp2=AssetManager.left2;

        this.standLeftAnime=AssetManager.standLeftAnime;
        this.standRightAnime=AssetManager.standRightAnime;

        this.chicken=gameMng.getObjectManager().getChicken();
    }
}

Přidáme importy a třídu uložíme. Nevyužitou BEGINYCONSTANT máme na příště. Vyběhla na nás chyba, že v AssetManageru není proměnná rBackground, otevřeme tedy AssetManager.java a pod stávající deklaraci proměnné

public static Texture background

přidáme:

public static TextureRegion rBackground;

Dále tuto proměnnou inicializujeme. Do funkce load() pod stávající řádky

background = new Texture(Gdx.files.internal("background.png"));
background.setFilter(TextureFilter.Nearest, TextureFilter.Nearest); //proti rozmazavani pri roztahovani

přidáme:

rBackground = new TextureRegion(background,0,0,800,500);
rBackground.flip(false, true);

Třídu uložíme a zavřeme.

Ještě jsem zapomněl v konstruktoru třídy Chicken.java inicializovat stavové proměnné movingState a standingState, proto si tuto třídu otevřeme a na konec konstruktoru doplníme:

this.standingState=StandingState.STANDRIGHT;
this.movingState=MovingState.RIGHT;

Nevyužité konstanty DEMANDED_SCREEN si zatím nevšímáme. Změnu uložíme a třídu zavřeme. Pro dnešek máme hotovo. Kdyby bylo cokoli nejasné, můžete opisovat z přiloženého zdrojového kódu, který je ke stažení. Aplikaci spustíme.

Kuře se naklání - Programujeme Android hru

Vidíme, že nám vše funguje, slepice jde správným směrem na místo kliku a také se naklání.

V příští lekci, Programujeme Android hru - Krmení I, si přidáme třídu, která vytvoří instanci našeho krmiva a třídu pro vyhledávání volné pozice na obrazovce.


 

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 32x (6.07 MB)
Aplikace je včetně zdrojových kódů v jazyce Java

 

Předchozí článek
Programujeme Android hru - Grafika I
Všechny články v sekci
Programujeme Android hru
Přeskočit článek
(nedoporučujeme)
Programujeme Android hru - Krmení 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