Vianoce v ITnetwork sú tu! Dobí si teraz kredity a získaj až 80 % extra kreditov na e-learningové kurzy ZADARMO. Zisti viac.
Hľadáme nové posily do ITnetwork tímu. Pozri sa na voľné pozície a pridaj sa k najagilnejšej firme na trhu - Viac informácií.

10. diel - Programujeme Android hru - Grafika I

V minulom diele nášho seriálu sme načítali grafické zdroje pozadie a sliepky. V dnešnom dvoj-diele je premietneme na obrazovku.

Pôjde o veľmi jednoduché premietanie, sliepky bude mať nasledujúce možnosti smerov chôdzou a rotáciou:

  • chôdza vľavo, rotácia vľavo
  • chôdza vpravo, rotácie vpravo
  • chôdza dole, rotácia vľavo
  • chôdza dole, rotácia vpravo
  • chôdza hore, rotácia vľavo
  • chôdza hore, rotácia vpravo
  • chôdze a rotácie šikmo vpravo hore
  • chôdze a rotácie šikmo vpravo dole
  • chôdze a rotácie šikmo vľavo dole
  • chôdze a rotácie šikmo vľavo hore
Varianty pohybov a otočenie - Programujeme Android hru

Ku každej možnosti je viazaná sada dvoch obrázkov, ktoré premietneme striedavo na obrazovku, aby sme vytvorili aspoň základné ilúziu chôdze sliepky.

Náš kód vyberie jednu z možností na základe výpočtu, ktorý objasním ďalej. Nesmiem zabudnúť zdôrazniť, že možnosti chôdzou iba čisto vľavo, vpravo, hore a dole málokedy existujú. Sliepky sa väčšinou pohybuje viac či menej po oboch osiach súčasne - teda šikmo. My to ale urobíme tak, že pohyby v mierne šikmých smeroch budeme považovať za pohyby čisto vľavo, vpravo, dolu alebo hore. Inak povedané, pri mierne šikmých pohyboch nebudeme sliepku nakláňať vôbec.

Rôzne možnosti premietnutí podľa aktuálnej pozície sliepky a kľučku užívateľa na obrazovku nie sú ničím iným, než vlastnosťami našej sliepky. Otvoríme si triedu Chicken.java a pomocou vymenovaných konštánt tieto vlastnosti sliepke pridáme. Pod existujúce premenné si pridáme ďalšie:

public enum MovingState{LEFT,LEFTUP,LEFTDOWN,LEFTSIDEDOWN,LEFTSIDEUP,
            RIGHT,RIGHTUP,RIGHTDOWN,RIGHTSIDEDOWN,RIGHTSIDEUP}

public enum StandingState{STANDLEFT,STANDRIGHT,EATLEFT,EATRIGHT}

private MovingState movingState;
private StandingState standingState;

Ďalej si k týmto premenným pridáme prístupovej metódy:

public MovingState getMovingState() {
    return movingState;
}

public void setMovingState(MovingState state) {
    movingState=state;
}

public StandingState getStandingState() {
    return standingState;
}

public void setStandingState(StandingState state) {
    standingState=state;
}

Vložíme treba na koniec triedy, pod existujúce prístupové metódy. Triedu uložíme a môžeme zatvoriť. Výpis celej triedy teraz robiť nebudem, v prípade potreby sa pozrite do priloženého zdrojového kódu, ktorý je k stiahnutiu.

Čo potrebujeme ďalej? Vždy, keď používateľ klikne na obrazovku, potrebujeme určiť a nastaviť do akého smeru sa má sliepky natočiť. To nám zaistí naša trieda TurnManager.java, do ktorej som na tento účel pridal metódu turnChicken (int x, int y), jej argumenty sú súradnice miesta kľučku používateľa na obrazovku. Upravme našej triedu TurnManager.java do nižšie uvedenej podoby:

public class TurnManager {

    private MovingState movingState;
    private StandingState standingState;
    private Chicken chicken;
    private final Vector2 screenBoundEnd;
    private final Vector2 screenBoundBegin;
    private final int BEGINYCONSTANT;

