11. diel - Programujeme Android hru - Grafika II
Ako teda pomocou metódy turnChicken (int x, int y) vykonávame natáčania kurčaťa?
Predstavme si, že máme súradnicovú sústavu podobnú tej karteziánske. Úmyselne zdôrazňujem podobnú, pretože v našej virtuálnej obrazovke máme pod osou x na osi y kladné hodnoty. Ostatné parametre našej sústavy už definíciu karteziánske sústavy vyhovujú: osi sú vzájomne kolmé, jednotky na nich majú rovnakú veľkosť (vzdialenosť v px), počiatok sústavy je v bode [0,0].
Ako to teda funguje? Obrázok nám povie viac ako veľa slov:
- Odpočítaním súradníc kurčaťa od súradníc kľučku užívateľa posunieme súradnice kurčaťa do začiatku súradnicového systému - teda do bodu [0,0] ao túto rovnakú vzdialenosť zároveň posunieme súradnice kľučku užívateľa.
- Spočítame premennú rt (skratka ratio) rovnakým spôsobom ako sínus v pravouhlom trojuholníku. Úmyselne som premennú nepomenoval sínus, pretože tým, že nie sme v kartézské sústave - máme inak os y, by znamienka nezodpovedala jednotlivým kvadrantům.
- Podľa hodnoty premennej rt a zároveň podľa toho, či premenná transformedPositionX je menšia alebo väčšia ako nula, určíme uhol a smer rotácie sliepky.
Poďme konečne premietať, otvoríme si triedu Renderer.java, ktorú máme vyplnenú z 8. dielu tak, že sa nám zobrazuje miesto sliepky žltý obdĺžnik. Aby sme nekopíroval text, triedu rovno vyplníme do nižšie uvedeného tvaru a nabudúce si všetko vysvetlíme.
public class Renderer { private OrthographicCamera cam; private ShapeRenderer shapeRenderer; private SpriteBatch batcher; private final Vector2 demandedScreen,screenBoundBegin; private final GameScreen gameScreen; private Chicken chicken; private GameManager gameMng; private Texture left1,left2,leftSideDown1,leftSideDown2,leftSideUp1,leftSideUp2,leftUp1,leftUp2,leftDown1,leftDown2; private Texture right1,right2,rightSideDown1,rightSideDown2,rightSideUp1,rightSideUp2,rightUp1,rightUp2,rightDown1,rightDown2; private TextureRegion rBackground; private Animation standLeftAnime,standRightAnime; private int counter; private float runTime; private final int COUNTERBEGIN = 20,COUNTEREND =40, BEGINYCONSTANT; public Renderer(GameManager gameManager, float orthoHeight, float orthoWidth) { this.gameMng=gameManager; this.gameScreen=gameMng.getGameScreen(); this.demandedScreen=gameScreen.DEMANDED_SCREEN; this.screenBoundBegin=gameScreen.SCREEN_BOUND_BEGIN; this.BEGINYCONSTANT=gameMng.getObjectManager().getBEGINYCONSTANT(); this.cam = new OrthographicCamera(); this.cam.setToOrtho(true, orthoWidth,orthoHeight); this.shapeRenderer = new ShapeRenderer(); this.shapeRenderer.setProjectionMatrix(cam.combined); this.batcher = new SpriteBatch(); this.batcher.setProjectionMatrix(cam.combined); counter=0; runTime=0; initAssetsObjects(); } public void render(float delta) { Gdx.gl.glClearColor(0, 0, 0, 1); // black background reduce flashing Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); batcher.begin(); //batcher.enableBlending(); //!!!!!!pruhlednost batcher.draw(rBackground,screenBoundBegin.x, screenBoundBegin.y, demandedScreen.x, demandedScreen.y); //pozadi drawChicken(delta); batcher.end(); } private void drawChicken(float delta) { counter+=delta*250*(chicken.getWholeSpeed()/180); // korekce animace pri zrychlovani chicken if(!chicken.isStanding()) { if(chicken.getMovingState()==MovingState.LEFT) { if((int)counter<COUNTERBEGIN) batcher.draw(left1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>=COUNTERBEGIN) { batcher.draw(left2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>COUNTEREND)counter=0; } } else if (chicken.getMovingState()==MovingState.RIGHT) { if((int)counter<COUNTERBEGIN) batcher.draw(right1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>=COUNTERBEGIN) { batcher.draw(right2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>COUNTEREND) counter=0; } } else if (chicken.getMovingState()==MovingState.LEFTSIDEDOWN) { if((int)counter<COUNTERBEGIN) batcher.draw(leftSideDown1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>=COUNTERBEGIN) { batcher.draw(leftSideDown2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>COUNTEREND) counter=0; } } else if (chicken.getMovingState()==MovingState.LEFTSIDEUP) { if((int)counter<COUNTERBEGIN) batcher.draw(leftSideUp1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>=COUNTERBEGIN) { batcher.draw(leftSideUp2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>COUNTEREND) counter=0; } } else if (chicken.getMovingState()==MovingState.RIGHTSIDEUP) { if((int)counter<COUNTERBEGIN) batcher.draw(rightSideUp1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>=COUNTERBEGIN) { batcher.draw(rightSideUp2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>COUNTEREND)counter=0; } } else if (chicken.getMovingState()==MovingState.RIGHTSIDEDOWN) { if((int)counter<COUNTERBEGIN) batcher.draw(rightSideDown1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>=COUNTERBEGIN) { batcher.draw(rightSideDown2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>COUNTEREND) counter=0; } } else if(chicken.getMovingState()==MovingState.LEFTUP) { if((int)counter<COUNTERBEGIN) batcher.draw(leftUp1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>=COUNTERBEGIN) { batcher.draw(leftUp2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>COUNTEREND)counter=0; } } else if(chicken.getMovingState()==MovingState.LEFTDOWN) { if((int)counter<COUNTERBEGIN) batcher.draw(leftDown1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>=COUNTERBEGIN) { batcher.draw(leftDown2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>COUNTEREND) counter=0; } } else if (chicken.getMovingState()==MovingState.RIGHTUP) { if((int)counter<COUNTERBEGIN) batcher.draw(rightUp1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>=COUNTERBEGIN) { batcher.draw(rightUp2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>COUNTEREND) counter=0; } } else if (chicken.getMovingState()==MovingState.RIGHTDOWN) { if((int)counter<COUNTERBEGIN) batcher.draw(rightDown1,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>=COUNTERBEGIN) { batcher.draw(rightDown2,chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); if((int)counter>COUNTEREND) counter=0; } } else Gdx.app.log("renderer:", "Sem by se rizeni nemelo dostat."); } else { runTime+=delta; //kvuli animaci if(chicken.getStandingState()==StandingState.STANDLEFT) batcher.draw(standLeftAnime.getKeyFrame(runTime),chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); else if(chicken.getStandingState()==StandingState.STANDRIGHT) batcher.draw(standRightAnime.getKeyFrame(runTime),chicken.getPositionX(),chicken.getPositionY(),chicken.getWidth(),chicken.getHeight()); else Gdx.app.log("renderer:", "Sem by se rizeni nemelo dostat."); } } //end of drawChicken private void initAssetsObjects() { this.rBackground=AssetManager.rBackground; this.right1=AssetManager.right1; this.right2=AssetManager.right2; this.rightSideDown1=AssetManager.rightSideDown1; this.rightSideDown2=AssetManager.rightSideDown2; this.rightSideUp1=AssetManager.rightSideUp1; this.rightSideUp2=AssetManager.rightSideUp2; this.rightUp1=rightDown1=AssetManager.right1; this.rightUp2=rightDown2=AssetManager.right2; this.left1=AssetManager.left1; this.left2=AssetManager.left2; this.leftSideDown1=AssetManager.leftSideDown1; this.leftSideDown2=AssetManager.leftSideDown2; this.leftSideUp1=AssetManager.leftSideUp1; this.leftSideUp2=AssetManager.leftSideUp2; this.leftDown1=leftUp1=AssetManager.left1; this.leftDown2=leftUp2=AssetManager.left2; this.standLeftAnime=AssetManager.standLeftAnime; this.standRightAnime=AssetManager.standRightAnime; this.chicken=gameMng.getObjectManager().getChicken(); } }
Pridáme importy a triedu uložíme. Nevyužitú BEGINYCONSTANT máme na nabudúce. Vybehla na nás chyba, že v AssetManageru nie je premenná rBackground, otvoríme teda AssetManager.java a pod existujúce deklaráciu premennej
public static Texture background
pridáme:
public static TextureRegion rBackground;
Ďalej túto premennú inicializujeme. Do funkcie load () pod existujúce riadky
background = new Texture(Gdx.files.internal("background.png")); background.setFilter(TextureFilter.Nearest, TextureFilter.Nearest); //proti rozmazavani pri roztahovani
pridáme:
rBackground = new TextureRegion(background,0,0,800,500); rBackground.flip(false, true);
Triedu uložíme a zatvoríme.
Ešte som zabudol v konstruktoru triedy Chicken.java inicializovať stavové premenné movingState a standingState, preto si túto triedu otvoríme a na koniec konstruktoru doplníme:
this.standingState=StandingState.STANDRIGHT; this.movingState=MovingState.RIGHT;
Nevyužité konštanty DEMANDED_SCREEN si zatiaľ nevšímame. Zmenu uložíme a triedu zatvoríme. Pre dnešok máme hotovo. Keby bolo čokoľvek nejasné, môžete opisovať z priloženého zdrojového kódu, ktorý je k stiahnutiu. Aplikáciu spustíme.
Vidíme, že nám všetko funguje, sliepky ide správnym smerom na miesto kľučku a tiež sa nakláňa.
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é 33x (6.07 MB)
Aplikácia je vrátane zdrojových kódov v jazyku Java