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 13 - Programujeme Android hru - Krmení II

Zdravím vás v dalším díle našeho kurzu. V tom minulém, Programujeme Android hru - Krmení I, jsme navenek nepřidali žádnou funkcionalitu, pouze jsme přidali dvě třídy.

Dnes si ve stručnosti popíšeme jejich princip a rozjedeme promítání krmení na obrazovku.

Začneme proměnnými třídy PosFinder.java, screen konstanty dobře známe, beginConstant též známe a je okomentovaná. Random je jasná, slouží k vylosování souřadnic. Instance třídy PosFinder.java musí při každém hledání volného místa mj. znát:

  • aktuální polohu kuřete
  • rozměry kuřete
  • rozměry krmiva

První dvě položky ukládáme do proměnné receivedRectangle a do proměnných width, height rozměry krmiva.

Dvouprvkové float pole generatedPosition je konečným výstupem a obsahuje vylosované vhodné souřadnice, na které je možné krmení v daný okamžik umístit.

Pole area[] inicializujeme v konstruktoru kódem:

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

Tedy jako pole čtyř obdélníků, proč zrovna tak? Na to více než slova odpoví obrázky:

PodminkaAC - Programujeme Android hru

PodminkaAB - Programujeme Android hru

PodminkaE - Programujeme Android hru

Ano, plochu, po které může naše hloupá slepice chodit, jsme si rozdělili na 4 oblasti. Ať slepice půjde po našem "jevišti" kamkoli, vždy vzniknou 2, 3 nebo 4 oblasti (obdélníky), které jsou vhodné pro umístění krmení.

Jak to funguje?

Souřadnice krmiva mají nějakou dobu životnosti, která je dána odčítáním proměnné lifeTime instance třídy Food.java. Vždy, když je proměnná lifeTime <= 0, zavolá se metoda findOutFreePo­sition(...), která dle aktuální pozice kuřete stanoví, zda se utvořily 2, 3, nebo 4 zmíněné oblasti (obdélníky). Korekce pomocí proměnné coefficient zabezpečí, aby oblasti vznikly teprve tehdy, až pro ně bude existovat větší místo, než je velikost krmiva, tedy minimálně 32*1,25 px, abychom měli z čeho losovat.

Podle vzniklých oblastí metoda findOutFreePo­sition(...) zavolá s příslušným char argumentem metodu generatePositi­on(...), která dle tohoto argumentu vybere konkrétní oblasti a nastaví je na konkrétní rozměry, dle aktuální pozice kuřete. Posledním úkolem metody generatePositi­on(...) je zavolání metody setCoordinate(...), která vylosuje oblast a souřadnice, na kterých se má krmivo objevit a nastaví tyto souřadnice do pole generatedPosition. Řízení se vrátí metodě findOutFreePo­sition(...), která vrací pole s požadovanými souřadnicemi.

Třída Food.java

Instance bude mít nějaké rozměry, dále souřadnice, kde se na obrazovce nachází (WIDTH, HEIGHT, positionX, positionY). Proměnnou lifeTime jsem již objasnil výše. Ještě k ní dodám, že je inicializovaná pomocí newLifeTime, protože postupně chceme snižovat dobu životnosti krmiva a tím zvyšovat obtížnost hry. Do counter se postupně přičítá delta a až součet dosáhne určité hodnoty, vyvolá to snížení hodnoty newLifeTime. Proměnná rectForOverlap bude sloužit k detekci kolize krmiva a kuřete. Vždy při promítnutí krmiva na nových souřadnicích se zobrazí jiný obrázek, toto přepnutí zajistí proměnná mask.

Řádek s výčtovými konstantami enum Type {WHEAT,CORN,BERRY,CARROT} jsem odstranil (vykomentoval). Pravdivostní wasClicked a wasCounted slouží k tomu, aby vyhodnocení kliknutí na krmivo a započítání bodu bylo provedeno jen jednou.

Promítání krmení

Co musíme splnit pro promítnutí krmiva?

  • načíst potřebné obrázky krmení ve třídě Assets.java
  • vytvořit instanci dle třídy Food.java a volat metodu update(...) této instance
  • renderovat instanci

Do složky assets přidáme 4 soubory obrázků krmení, jsou součástí balíku ke stažení dole. Ve třídě AssetManager.java tyto obrázky načteme do paměti, výsledná podoba třídy:

public class AssetManager {
    public static Texture background;
    public static TextureRegion rBackground;
    public static Texture left1,left2,leftSideDown1,leftSideDown2,leftSideUp1,leftSideUp2;
    public static Texture right1,right2,rightSideDown1,rightSideDown2,rightSideUp1,rightSideUp2;
    public static Texture carrot,autumn,corn,wheat;

    public static Texture standLeft12;          //na animaci oka
    public static TextureRegion rStandLeft1,rStandLeft2;    //na animaci oka
    public static Animation standLeftAnime;         //na animaci oka

    public static Texture standRight12;         //na animaci oka
    public static TextureRegion rStandRight1,rStandRight2;  //na animaci oka
    public static Animation standRightAnime;        //na animaci oka


