C týden
Tento týden až 80% sleva na e-learning týkající se jazyka C
50 % bodů zdarma na online výuku díky naší Slevové akci!

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
  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í

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.


 

Stáhnout

Staženo 30x (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
Článek pro vás napsal Jaroslav Polívka
Avatar
Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!
Autor se věnuje převážně jazykům JAVA a C++
Aktivity (4)

 

 

Komentáře

Avatar
vodacek
Redaktor
Avatar
vodacek:21.11.2016 20:32

proč tolik textur? proč nejsou v atlasu? proč to není jen 1 obrázek, který se natáčí?

 
Odpovědět
21.11.2016 20:32
Avatar
Jaroslav Polívka:22.11.2016 18:53

Obrázky bych musel pospojovat do jednoho souboru a pak je pomocí souřadnic načítat, nechci pracovat tolik se souřadnicemi. Natáčení mě taky napadlo, ale chtěl jsem ještě mihotat packama kuřete.

Odpovědět
22.11.2016 18:53
Velice často si věci žijí svým životem
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 2 zpráv z 2.