10. diel - Programujeme Android hru - Grafika I
V minulom diele nášho seriálu sme načítali grafické zdroje pozadie a sliepky. V dnešnom dvoj-diele je premietneme na obrazovku.
Pôjde o veľmi jednoduché premietanie, sliepky bude mať nasledujúce možnosti smerov chôdzou a rotáciou:
- chôdza vľavo, rotácia vľavo
- chôdza vpravo, rotácie vpravo
- chôdza dole, rotácia vľavo
- chôdza dole, rotácia vpravo
- chôdza hore, rotácia vľavo
- chôdza hore, rotácia vpravo
- chôdze a rotácie šikmo vpravo hore
- chôdze a rotácie šikmo vpravo dole
- chôdze a rotácie šikmo vľavo dole
- chôdze a rotácie šikmo vľavo hore
Ku každej možnosti je viazaná sada dvoch obrázkov, ktoré premietneme striedavo na obrazovku, aby sme vytvorili aspoň základné ilúziu chôdze sliepky.
Náš kód vyberie jednu z možností na základe výpočtu, ktorý objasním ďalej. Nesmiem zabudnúť zdôrazniť, že možnosti chôdzou iba čisto vľavo, vpravo, hore a dole málokedy existujú. Sliepky sa väčšinou pohybuje viac či menej po oboch osiach súčasne - teda šikmo. My to ale urobíme tak, že pohyby v mierne šikmých smeroch budeme považovať za pohyby čisto vľavo, vpravo, dolu alebo hore. Inak povedané, pri mierne šikmých pohyboch nebudeme sliepku nakláňať vôbec.
Rôzne možnosti premietnutí podľa aktuálnej pozície sliepky a kľučku užívateľa na obrazovku nie sú ničím iným, než vlastnosťami našej sliepky. Otvoríme si triedu Chicken.java a pomocou vymenovaných konštánt tieto vlastnosti sliepke pridáme. Pod existujúce premenné si pridáme ďalšie:
public enum MovingState{LEFT,LEFTUP,LEFTDOWN,LEFTSIDEDOWN,LEFTSIDEUP, RIGHT,RIGHTUP,RIGHTDOWN,RIGHTSIDEDOWN,RIGHTSIDEUP} public enum StandingState{STANDLEFT,STANDRIGHT,EATLEFT,EATRIGHT} private MovingState movingState; private StandingState standingState;
Ďalej si k týmto premenným pridáme prístupovej metódy:
public MovingState getMovingState() { return movingState; } public void setMovingState(MovingState state) { movingState=state; } public StandingState getStandingState() { return standingState; } public void setStandingState(StandingState state) { standingState=state; }
Vložíme treba na koniec triedy, pod existujúce prístupové metódy. Triedu uložíme a môžeme zatvoriť. Výpis celej triedy teraz robiť nebudem, v prípade potreby sa pozrite do priloženého zdrojového kódu, ktorý je k stiahnutiu.
Čo potrebujeme ďalej? Vždy, keď používateľ klikne na obrazovku, potrebujeme určiť a nastaviť do akého smeru sa má sliepky natočiť. To nám zaistí naša trieda TurnManager.java, do ktorej som na tento účel pridal metódu turnChicken (int x, int y), jej argumenty sú súradnice miesta kľučku používateľa na obrazovku. Upravme našej triedu TurnManager.java do nižšie uvedenej podoby:
public class TurnManager { private MovingState movingState; private StandingState standingState; private Chicken chicken; private final Vector2 screenBoundEnd; private final Vector2 screenBoundBegin; private final int BEGINYCONSTANT; public TurnManager(GameScreen gameScreen,final int BEGINYCONSTANT) { final Vector2 demandedScreen=gameScreen.DEMANDED_SCREEN; this.screenBoundBegin=gameScreen.SCREEN_BOUND_BEGIN; this.screenBoundEnd=gameScreen.SCREEN_BOUND_END; this.BEGINYCONSTANT=BEGINYCONSTANT; this.chicken = new Chicken(screenBoundBegin,screenBoundEnd,demandedScreen,BEGINYCONSTANT); } public void turnChicken(int x,int y) { // x a y souradnice kliku float transformedPositionX = x - chicken.getPositionX() - chicken.getWidth()/2; float transformedPositionY = y - chicken.getPositionY() - chicken.getHeight()/2; double rt = transformedPositionY / Math.sqrt( (Math.pow(transformedPositionX,2) + Math.pow(transformedPositionY,2)) ); // Gdx.app.log("turnMng rt:", ""+rt); if ((rt < -0.9) && (transformedPositionX <= 0)) { movingState=MovingState.LEFTUP; chicken.setMovingState(movingState); standingState=StandingState.STANDLEFT; chicken.setStandingState(standingState); //Gdx.app.log("turnMng state:",chicken.getMovingState().toString()); } else if ((rt < -0.9) && (transformedPositionX > 0)) { movingState=MovingState.RIGHTUP; chicken.setMovingState(movingState); standingState=StandingState.STANDRIGHT; chicken.setStandingState(standingState); //Gdx.app.log("turnMng state:",chicken.getMovingState().toString()); } else if ((rt >= -0.9 ) && (rt <= -0.4) && (transformedPositionX > 0)) { movingState=MovingState.RIGHTSIDEUP; chicken.setMovingState(movingState); standingState=StandingState.STANDRIGHT; chicken.setStandingState(standingState); //Gdx.app.log("turnMng state:",chicken.getMovingState().toString()); } else if ((rt > -0.4) && (rt < 0.4) && (transformedPositionX > 0)) { movingState=MovingState.RIGHT; chicken.setMovingState(movingState); standingState=StandingState.STANDRIGHT; chicken.setStandingState(standingState); //Gdx.app.log("turnMng state:",chicken.getMovingState().toString()); } else if ((rt >= 0.4) && (rt <= 0.9 ) && (transformedPositionX > 0)) { movingState=MovingState.RIGHTSIDEDOWN; chicken.setMovingState(movingState); standingState=StandingState.STANDRIGHT; chicken.setStandingState(standingState); //Gdx.app.log("turnMng state:",chicken.getMovingState().toString()); } else if ((rt > 0.9) && (transformedPositionX <= 0)) { movingState=MovingState.LEFTDOWN; chicken.setMovingState(movingState); standingState=StandingState.STANDLEFT; chicken.setStandingState(standingState); //Gdx.app.log("turnMng state:",chicken.getMovingState().toString()); } else if ((rt > 0.9) && (transformedPositionX > 0)) { movingState=MovingState.RIGHTDOWN; chicken.setMovingState(movingState); standingState=StandingState.STANDRIGHT; chicken.setStandingState(standingState); //Gdx.app.log("turnMng state:",chicken.getMovingState().toString()); } else if ((rt <= 0.9 ) && (rt >= 0.4) && (transformedPositionX < 0)) { movingState=MovingState.LEFTSIDEDOWN; chicken.setMovingState(movingState); standingState=StandingState.STANDLEFT; chicken.setStandingState(standingState); //Gdx.app.log("turnMng state:",chicken.getMovingState().toString()); } else if ((rt < 0.4) && (rt > -0.4) && (transformedPositionX < 0)) { movingState=MovingState.LEFT; chicken.setMovingState(movingState); standingState=StandingState.STANDLEFT; chicken.setStandingState(standingState); //Gdx.app.log("turnMng state:",chicken.getMovingState().toString()); } else if ((rt <= -0.4) && (rt >= -0.9) && (transformedPositionX < 0)) { movingState=MovingState.LEFTSIDEUP; chicken.setMovingState(movingState); standingState=StandingState.STANDLEFT; chicken.setStandingState(standingState); //Gdx.app.log("turnMng state:",chicken.getMovingState().toString()); } else Gdx.app.log("turnMng:", "chybna hodnota rt"); } //konec turnChicken public void setChickenDistance(int x, int y) { int clickedPositionX=x,clickedPositionY=y; float distanceX,distanceY; float chickenTailX = chicken.getPositionX() + chicken.getWidth(); if (Math.abs(clickedPositionX - chicken.getPositionX()) <= Math.abs(clickedPositionX - chickenTailX)) distanceX = clickedPositionX - chicken.getPositionX(); else distanceX=clickedPositionX - chickenTailX; if(distanceX < screenBoundBegin.x-chicken.getPositionX()) distanceX = screenBoundBegin.x-chicken.getPositionX(); if(distanceX > screenBoundEnd.x- chickenTailX) distanceX=screenBoundEnd.x- chickenTailX; distanceY=clickedPositionY-(chicken.getPositionY()+chicken.getHeight()); if(distanceY < (screenBoundBegin.y+BEGINYCONSTANT)-(chicken.getPositionY()+ chicken.getHeight())) distanceY=(screenBoundBegin.y+BEGINYCONSTANT)-(chicken.getPositionY()+ chicken.getHeight()); if(distanceY > (screenBoundEnd.y-(chicken.getPositionY()+chicken.getHeight())) ) distanceY = screenBoundEnd.y-(chicken.getPositionY()+chicken.getHeight()); if(Math.abs(distanceX)<0.5f) { if(distanceX >=0) distanceX=0.5f; else distanceX=-0.5f; } if(Math.abs(distanceY)<0.5f) { if(distanceY >=0) distanceY=0.5f; else distanceY=-0.5f; } chicken.setDistanceX(distanceX); chicken.setDistanceY(distanceY); } public void setChickenSpeed() { float speedRatio = chicken.getWholeSpeed() / (Math.abs(chicken.getDistanceX()) + Math.abs(chicken.getDistanceY())); chicken.setDividedSpeedX(speedRatio*chicken.getDistanceX()); chicken.setDividedSpeedY(speedRatio*chicken.getDistanceY()); } public Chicken getChicken() { // kvuli objMng return chicken; } }
Pridáme importy, triedu uložíme a môžeme zatvoriť. Našou novú metódu turnChicken (int x, int y) nezabudneme zavolať. Otvoríme si triedu ObjectManager.java a do jej metódy receivePosition (int x, int y) pridáme volanie, takže výsledná podoba metódy bude:
public void receivePosition(int x,int y) { //souradnice z inputu turnMng.turnChicken(x, y); turnMng.setChickenDistance(x, y); turnMng.setChickenSpeed(); chicken.setXPositionAchieved(false); chicken.setYPositionAchieved(false); }
Týmto zavolaním nám metóda turnChicken (int x, int y) po kliku používateľa na obrazovku nastaví stavové premenné kurčaťa movingState a standingState, ktorými následne budeme riadiť premietačku. Nabudúce budeme pokračovať objasnením princípu funkcie turnChicken (int x, int y).
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é 21x (12.54 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Java