    public static void load() {
        background = new Texture(Gdx.files.internal("background.png"));
        background.setFilter(TextureFilter.Nearest, TextureFilter.Nearest); //proti rozmazavani pri roztahovani

        rBackground = new TextureRegion(background,0,0,800,500);
        rBackground.flip(false, true);

        carrot = new Texture(Gdx.files.internal("carrot.png"));
        carrot.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);
        autumn = new Texture(Gdx.files.internal("autumn.png"));
        autumn.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);
        corn = new Texture(Gdx.files.internal("corn.png"));
        corn.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);
        wheat = new Texture(Gdx.files.internal("wheat.png"));
        wheat.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);

        left1 = new Texture(Gdx.files.internal("left1.png"));
        left1.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);

        left2 = new Texture(Gdx.files.internal("left2.png"));
        left2.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);

        leftSideDown1 = new Texture(Gdx.files.internal("leftsidedown1.png"));
        leftSideDown1.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);

        leftSideDown2 = new Texture(Gdx.files.internal("leftsidedown2.png"));
        leftSideDown2.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);

        leftSideUp1 = new Texture(Gdx.files.internal("leftsideup1.png"));
        leftSideUp1.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);

        leftSideUp2 = new Texture(Gdx.files.internal("leftsideup2.png"));
        leftSideUp2.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);

        right1 = new Texture(Gdx.files.internal("right1.png"));
        right1.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);

        right2 = new Texture(Gdx.files.internal("right2.png"));
        right2.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);

        rightSideDown1 = new Texture(Gdx.files.internal("rightsidedown1.png"));
        rightSideDown1.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);

        rightSideDown2 = new Texture(Gdx.files.internal("rightsidedown2.png"));
        rightSideDown2.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);

        rightSideUp1 = new Texture(Gdx.files.internal("rightsideup1.png"));
        rightSideUp1.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);

        rightSideUp2 = new Texture(Gdx.files.internal("rightsideup2.png"));
        rightSideUp2.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);


        /* zacatek obsluhy animace mrkani oka, kdyz kure stoji doleva nebo doprava */
        standLeft12 = new Texture(Gdx.files.internal("standleft12.png"));
        standLeft12.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);
        rStandLeft1 = new TextureRegion(standLeft12,0,0,115,90);
        rStandLeft1.flip(false, false);
        rStandLeft2 = new TextureRegion(standLeft12,115,0,115,90);
        rStandLeft2.flip(false, false);
        TextureRegion[]rStandLeft12={rStandLeft1,rStandLeft1,rStandLeft1,
        rStandLeft1,rStandLeft1,rStandLeft2};
        standLeftAnime = new Animation(0.2f, rStandLeft12);
        standLeftAnime.setPlayMode(Animation.PlayMode.LOOP_PINGPONG);

        standRight12 = new Texture(Gdx.files.internal("standright12.png"));
        standRight12.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);
        rStandRight1 = new TextureRegion(standRight12,0,0,115,90);
        rStandRight1.flip(false, false);
        rStandRight2 = new TextureRegion(standRight12,115,0,115,90);
        rStandRight2.flip(false, false);
        TextureRegion[]rStandRight12={rStandRight1,rStandRight1,rStandRight1,
        rStandRight1,rStandRight1,rStandRight2};
        standRightAnime =  new Animation(0.2f, rStandRight12);
        standRightAnime.setPlayMode(Animation.PlayMode.LOOP_PINGPONG);
        /* konec obsluhy animace mrkani oka, kdyz kure stoji doleva nebo doprava */

    }
}

Vytvoření instance dle třídy Food.java a volání metody update(...)

Do třídy ObjectManager.java přidáme tyto řádky:

private Food food;
this.food = new Food(gameScreen, chicken, BEGINYCONSTANT);
food.update(delta);

public Food getFood() {
    return food;
}

Přidáme importy a uložíme. Již nemáme prostor dělat výpis celé třídy, takže pokud si nejsme jisti, kam řádky do třídy přidat, podíváme se do zdrojového kódu, který je na konci této kapitoly ke stažení.

Promítnutí krmení

Do třídy Renderer.java přidáme následující kód:

private Food food;
private Texture carrot, autumn, corn, wheat;

this.carrot = AssetManager.carrot;
this.autumn = AssetManager.autumn;
this.corn = AssetManager.corn;
this.wheat = AssetManager.wheat;

this.food = gameMng.getObjectManager().getFood();

drawFood();

private void drawFood() {
    if (food.getMask() == 0)
        batcher.draw(autumn, food.getPositionX(),food.getPositionY(),food.getWidth(),food.getHeight());
    else if(food.getMask()==1)
        batcher.draw(corn, food.getPositionX(),food.getPositionY(),food.getWidth(),food.getHeight());
    else if(food.getMask()==2)
        batcher.draw(wheat, food.getPositionX(),food.getPositionY(),food.getWidth(),food.getHeight());
    else
        batcher.draw(carrot, food.getPositionX(),food.getPositionY(),food.getWidth(),food.getHeight());
}

Přidáme importy a uložíme. Stejně jako v předchozí třídě, pokud si nejsme jisti, kam řádky do třídy přidat, podíváme se do zdrojového kódu. Aplikaci spustíme a pokud máme vše správně, postupně se nám za sebou promítnou krmiva bobule, kukuřice, pšenice a mrkev na náhodných souřadnicích.

Příště, Programujeme Android hru - Collision detection, se budeme zabývat kolizí našeho hloupého kuřete s krmením, promítáním skóre, rychlosti a životnosti krmiva.


 

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

 

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