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 10 - Programujeme Android hru - Grafika I

V minulém díle našeho seriálu, Programujeme Android hru - Assets load, jsme načetli grafické zdroje pozadí a slepice.

V dnešním dvoj-díle je promítneme na obrazovku.

Půjde o velmi jednoduché promítání, slepice bude mít následující možnosti směrů chůzí a rotací:

  • chůze vlevo, rotace vlevo
  • chůze vpravo, rotace vpravo
  • chůze dolů, rotace vlevo
  • chůze dolů, rotace vpravo
  • chůze vzhůru, rotace vlevo
  • chůze vzhůru, rotace vpravo
  • chůze a rotace šikmo vpravo vzhůru
  • chůze a rotace šikmo vpravo dolů
  • chůze a rotace šikmo vlevo dolů
  • chůze a rotace šikmo vlevo vzhůru
Varianty pohybů a otočení - Programujeme Android hru

Ke každé možnosti je vázána sada dvou obrázků, které promítneme střídavě na obrazovku, abychom vytvořili alespoň základní iluzi chůze slepice.

Náš kód vybere jednu z možností na základě výpočtu, který objasním dále. Nesmím zapomenout zdůraznit, že možnosti chůzí pouze čistě vlevo, vpravo, vzhůru a dolů málokdy existují. Slepice se většinou pohybuje více či méně po obou osách současně - tedy šikmo. My to ale uděláme tak, že pohyby v mírně šikmých směrech budeme považovat za pohyby čistě vlevo, vpravo, dolů nebo vzhůru. Jinak řečeno, při mírně šikmých pohybech nebudeme slepici naklánět vůbec.

Různé možnosti promítnutí podle aktuální pozice slepice a kliku uživatele na obrazovku nejsou ničím jiným, než vlastnostmi naší slepice. Otevřeme si třídu Chicken.java a pomocí výčtových konstant tyto vlastnosti slepici přidáme. Pod stávající proměnné si přidáme další:

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;

Dále si k těmto proměnným přidáme přístupové metody:

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 je třeba na konec třídy, pod stávající přístupové metody. Třídu uložíme a můžeme zavřít. Výpis celé třídy nyní dělat nebudu, v případě potřeby se podívejte do přiloženého zdrojového kódu, který je ke stažení.

Co potřebujeme dále? Vždy, když uživatel klikne na obrazovku, potřebujeme určit a nastavit do jakého směru se má slepice natočit. To nám zajistí naše třída TurnManager.java, do které jsem pro tento účel přidal metodu turnChicken(int x,int y), jejími argumenty jsou souřadnice místa kliku uživatele na obrazovku. Upravme naší třídu TurnManager.java do níže uvedené 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;
        }
}

Přidáme importy, třídu uložíme a můžeme zavřít. Naší novou metodu turnChicken(int x, int y) nezapomeneme zavolat. Otevřeme si třídu ObjectManager.java a do její metody receivePosition(int x,int y) přidáme volání, takže výsledná podoba metody 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 zavoláním nám metoda turnChicken(int x,int y) po kliku uživatele na obrazovku nastaví stavové proměnné kuřete movingState a standingState, kterými následně budeme řídit promítačku.

Příště, Programujeme Android hru - Grafika II, budeme pokračovat objasněním principu funkce turnChicken (int x,int y).


 

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

 

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