14. díl - Programujeme Android hru - Collision detection

Java Android Programujeme hru Programujeme Android hru - Collision detection

V minulé lekci programování hry pro Android jsme se věnovali krmení. Dnes budeme zjišťovat možnou kolizi našeho kuřete s krmením a pokud zjistíme, že k této kolizi došlo, zvýšíme herní skóre o jedničku. Skóre a některé další údaje budeme chtít samozřejmě promítnout na obrazovku, pro tento účel si do assets nahrajeme své vlastní písmo.

Otevřeme si třídu AssetManager.java a doplníme k deklaracím proměnných:

public static BitmapFont yellowFont, shadowFont;

Do metody load() přidá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);

Dále do třídy přidáme metodu dispose(), která slouží k uvolnění paměti po našich zdrojích:

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();
}

Přidáme importy a uložíme. Nezapomeneme naimportovat soubory písma a jeho stínu do složky assets, to již umíme. Metodu dispose() musíme ještě zavolat, otevřeme si třídu WackyChicken.java a zde na konec funkce dispose() přidáme řádek:

AssetManager.dispose();

Už jsme si zvykli, že již vypisuji pouze změny (přírůstky) kódu, na celý výpis tady nemáme prostor, vše najdeme v kompletním zdrojovém kódu, který je jako obvykle níže ke stažení.

Ohledně písma to je vše a nic nám nebrání v jeho použití, budeme ho potřebovat později při implementaci promítání skóre. Nyní pojďme řešit kolizi.

V balíčku com.wackychic­ken.managers si vytvoříme novou třídu OverlapsManager­.java a vyplníme ji do následujícího 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;
        }
}

Přidáme importy a uložíme. Eclipse na nás oprávněně vyhodí chybu, že v instanci chicken nezná přístupovou metodu getRectForOver­lap(), nejenže tam nemáme tuto přístupovou metodu, nemáme tam ani proměnnou, ke které přistupovat chceme. Pojďme to napravit, otevřeme třídu Chicken.java, kde k deklaracím proměnných přidáme:

private Rectangle rectForOverlap;

Do konstruktoru přidáme:

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

Na začátek metody update(...) doplníme:

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

Na konec třídy pod stávající metody přidáme:

public Rectangle getRectForOverlap() {
        return rectForOverlap;
}

Přidáme importy a uložíme. Co nám zbývá dále? Založit instanci naší třídy OverlapsManager­.java, zavolat její metody update(...) a clickedPositi­on(...), otevřeme třídu ObjectManager.java, kde k deklaracím proměnných přidáme:

private OverlapsManager overlapsMng;

Na konec konstruktoru přidáme:

this.overlapsMng=new OverlapsManager(food);

Na konec funkce update(...) přidáme:

overlapsMng.update(delta);

Na začátek funkce receivePositi­on(...) přidáme:

overlapsMng.clickedPosition(x,y);

Na konec třídy ještě přidáme přístupovou metodu:

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

Změny v třídě ObjectManager.java uložíme, třída je ve stejném balíčku, proto importy nejsou vyžadovány.

Nyní nám zbývá pouze pomocí našeho nově naimportovaného písma promítnout skóre, rychlost a "životnost" krmiva na obrazovku.

Otevřeme třídu Renderer.java, kde k deklaracím proměnných přidáme:

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

Na konci funkce initAssetsObjects() provedeme inicializaci výše uvedených proměnných přidáním:

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

Dále do třídy Renderer.java přidáme 3 privátní metody, která umístíme například ihned pod metodu 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 již nám nezbývá nic jiného, než provést volání těchto metod, provedeme to ve funkci render(...) ihned po promítnutí pozadí:

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

Přidáme importy, třídu uložíme a apk. spustíme.

Skóre se započítává

Vše nám funguje, slepici můžeme postupně popohánět k vyšší rychlosti. Při kolizi dojde k vylosování nové pozice krmiva a samozřejmě k započítání skóre. Rovněž "životnost" krmiva je odčítána. Příště si ve stručnosti vysvětlíme princip činnosti a přidáme další fíčury.


 

Stáhnout

Staženo 7x (6.18 MB)
Aplikace je včetně zdrojových kódů v jazyce Java

 

  Aktivity (2)

Č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í!


 


Miniatura
Všechny články v sekci
Programujeme Android hru

 

 

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í!