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 7 - Programujeme Android hru - Rozdělení hry do tříd I

Z minulé lekce kurzu o programování hry pro Android v Javě, Programujeme Android hru - Úvaha nad obrazovkami, máme vytvořené prázdné třídy.

Dnes a příště do nich budeme doplňovat. Nejprve si však ještě v balíčku com.wackychic­ken.managers vytvoříme novou třídu TurnManager.java, která se nám bude starat nejen o pohyb a natáčení slepice právě tím směrem, kterým půjde. Třídu zatím ponecháme od Eclipse ve výchozím stavu, tzn. prázdnou a s prázdným konstruktorem.

Nyní již pojďme psát kód do třídy, která bude reprezentovat naší hloupou slepici. Otevřeme si třídu Chicken.java a vyplníme následujícím kódem:

public class Chicken {

    private float wholeSpeed,dividedSpeedX,dividedSpeedY,positionX,positionY,distanceX,distanceY;
    private final float WIDTH=115,HEIGHT=90;
    private final int BEGINYCONSTANT;
    private final Vector2 SCREEN_BOUND_BEGIN,SCREEN_BOUND_END,DEMANDED_SCREEN;
    private boolean xPositionAchieved,yPositionAchieved;

    public Chicken(final Vector2 screenBoundBegin, final Vector2 screenBoundEnd,
        final Vector2 demandedScreen, final int BEGINYCONSTANT) {

        this.wholeSpeed = 50;
        this.dividedSpeedX=dividedSpeedY=0;
        this.xPositionAchieved=this.yPositionAchieved=true;
        this.positionX=screenBoundBegin.x+200;
        this.positionY=screenBoundBegin.y+BEGINYCONSTANT+(demandedScreen.y-BEGINYCONSTANT)/2 -(HEIGHT/2);
        this.BEGINYCONSTANT=BEGINYCONSTANT;
        this.SCREEN_BOUND_BEGIN=screenBoundBegin;
        this.SCREEN_BOUND_END=screenBoundEnd;
        this.DEMANDED_SCREEN=demandedScreen;
    }

    public void update(float delta) {
        checkBorders(); //druha kotva ohraniceni, kdyby byla spatne spocitana distance a kvuli
            //BEGINYCONSTANT
        if (!xPositionAchieved) {
            if (distanceX<0) { // kdyz je distance zaporna, tak dividedSpeed take
                positionX+= dividedSpeedX *delta;
                distanceX+=((-1)*dividedSpeedX *delta);
                if (dis anceX>0) xPositionAchieved=true;
            }

            if distanceX>0) {
                positionX+= dividedSpeedX *delta;
                distanceX+=((-1)*dividedSpeedX *delta);
                if(distanceX<0)xPositionAchieved=true;
            }
        }

        if (!yPositi nAchieve ) {
            if ( istanceY<0) {
                positionY+= dividedSpeedY *delta;
                distanceY+=((-1)*dividedSpeedY *delta);
                if(distanceY>0)yPositionAchieved=true;
            }

        if(distanceY>0) {
                positionY+= dividedSpeedY*delta;
                distanceY+=((-1)* dividedSp edY *delta);
            if (distanceY<0) yPositionAchieved=true;
            }

        }