    public TurnManager(GameScreen gameScreen,final int BEGINYCONSTANT) {
        final Vector2 demandedScreen=gameScreen.DEMANDED_SCREEN;
        this.screenBoundBegin=gameScreen.SCREEN_BOUND_BEGIN;
        this.screenBoundEnd=gameScreen.SCREEN_BOUND_END;
        this.BEGINYCONSTANT=BEGINYCONSTANT;
        this.chicken = new Chicken(screenBoundBegin,screenBoundEnd,demandedScreen,BEGINYCONSTANT);
        }

    public void turnChicken(int x,int y) {
        // x a y souradnice kliku
        float transformedPositionX = x - chicken.getPositionX() - chicken.getWidth()/2;
        float transformedPositionY = y - chicken.getPositionY() - chicken.getHeight()/2;
        double rt = transformedPositionY /  Math.sqrt( (Math.pow(transformedPositionX,2) + Math.pow(transformedPositionY,2)) );
        // Gdx.app.log("turnMng rt:", ""+rt);

        if ((rt < -0.9) && (transformedPositionX <= 0))
        {
            movingState=MovingState.LEFTUP;
            chicken.setMovingState(movingState);
            standingState=StandingState.STANDLEFT;
            chicken.setStandingState(standingState);
            //Gdx.app.log("turnMng state:",chicken.getMovingState().toString());
        }
        else if ((rt < -0.9) && (transformedPositionX > 0))
        {
            movingState=MovingState.RIGHTUP;
            chicken.setMovingState(movingState);
            standingState=StandingState.STANDRIGHT;
            chicken.setStandingState(standingState);
            //Gdx.app.log("turnMng state:",chicken.getMovingState().toString());
        }
        else if ((rt >= -0.9 ) && (rt <= -0.4) && (transformedPositionX > 0))
        {
            movingState=MovingState.RIGHTSIDEUP;
            chicken.setMovingState(movingState);
            standingState=StandingState.STANDRIGHT;
            chicken.setStandingState(standingState);
            //Gdx.app.log("turnMng state:",chicken.getMovingState().toString());
        }
        else if ((rt > -0.4)  && (rt < 0.4)  && (transformedPositionX > 0))
        {
            movingState=MovingState.RIGHT;
            chicken.setMovingState(movingState);
            standingState=StandingState.STANDRIGHT;
            chicken.setStandingState(standingState);
            //Gdx.app.log("turnMng state:",chicken.getMovingState().toString());
        }
        else if ((rt >= 0.4) && (rt <= 0.9 ) && (transformedPositionX > 0))
        {
            movingState=MovingState.RIGHTSIDEDOWN;
            chicken.setMovingState(movingState);
            standingState=StandingState.STANDRIGHT;
            chicken.setStandingState(standingState);
            //Gdx.app.log("turnMng state:",chicken.getMovingState().toString());
        }
        else if ((rt > 0.9) && (transformedPositionX <= 0))
        {
            movingState=MovingState.LEFTDOWN;
            chicken.setMovingState(movingState);
            standingState=StandingState.STANDLEFT;
            chicken.setStandingState(standingState);
            //Gdx.app.log("turnMng state:",chicken.getMovingState().toString());
        }
        else if ((rt > 0.9) && (transformedPositionX > 0))
        {
            movingState=MovingState.RIGHTDOWN;
            chicken.setMovingState(movingState);
            standingState=StandingState.STANDRIGHT;
            chicken.setStandingState(standingState);
            //Gdx.app.log("turnMng state:",chicken.getMovingState().toString());
        }
        else if ((rt <= 0.9 )  && (rt >= 0.4) && (transformedPositionX < 0))
        {
            movingState=MovingState.LEFTSIDEDOWN;
            chicken.setMovingState(movingState);
            standingState=StandingState.STANDLEFT;
            chicken.setStandingState(standingState);
            //Gdx.app.log("turnMng state:",chicken.getMovingState().toString());
        }
        else if ((rt < 0.4) &&  (rt > -0.4) && (transformedPositionX < 0))
        {
            movingState=MovingState.LEFT;
            chicken.setMovingState(movingState);
            standingState=StandingState.STANDLEFT;
            chicken.setStandingState(standingState);
            //Gdx.app.log("turnMng state:",chicken.getMovingState().toString());
        }
        else if ((rt <= -0.4) && (rt >= -0.9) && (transformedPositionX < 0))
        {
            movingState=MovingState.LEFTSIDEUP;
            chicken.setMovingState(movingState);
            standingState=StandingState.STANDLEFT;
            chicken.setStandingState(standingState);
            //Gdx.app.log("turnMng state:",chicken.getMovingState().toString());
        }
        else Gdx.app.log("turnMng:", "chybna hodnota rt");
    } //konec turnChicken

