IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
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í.

14. diel - Programujeme Android hru - Collision detection

V minulej lekcii programovanie hry pre Android sme sa venovali kŕmenie. Dnes budeme zisťovať možnú kolíziu nášho kurčaťa s kŕmením a ak zistíme, že k tejto kolízii došlo, zvýšime herné skóre o jednotku. Skóre a niektoré ďalšie údaje budeme chcieť samozrejme premietnuť na obrazovku, na tento účel si do assets nahráme svojej vlastné písmo.

Otvoríme si triedu AssetManager.java a doplníme k deklaráciám premenných:

public static BitmapFont yellowFont, shadowFont;

Do metódy load () pridáme:

yellowFont = new BitmapFont(Gdx.files.internal("yellowfont.fnt"),true);
yellowFont.getData().setScale(0.5f, 0.5f);
shadowFont = new BitmapFont(Gdx.files.internal("blackfont.fnt"),true);
shadowFont.getData().setScale(0.5f, 0.5f);

Ďalej do triedy pridáme metódu dispose (), ktorá slúži na uvoľnenie pamäti po našich zdrojoch:

public static void dispose() {
    Gdx.app.log("AssetMng ", "dispose()");
    background.dispose();
    carrot.dispose();
    autumn.dispose();
    corn.dispose();
    wheat.dispose();

    yellowFont.dispose();
    shadowFont.dispose();

    left1.dispose();
    left2.dispose();
    leftSideDown1.dispose();
    leftSideDown2.dispose();
    leftSideUp1.dispose();
    leftSideUp2.dispose();

    right1.dispose();
    right2.dispose();
    rightSideDown1.dispose();
    rightSideDown2.dispose();
    rightSideUp1.dispose();
    rightSideUp2.dispose();

    standLeft12.dispose();
    standRight12.dispose();
}

Pridáme importy a uložíme. Nezabudneme naimportovať súbory písma a jeho tieňa do zložky assets, to už vieme. Metódu dispose () musíme ešte zavolať, otvoríme si triedu WackyChicken.java a tu na koniec funkcie dispose () pridáme riadok:

AssetManager.dispose();

Už sme si zvykli, že už vypisujem iba zmeny (prírastky) kódu, na celý výpis tu nemáme priestor, všetko nájdeme v kompletnom zdrojovom kóde, ktorý je ako obvykle nižšie k stiahnutiu.

Ohľadom písma to je všetko a nič nám nebráni v jeho použití, budeme ho potrebovať neskôr pri implementácii premietaní skóre. Teraz poďme riešiť kolízii.

V balíčku com.wackychic­ken.managers si vytvoríme novú triedu OverlapsManager­.java a vyplníme ju do nasledujúceho tvaru:

public class OverlapsManager {

    private Food food;
    private Chicken chicken;
    private int []score;

    public OverlapsManager(Food food) {
        this.food=food;
        this.chicken=food.getChicken();
        this.score=new int[1];
        this.score[0]=0;
    }

    public void update(float delta) { // trida hlida zda instance food a chicken se protinaji!
        if (Intersector.overlaps(food.getRectForOverlap(),chicken.getRectForOverlap()) && food.getWasClicked() && (!food.getWasCounted()) && chicken.isStanding()   )
        {
            score[0]++;
            food.setWasCounted(true);
            food.setLifeTime(0);
        }
    }

    public void clickedPosition(int x, int y) { // souradnice kliku z inputMng!
        if(food.getRectForOverlap().contains(x, y))
        {
            food.setWasClicked(true);
            chicken.incrWholeSpeed(10); // vzdy kdyz tapneme jidlo, zvysit rychlost
        }
        else { // zvysit rychost ale chceme i kdyz se neklika primo na zradlo
            if( (!chicken.isStanding() && chicken.getStandingState()==StandingState.STANDLEFT && x<chicken.getPositionX()) || (!chicken.isStanding() && chicken.getStandingState()==StandingState.STANDRIGHT && x>chicken.getPositionX()+chicken.getWidth()) )
            {
                chicken.incrWholeSpeed(10);
            }
        }
        // nize vyresetovani rychlosti pri zmene smeru
        if (!chicken.isStanding() && chicken.getStandingState()==StandingState.STANDLEFT && x>chicken.getPositionX()+chicken.getWidth())
            chicken.resetWholeSpeed();
        if (!chicken.isStanding() && chicken.getStandingState()==StandingState.STANDRIGHT && x<chicken.getPositionX())
            chicken.resetWholeSpeed();

    }

    public int[] getScore() {
        return score;
    }

    public void scoreRestart() {
        this.score[0]=0;
    }
}

