NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!
NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.

Lekce 12 - Programujeme Android hru - Krmení I

Vítejte v dalším díle našeho kurzu. Z minulého dílu, Programujeme Android hru - Grafika II, máme naší hru ve stavu, kdy jde slepice na místo kliknutí.

Dnes začneme s obsluhou a promítáním krmiva, kterým budeme naší hloupou slepici krmit. Budeme k tomu potřebovat dvě třídy. Podle jedné se nám vytvoří instance našeho krmení. Druhá nám zjistí, kde je právě volné místo pro umístění onoho krmení, tedy tam, kde zrovna nestojí naše hloupé kuře.

Začneme druhou zmíněnou třídou. V balíčku com.wackychic­ken.managers si vytvoříme novou třídu PosFinder.java a vyplníme ji do následujícího tvaru:

package com.wackychicken.managers;

import java.util.Random;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.wackychicken.screens.GameScreen;

public class PosFinder {

    private final Vector2 demandedScreen,screenBoundBegin,screenBoundEnd;
    private final int beginConstant; //zacatek travy
    private Random random;
    private float coefficient;
    public Rectangle area[];
    private Rectangle receivedRectangle;
    private float [] generatedPosition;
    private float width,height;

    public PosFinder(GameScreen gameScreen,final int beginConstant,Rectangle receivedRectangle,float width,float height) {
        this.demandedScreen=gameScreen.DEMANDED_SCREEN;
        this.screenBoundBegin=gameScreen.SCREEN_BOUND_BEGIN;
        this.screenBoundEnd=gameScreen.SCREEN_BOUND_END;
        this.beginConstant=beginConstant;
        this.coefficient=1.25f;
        this.width=width;
        this.height=height;
        this.random = new Random();

        this.area=new Rectangle[4];
        for(int i=0;i<area.length;i++)
            area[i]=new Rectangle();

        this.receivedRectangle=receivedRectangle; //chickenPositionX,chickenPositionY,chickenWidth,chickenHeight
        this.generatedPosition=new float[2];
    }

    public float [] findOutFreePosition(float positionX,float positionY) {
        receivedRectangle.setPosition(positionX, positionY);
        if( !((receivedRectangle.getY() - screenBoundBegin.y<=beginConstant + height*coefficient)&&//nepravda podminka a i c
(receivedRectangle.getX() - screenBoundBegin.x <=  width*coefficient)) &&
!((screenBoundEnd.y - receivedRectangle.getY()-receivedRectangle.getHeight() <= height*coefficient)&& //nepravda podminka b i c
(receivedRectangle.getX() - screenBoundBegin.x <=  width*coefficient)) &&
!((receivedRectangle.getY() - screenBoundBegin.y<=beginConstant + height*coefficient)&&//nepravda podminka a i d
(screenBoundEnd.x - receivedRectangle.getX() -receivedRectangle.getWidth() <=  width*coefficient)) &&
!((screenBoundEnd.y - receivedRectangle.getY()-receivedRectangle.getHeight() <= height*coefficient)&& //nepravda podminka b i d
(screenBoundEnd.x - receivedRectangle.getX() -receivedRectangle.getWidth() <=  width*coefficient))      )
        {
            if(receivedRectangle.getY() - screenBoundBegin.y<=beginConstant + height*coefficient ) //podminka a
            generatePosition('a');

            else if(screenBoundEnd.y - receivedRectangle.getY()-receivedRectangle.getHeight() <= height*coefficient)//podminka b
                generatePosition('b');
            else if(receivedRectangle.getX() - screenBoundBegin.x <=  width*coefficient)
                generatePosition('c');
            else if(screenBoundEnd.x - receivedRectangle.getX() -receivedRectangle.getWidth() <=  width*coefficient)
                generatePosition('d');
            else
                generatePosition('e');
        }

        else if((receivedRectangle.getY() - screenBoundBegin.y<=beginConstant + height*coefficient)&& //podminka a i C
    (receivedRectangle.getX() - screenBoundBegin.x <=  width*coefficient) )
            generatePosition('f');

        else if((screenBoundEnd.y - receivedRectangle.getY()-receivedRectangle.getHeight() <= height*coefficient)&& //podminka b i C
    (receivedRectangle.getX() - screenBoundBegin.x <=  width*coefficient))
            generatePosition('g');

        else if((receivedRectangle.getY() - screenBoundBegin.y<=beginConstant + height*coefficient)&&   //podminka a i d
    (screenBoundEnd.x - receivedRectangle.getX() -receivedRectangle.getWidth() <=  width*coefficient))
            generatePosition('h');

        else if((screenBoundEnd.y - receivedRectangle.getY()-receivedRectangle.getHeight() <= height*coefficient)&& //podminka b i d
    (screenBoundEnd.x - receivedRectangle.getX() -receivedRectangle.getWidth() <=  width*coefficient))
            generatePosition('i');

        return generatedPosition;
    }

