7. díl - Programujeme Android hru - Rozdělení hry do tříd I

Java Android Programujeme hru Programujeme Android hru - Rozdělení hry do tříd I

Z minulé lekce kurzu o programování hry pro Android v Javě 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

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ě.


 

  Aktivity (3)

Článek pro vás napsal Jaroslav Polívka
Avatar
Autor se věnuje převážně jazykům JAVA a C++

Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!


 



 

 

Komentáře

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.

Zatím nikdo nevložil komentář - buď první!