12. diel - Programujeme Android hru - Kŕmenie I
Vitajte v ďalšom diele nášho kurzu. Z minulého dielu máme našej hru v stave, kedy ide sliepky na miesto kliknutia. Dnes začneme s obsluhou a premietaním krmivá, ktorým budeme našej hlúpu sliepku kŕmiť. Budeme k tomu potrebovať dve triedy. Podľa jednej sa nám vytvorí inštancia nášho kŕmenie. Druhá nám zistí, kde je práve voľné miesto pre umiestnenie onoho kŕmenie, teda tam, kde práve nestojí naše hlúpe kurča.
Začneme druhú zmienenú triedou. V balíčku com.wackychicken.managers si vytvoríme novú triedu PosFinder.java a vyplníme ju do nasledujúceho 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; } }
Triedu si uložíme, vypísal som aj importy, takže pridávať ich nemusíme. Obe triedy si vysvetlíme v druhej časti tohto dielu. Poďme ďalej a v balíčku com.wackychicken.gameobjects si vytvoríme novú triedu Food.java a prekopíruje do nasledujúceho 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; } }
Triedu si uložíme, opäť som vypísal aj importy, takže nepridávame. Ospravedlňte dnešnej dlhý kód a tým pádom aj strohý diel. Pre dnešok nám naozaj stačí, keď správne prekopíruje obsah tried a umiestnime ich do správnych balíčkov. Princíp si vysvetlíme nabudúce. Motiváciou pre nás môže byť zistenie, že v ďalších dieloch pridáme už len jednu triedu, budeme sa teda blížiť k cieľu.
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é 18x (16.07 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Java