    private void generatePosition(char chickenPlacement) {
        if(chickenPlacement =='a')
        {   //zde je drobna uprava,kdyz je kure moc nahore vzdalenost > (ch.height*0.5) od scrBgn+bgnCnst
            //pak vyber vzdy nejvetsi oblast O
        area[1].set(screenBoundBegin.x,screenBoundBegin.y+beginConstant-height,(receivedRectangle.getX()-screenBoundBegin.x),
(receivedRectangle.getY()+receivedRectangle.getHeight())-(screenBoundBegin.y+beginConstant-height));

        area[0].set(screenBoundBegin.x,(receivedRectangle.getY()+receivedRectangle.getHeight()),
demandedScreen.x,screenBoundEnd.y-(receivedRectangle.getY()+receivedRectangle.getHeight()) );

        area[2].set(receivedRectangle.getX()+receivedRectangle.getWidth(),screenBoundBegin.y+beginConstant-height,
screenBoundEnd.x-receivedRectangle.getX()-receivedRectangle.getWidth(),
receivedRectangle.getY()+receivedRectangle.getHeight()-(screenBoundBegin.y+beginConstant-height));

        area[3].set(0,0,0,0);

        if(receivedRectangle.getY()+receivedRectangle.getHeight()-(screenBoundBegin.y+beginConstant)
< receivedRectangle.getHeight()*0.5f) //kdyz je kure moc nahore vyber nejvetsi oblast
{
            setCoordinate(1);
        }

        else
            setCoordinate(3);
            //Gdx.app.log("posFinder:", "podminka a");
        }

        else if(chickenPlacement =='b') {

            area[0].set(screenBoundBegin.x,screenBoundBegin.y+beginConstant,
            demandedScreen.x,receivedRectangle.getY()-(screenBoundBegin.y+beginConstant));

            area[1].set(screenBoundBegin.x,receivedRectangle.getY(),
receivedRectangle.getX()-screenBoundBegin.x,screenBoundEnd.y-receivedRectangle.getY());

            area[2].set(receivedRectangle.getX()+receivedRectangle.getWidth(),receivedRectangle.getY(),
screenBoundEnd.x-(receivedRectangle.getX()+receivedRectangle.getWidth()),screenBoundEnd.y-receivedRectangle.getY());

            area[3].set(0,0,0,0);
            setCoordinate(3);
            //Gdx.app.log("posFinder:", "podminka b");
        }

        else if(chickenPlacement =='c')
        {
            area[0].set(screenBoundBegin.x,screenBoundBegin.y+beginConstant,
            demandedScreen.x,receivedRectangle.getY()-(screenBoundBegin.y+beginConstant));

            area[1].set(receivedRectangle.getX()+receivedRectangle.getWidth(),receivedRectangle.getY(),
screenBoundEnd.x-(receivedRectangle.getX()+receivedRectangle.getWidth()),receivedRectangle.getHeight());

            area[2].set(screenBoundBegin.x,receivedRectangle.getY()+receivedRectangle.getHeight(),
demandedScreen.x,screenBoundEnd.y-(receivedRectangle.getY()+receivedRectangle.getHeight()));

            area[3].set(0,0,0,0);
            setCoordinate(3);
            //Gdx.app.log("posFinder:", "podminka c");
        }

        else if(chickenPlacement =='d')
        {
            area[0].set(screenBoundBegin.x,screenBoundBegin.y+beginConstant,
demandedScreen.x,receivedRectangle.getY()-(screenBoundBegin.y+beginConstant));

            area[1].set(screenBoundBegin.x,receivedRectangle.getY(),
receivedRectangle.getX()-screenBoundBegin.x,receivedRectangle.getHeight());

            area[2].set(screenBoundBegin.x,receivedRectangle.getY()+receivedRectangle.getHeight(),
demandedScreen.x,screenBoundEnd.y-(receivedRectangle.getY()+receivedRectangle.getHeight()));

            area[3].set(0,0,0,0);

            setCoordinate(3);
            //Gdx.app.log("posFinder:", "podminka d");
        }

        else if(chickenPlacement =='e')
        {
            area[0].set(screenBoundBegin.x,screenBoundBegin.y+beginConstant,
            demandedScreen.x,receivedRectangle.getY()-(screenBoundBegin.y+beginConstant));

            area[1].set(screenBoundBegin.x,receivedRectangle.getY(),
            receivedRectangle.getX()-screenBoundBegin.x,receivedRectangle.getHeight());

                area[2].set(receivedRectangle.getX()+receivedRectangle.getWidth(),receivedRectangle.getY(),
screenBoundEnd.x-(receivedRectangle.getX()+receivedRectangle.getWidth()),receivedRectangle.getHeight());

            area[3].set(screenBoundBegin.x,receivedRectangle.getY()+receivedRectangle.getHeight(),
demandedScreen.x,screenBoundEnd.y-(receivedRectangle.getY()+receivedRectangle.getHeight()));

            setCoordinate(4);
            //Gdx.app.log("posFinder:", "ostatni prostor");
        }


        else if(chickenPlacement =='f')
        {
            area[0].set(receivedRectangle.getX()+receivedRectangle.getWidth(),screenBoundBegin.y+beginConstant-height,
(screenBoundEnd.x-(receivedRectangle.getX()+receivedRectangle.getWidth()) ),
((receivedRectangle.getY()+receivedRectangle.getHeight())-(screenBoundBegin.y+beginConstant-height)));

            area[1].set(screenBoundBegin.x,receivedRectangle.getY()+receivedRectangle.getHeight(),
demandedScreen.x,screenBoundEnd.y-(receivedRectangle.getY()+receivedRectangle.getHeight()));

            area[2].set(0,0,0,0);
            area[3].set(0,0,0,0);

            setCoordinate(2);
            //Gdx.app.log("posFinder:", "podminka a i c");
        }

        else if(chickenPlacement =='g')
        {
                area[0].set(screenBoundBegin.x,screenBoundBegin.y+beginConstant,demandedScreen.x,
receivedRectangle.getY()-(screenBoundBegin.y+beginConstant));

                        area[1].set(receivedRectangle.getX()+receivedRectangle.getWidth(),receivedRectangle.getY(),
screenBoundEnd.x-(receivedRectangle.getX()+receivedRectangle.getWidth()),screenBoundEnd.y-receivedRectangle.getY());

            area[2].set(0,0,0,0);
            area[3].set(0,0,0,0);

            setCoordinate(2);
            //Gdx.app.log("posFinder:", "podminka b i c");
        }

        else if(chickenPlacement =='h')
        {
            area[0].set(screenBoundBegin.x,screenBoundBegin.y+beginConstant-height,receivedRectangle.getX()- screenBoundBegin.x,
((receivedRectangle.getY()+receivedRectangle.getHeight())-(screenBoundBegin.y+beginConstant-height)));

                        area[1].set(screenBoundBegin.x,receivedRectangle.getY()+receivedRectangle.getHeight(),demandedScreen.x,
screenBoundEnd.y-(receivedRectangle.getY()+receivedRectangle.getHeight()));

            area[2].set(0,0,0,0);
            area[3].set(0,0,0,0);

            setCoordinate(2);
            //Gdx.app.log("posFinder:", "podminka a i d");
        }

        else if(chickenPlacement =='i')
        {
            area[0].set(screenBoundBegin.x,screenBoundBegin.y+beginConstant,demandedScreen.x,
receivedRectangle.getY()-(screenBoundBegin.y+beginConstant));

            area[1].set(screenBoundBegin.x,receivedRectangle.getY(),
receivedRectangle.getX()-screenBoundBegin.x,screenBoundEnd.y-receivedRectangle.getY());

            area[2].set(0,0,0,0);
            area[3].set(0,0,0,0);
            setCoordinate(2);
            //Gdx.app.log("posFinder:", "podminka b i d");
        }

    }