        if(isStanding())
        resetWholeSpeed();

    } // konec update

    public float getWholeSpeed() {
        return wholeSpeed;
    }

    public void incrWholeSpeed(float speed) {
        this.wholeSpeed+=speed;
    }

    public void resetWholeSpeed() {
        this.wholeSpeed=50;
    }

    public void setXPositionAchieved(boolean achieved) {
        xPositionAchieved=achieved;
    }

    public void setYPositionAchieved(boolean achieved) {
        yPositionAchieved=achieved;
    }

    public boolean isStanding() {
        return (xPositionAchieved&&yPositionAchieved);
    }

    private void checkBorders() {

        if(positionX<=SCREEN_BOUND_BEGIN.x)
        {
            positionX=SCREEN_BOUND_BEGIN.x;
        }

        if(positionX+WIDTH>=SCREEN_BOUND_END.x)
        {
            positionX=SCREEN_BOUND_END.x-WIDTH;
        }

        if(positionY+HEIGHT<SCREEN_BOUND_BEGIN.y+BEGINYCONSTANT)
        {
            positionY=SCREEN_BOUND_BEGIN.y+BEGINYCONSTANT-HEIGHT;
        }

        if(positionY+HEIGHT>SCREEN_BOUND_END.y)
        {
            positionY=SCREEN_BOUND_END.y-HEIGHT;
        }

    }

    public float getPositionX() {
        return positionX;
    }

    public float getPositionY() {
        return positionY;
    }

    public float getWidth() {
        return WIDTH;
    }

    public float getHeight() {
        return HEIGHT;
    }

    public float getDistanceX() {
        return distanceX;
    }

    public float getDistanceY() {
        return distanceY;
    }

    public void setDistanceX(float x) {
        distanceX=x;
    }

    public void setDistanceY(float y) {
        distanceY=y;
    }

    public void setDividedSpeedX(float X) {
        dividedSpeedX = X;
    }

    public void setDividedSpeedY(float Y) {
        dividedSpeedY = Y;
    }

}

Přidáme importy a uložíme. Třídu stručně popíši, o všech proměnných nebo konstantách se nebudu zmiňovat, protože jejich názvem je naznačeno, k čemu jsou určeny. Slepice bude mít nějakou rychlost, kterou se bude pohybovat po obrazovce (wholespeed). Aby chodila po obou osách x a y rovnoměrně, je nutné tuto celkovou rychlost rozložit (dividedSpeedX, dividedSpeedY) dle poměru vzdáleností os, které má naše hloupé kuře urazit. BEGINYCONSTANT je vytyčení hranice na y souřadnici, aby slepice chodila jen po trávě. Konstanty vektorů SCREEN_BOUND_BE­GIN,SCREEN_BO­UND_END,DEMAN­DED_SCREEN již známe a slouží k vytyčení virtuální obrazovky. Pravdivostní proměnné xPositionAchieved a yPositionAchieved uchovávají informaci o tom, zda slepice dosáhla požadovaných souřadnic. Metoda update() přičítá do proměnných positionX a Y a tím dává kuře na obrazovce do pohybu. Metodu checkBorders() jsem popsal v kódu komentářem. Nakonec máme přístupové metody (getters and setters) pro získání nebo nastavení hodnot proměnných.

Otevřeme naší prázdnou třídu TurnManager.java, kterou jsme před chvílí vytvořili a vyplníme jí kódem:

public class TurnManager {

    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 setChickenDistance(int x, int y) {
        int clickedPositionX=x,clickedPositionY=y;
        float distanceX,distanceY;
        float chickenTailX = chicken.getPositionX() + chicken.getWidth(); //pozice chicken.x a y jsou floaty
                                // je do nich pricitana delta

        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 objectManager
        return chicken;
    }
}

Přidáme importy a uložíme. Vyběhnou na nás tři chyby, že vektory obrazovky ve třídě GameScreen.java nejsou viditelné:

Vektory obrazovky dáme public - Programujeme Android hru

Otevřeme si tedy tuto třídu a změníme v ní řádek z:

private final Vector2 DEMANDED_SCREEN,SCREEN_BOUND_BEGIN,SCREEN_BOUND_END;

na:

public final Vector2 DEMANDED_SCREEN,SCREEN_BOUND_BEGIN,SCREEN_BOUND_END;

a změnu uložíme. Zatím neřešíme natáčení slepice do požadovaného směru, metoda setChickenDis­tance() vypočítává vzdálenost mezi aktuálními souřadnicemi slepice a souřadnicemi dotyku uživatele na obrazovce. Do výpočtu se musí zohlednit, kam uživatel klikl vůči aktuální pozici slepice, tedy zda se (ne)budou do vzdálenosti přičítat i její rozměry. Metodu setChickenSpeed() jsem již popsal výše, když jsem popisoval rozdělení celé rychlosti v proměnné wholeSpeed do proměnných dividedSpeedX a dividedSpeedY.

Pro dnešek je to vše.

Pokračovat budeme příště, Programujeme Android hru - Rozdělení hry do tříd II.


 

Předchozí článek
Programujeme Android hru - Úvaha nad obrazovkami
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 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