    public void setChickenDistance(int x, int y) {
        int clickedPositionX=x,clickedPositionY=y;
        float distanceX,distanceY;
        float chickenTailX = chicken.getPositionX() + chicken.getWidth();
        if (Math.abs(clickedPositionX - chicken.getPositionX()) <= Math.abs(clickedPositionX - chickenTailX))
            distanceX = clickedPositionX - chicken.getPositionX();
        else
                distanceX=clickedPositionX - chickenTailX;
        if(distanceX < screenBoundBegin.x-chicken.getPositionX())
            distanceX = screenBoundBegin.x-chicken.getPositionX();
        if(distanceX > screenBoundEnd.x- chickenTailX)
            distanceX=screenBoundEnd.x- chickenTailX;

        distanceY=clickedPositionY-(chicken.getPositionY()+chicken.getHeight());
        if(distanceY < (screenBoundBegin.y+BEGINYCONSTANT)-(chicken.getPositionY()+ chicken.getHeight()))
            distanceY=(screenBoundBegin.y+BEGINYCONSTANT)-(chicken.getPositionY()+ chicken.getHeight());
        if(distanceY > (screenBoundEnd.y-(chicken.getPositionY()+chicken.getHeight())) )
            distanceY = screenBoundEnd.y-(chicken.getPositionY()+chicken.getHeight());

        if(Math.abs(distanceX)<0.5f)
        {
            if(distanceX >=0) distanceX=0.5f;
                else distanceX=-0.5f;
        }

        if(Math.abs(distanceY)<0.5f)
        {
            if(distanceY >=0) distanceY=0.5f;
                else distanceY=-0.5f;
        }

        chicken.setDistanceX(distanceX);
        chicken.setDistanceY(distanceY);
    }


    public void setChickenSpeed() {
        float speedRatio = chicken.getWholeSpeed() / (Math.abs(chicken.getDistanceX()) + Math.abs(chicken.getDistanceY()));

        chicken.setDividedSpeedX(speedRatio*chicken.getDistanceX());
        chicken.setDividedSpeedY(speedRatio*chicken.getDistanceY());
    }

    public Chicken getChicken() {   // kvuli objMng
        return chicken;
        }
}

Pridáme importy, triedu uložíme a môžeme zatvoriť. Našou novú metódu turnChicken (int x, int y) nezabudneme zavolať. Otvoríme si triedu ObjectManager.java a do jej metódy receivePosition (int x, int y) pridáme volanie, takže výsledná podoba metódy bude:

public void receivePosition(int x,int y) { //souradnice z inputu
    turnMng.turnChicken(x, y);
    turnMng.setChickenDistance(x, y);
    turnMng.setChickenSpeed();
    chicken.setXPositionAchieved(false);
    chicken.setYPositionAchieved(false);
}

Týmto zavolaním nám metóda turnChicken (int x, int y) po kliku používateľa na obrazovku nastaví stavové premenné kurčaťa movingState a standingState, ktorými následne budeme riadiť premietačku. Nabudúce budeme pokračovať objasnením princípu funkcie turnChicken (int x, int y).


 

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 (12.54 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Java

 

Predchádzajúci článok
Programujeme Android hru - Assets load
Všetky články v sekcii
Programujeme Android hru
Preskočiť článok
(neodporúčame)
Programujeme Android hru - Grafika II
Článok pre vás napísal Jaroslav Polívka
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje převážně jazykům JAVA a C++
Aktivity