    private void setCoordinate(int areasSum) {
        int i = random.nextInt(areasSum);
        int rangeX=(int)(area[i].x+area[i].width-area[i].x-width);  // sychrovka minimum pro random musí být 1
        int rangeY=(int)(area[i].y+area[i].height-area[i].y-height); // sychrovka minimum pro random musí být 1
        if(rangeX<1)
            rangeX=1;
        if(rangeY<1)
            rangeY=1;
        generatedPosition[0] = random.nextInt(rangeX)+area[i].x;
        generatedPosition[1] = random.nextInt(rangeY)+area[i].y;
    }

}

Třídu si uložíme, vypsal jsem i importy, takže přidávat je nemusíme. Obě třídy si vysvětlíme v druhé části tohoto dílu. Pojďme dále a v balíčku com.wackychic­ken.gameobjec­ts si vytvoříme novou třídu Food.java a překopírujeme do následujícího tvaru:

package com.wackychicken.gameobjects;

import com.badlogic.gdx.math.Rectangle;
import com.wackychicken.managers.PosFinder;
import com.wackychicken.screens.GameScreen;

public class Food {
    private final float WIDTH=32,HEIGHT=32;
    private float positionX,positionY;
    private float lifeTime,newLifeTime,counter;
    private Rectangle rectForOverlap;
    private int mask;