Pridáme importy a uložíme. Eclipse na nás oprávnene vyhodí chybu, že v inštancii chicken nepozná prístupovú metódu getRectForOverlap (), nielenže tam nemáme túto prístupovú metódu, nemáme tam ani premennú, ku ktorej pristupovať chceme. Poďme to napraviť, otvoríme triedu Chicken.java, kde k deklaráciám premenných pridáme:

private Rectangle rectForOverlap;

Do konstruktoru pridáme:

this.rectForOverlap = new Rectangle(positionX,positionY,this.WIDTH,this.HEIGHT);

Na začiatok metódy update (...) doplníme:

rectForOverlap.set(positionX, positionY, this.WIDTH, this.HEIGHT);

Na koniec triedy pod existujúce metódy pridáme:

public Rectangle getRectForOverlap() {
    return rectForOverlap;
}

Pridáme importy a uložíme. Čo nám zostáva ďalej? Založiť inštanciu našej triedy OverlapsManager­.java, zavolať jej metódy update (...) a clickedPosition (...), otvoríme triedu ObjectManager.java, kde k deklaráciám premenných pridáme:

private OverlapsManager overlapsMng;

Na koniec konstruktoru pridáme:

this.overlapsMng=new OverlapsManager(food);

Na koniec funkcie update (...) pridáme:

overlapsMng.update(delta);

Na začiatok funkcie receivePosition (...) pridáme:

overlapsMng.clickedPosition(x,y);

Na koniec triedy ešte pridáme prístupovú metódu:

public OverlapsManager getOverlapsManager(){
    return this.overlapsMng;
}

Zmeny v triede ObjectManager.java uložíme, trieda je v rovnakom balíčku, preto importy nie sú vyžadované.

Teraz nám zostáva iba pomocou nášho novo naimportovaného písma premietnuť skóre, rýchlosť a "životnosť" krmiva na obrazovku.

Otvoríme triedu Renderer.java, kde k deklaráciám premenných pridáme:

private OverlapsManager overlapsMng;
private BitmapFont yellowFont,shadowFont;
private int score[];

Na konci funkcie initAssetsObjects () vykonáme inicializáciu vyššie uvedených premenných pridaním:

this.overlapsMng=gameMng.getObjectManager().getOverlapsManager();
this.score=overlapsMng.getScore();
this.yellowFont=AssetManager.yellowFont;
this.shadowFont=AssetManager.shadowFont;

Ďalej do triedy Renderer.java pridáme 3 privátne metódy, ktorá umiestnime napríklad ihneď pod metódu render (...):

private void drawTextScore() {
    shadowFont.draw(batcher, "Score: "+score[0],    screenBoundBegin.x+demandedScreen.x*0.22f+2,screenBoundBegin.y+5+2);
    yellowFont.draw(batcher, "Score: "+score[0], screenBoundBegin.x+demandedScreen.x*0.22f,screenBoundBegin.y+5);
}

private void drawTextSpeed() {
    shadowFont.draw(batcher, "Speed: "+(int)(chicken.getWholeSpeed()/10), screenBoundBegin.x+demandedScreen.x*0.45f+2,screenBoundBegin.y+5+2 );
    yellowFont.draw(batcher, "Speed: "+(int)(chicken.getWholeSpeed()/10), screenBoundBegin.x+demandedScreen.x*0.45f,screenBoundBegin.y+5 );
}

private void drawTextFood() {
    shadowFont.draw(batcher, "Food: "+(int)(1+food.getLifeTime()), screenBoundBegin.x+demandedScreen.x*0.7f+2,screenBoundBegin.y+5+2 );
    yellowFont.draw(batcher, "Food: "+(int)(1+food.getLifeTime()),screenBoundBegin.x+demandedScreen.x*0.7f,screenBoundBegin.y+5 );
}

A už nám nezostáva nič iné, než vykonať volanie týchto metód, vykonáme to vo funkcii render (...) ihneď po premietnutí pozadia:

drawTextScore();
drawTextSpeed();
drawTextFood();

Pridáme importy, triedu uložíme a apk. spustíme.

Skóre sa započítava - Programujeme Android hru

Všetko nám funguje, sliepku môžeme postupne poháňať k vyššej rýchlosti. Pri kolízii dôjde k vyžrebovanie novej pozície krmiva a samozrejme k započítanie skóre. Rovnako "životnosť" krmiva je odčítanie. Nabudúce si v stručnosti vysvetlíme princíp činnosti a pridáme ďalšie fíčury.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 29x (6.18 MB)
Aplikácia je vrátane zdrojových kódov v jazyku Java

 

Predchádzajúci článok
Programujeme Android hru - Kŕmenie II
Všetky články v sekcii
Programujeme Android hru
Preskočiť článok
(neodporúčame)
Programujeme Android hru - Animácie, zvuky
Článok pre vás napísal Jaroslav Polívka
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje převážně jazykům JAVA a C++
Aktivity