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.wackychicken.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.wackychicken.gameobjects 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