    private Rectangle chickenRectangle;
    private PosFinder posFinder;
    private float []generatedPosition;
    private Chicken chicken;
    public enum Type {WHEAT,CORN,BERRY,CARROT}
    private boolean wasClicked,wasCounted;

    public Food(GameScreen gameScreen,Chicken chicken,final int BEGINYCONSTANT) {
        this.lifeTime=this.newLifeTime=10;
        this.generatedPosition=new float[2];
        this.chicken=chicken;
        this.chickenRectangle=new Rectangle(chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
        this.wasClicked=this.wasCounted=false;
        this.counter=0;
        this.mask=0;

        posFinder=new PosFinder(gameScreen,BEGINYCONSTANT,chickenRectangle,WIDTH,HEIGHT);
        generatedPosition=posFinder.findOutFreePosition(chicken.getPositionX(),chicken.getPositionY());
        this.positionX=generatedPosition[0];
        this.positionY=generatedPosition[1];
        this.rectForOverlap = new Rectangle(positionX,positionY,this.WIDTH,this.HEIGHT);
    }

    public void update(float delta) {
        rectForOverlap.set(positionX, positionY, this.WIDTH, this.HEIGHT);
        if(lifeTime<=0)
        {
            generatedPosition=posFinder.findOutFreePosition(chicken.getPositionX(),chicken.getPositionY());
            positionX=generatedPosition[0];
            positionY=generatedPosition[1];
            wasClicked=wasCounted=false;
            lifeTime=newLifeTime;
            updateMask();
        }
        lifeTime-=delta;
        updateNewLifeTime(delta);
    }

    private void updateNewLifeTime(float delta){ //postupne snizovani pocatecni hodnoty lifeTime foodu z 10 na 5
        if(counter+delta>110)
        {
            newLifeTime-=1;
            if(newLifeTime-delta<4)newLifeTime=4;   //minimalni lifetime foodu je 4
            counter=0;
        }
        else
            counter+=delta;
    }

    public void restart() {
        this.lifeTime=this.newLifeTime=10;
        this.chickenRectangle.set(chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight());
        this.wasClicked=this.wasCounted=false;
        this.counter=0;
        this.mask=0;
        generatedPosition=posFinder.findOutFreePosition(chicken.getPositionX(),chicken.getPositionY());
        this.positionX=generatedPosition[0];
        this.positionY=generatedPosition[1];
        this.rectForOverlap.set(positionX,positionY,this.WIDTH,this.HEIGHT);
    }

    public PosFinder getPosFinder() {
        return posFinder;
    }

    public float getPositionX() {
        return positionX;
    }

    public float getPositionY() {
        return positionY;
    }

    public float getWidth() {
        return WIDTH;
    }

    public float getHeight() {
        return HEIGHT;
    }

    public float getLifeTime() {
        return lifeTime;
    }

    public void setLifeTime(float time) {
        this.lifeTime=time; //kvuli objectMng - po animaci chtit novou pozici foodu
    }

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

    public Rectangle getRectForOverlap() { //kvuli OverlapsManager
        return rectForOverlap;
    }

    public void setWasClicked(boolean x) { //kvuli OverlapsManager
        wasClicked=x;
    }

    public boolean getWasClicked(){ //kvuli OverlapsManager
        return wasClicked;
    }

    public void setWasCounted(boolean x) { //kvuli OverlapsManager
        wasCounted=x;
    }

    public boolean getWasCounted() { //kvuli OverlapsManager
        return wasCounted;
    }

    public int getMask() {
        return this.mask;
    }

    private void updateMask() {
        mask++;
        if(mask>3)
            mask=0;
    }
}

Třídu si uložíme, opět jsem vypsal i importy, takže nepřidáváme. Omluvte dnešní dlouhý kód a tím pádem i strohý díl. Pro dnešek nám opravdu stačí, když správně překopírujeme obsah tříd a umístíme je do správných balíčků.

Princip si vysvětlíme příště, Programujeme Android hru - Krmení II. Motivací pro nás může být zjištění, že v dalších dílech přidáme už jen jednu třídu, budeme se tedy blížit k cíli.


 

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

 

Předchozí článek
Programujeme Android hru - Grafika II
Všechny články v sekci
Programujeme Android hru
Přeskočit článek
(nedoporučujeme)
Programujeme Android hru - Krmení II
Článek pro vás napsal Jaroslav Polívka
Avatar
Uživatelské hodnocení:
Ještě nikdo nehodnotil, buď první!
Autor se věnuje převážně jazykům JAVA a C++
Aktivity