11. díl - Šibenice pro Android - MainGameActivity

Java Android Šibenice pro Android - MainGameActivity

V minulém tutoriálu o programování aplikací pro Android jsme vytvořili jednotlivé aktivity hry šibenice a implementovali jsme menu s výběrem okruhů. V dnešním dílu se budeme věnovat hlavní aktivitě - MainGameActivity.

Jako první si přidáme instanční proměnné, potřebné pro chod hry:

private String slovo = "";
private int chyba = 0;

private int delkaSlova=0;
private int PocetVyskytu=0;
private String PomDelka="";

private int score = 10000;
private int multiplikator = 0;
private String Suhadnute="";
private String ZapocitaneChyby="";

int okruh=0;

Přidejme metodu onCreate(). Zde se vytvoří objekt AnimationDrawable (animace) a inicializuje se ImageView (Nadpis). Dále se použije metoda addFrame(), pomocí které do animace přidáme jednotlivé snímky a nastavíme čas v ms, po který se bude daný snímek zobrazovat. Objektu Nadpis (ImageView) nastavíme BackgroundDrawable. Parametrem je animace. Poté animaci spustí a metodou getIntent().ge­tIntExtra() načte hodnotu buňky VybranaMetoda, defaultní hodnota je 1. Na konci se volá metoda VyberSlovo() a uprav().

@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_game);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
        //zakázání změn orientace

        AnimationDrawable animace = new AnimationDrawable();
        ImageView Napis=(ImageView) findViewById(R.id.imageView4);

        animace.addFrame(getResources().getDrawable(R.drawable.napis1),1000);
        animace.addFrame(getResources().getDrawable(R.drawable.napis2),1000);
        animace.addFrame(getResources().getDrawable(R.drawable.napis3),1000);
        animace.addFrame(getResources().getDrawable(R.drawable.napis4),1000);
        animace.addFrame(getResources().getDrawable(R.drawable.napis5),1000);
        animace.addFrame(getResources().getDrawable(R.drawable.napis6),1000);
        animace.addFrame(getResources().getDrawable(R.drawable.napis7),1000);
        animace.addFrame(getResources().getDrawable(R.drawable.napis8),1000);
        animace.addFrame(getResources().getDrawable(R.drawable.napis9),1000);
        animace.addFrame(getResources().getDrawable(R.drawable.napis10),1000);

        Napis.setBackgroundDrawable(animace);

        animace.start();

        okruh = getIntent().getIntExtra("VybranaMetoda",1);

        VyberSlovo();
        uprav(slovo);
}

Metoda VyberSlovo() vytvoří pole stringů. Na základě vybraného okruhu se do něj uloží slova. Vytvoří objekt Random (ranInfo) a pomocí metody nextInt() určí náhodné číslo od 0 do délky pole -1. Do instanční proměnné "slovo" se uloží vybrané slovo.

private void VyberSlovo(){
        String [] poleInfo = new String[100];
        int delkaInfo=0;

        if(okruh==1){
                poleInfo  = new String[] {"síť", "crack", "hacker", "firewall", "databáze", "počítač", "notebook", "klávesnice", "myš", "ram", "procesor", "java", "android", "windows", "linux", "ubuntu", "lubuntu", "algoritmus", "program", "bios", "hardware", "software", "monitor", "lan", "man", "wan", "ethernet", "proxy", "server", "chrome", "opera", "safari", "komprese", "dekomprese", "informace", "diagram", "kódování", "zdroj", "patice", "frekvence", "sektor", "odezva", "kontrast", "jas", "rozlišení", "skener", "tablet", "projektor", "cyklus", "podmínka", "pascal", "apple", "mac", "procedura"};
                                }
        if(okruh==2){
                poleInfo  = new String[] {"praha", "brno", "ostrava", "plzeň", "liberec", "olomouc", "pardubice", "havířov", "zlín", "kladno", "most", "karviná", "opava", "bruntál", "jihlava", "teplice", "kolín", "šumperk", "chomutov", "přerov", "prostějov", "třebíč", "tábor", "třinec", "znojmo", "příbram", "cheb", "orlová", "trutnov", "písek", "vsetín", "hodonín", "sokolov", "bohumín", "beroun", "jičín", "benešov"};
         }
        if(okruh==3){
                poleInfo  = new String[] {"klokan", "opice", "zebra", "lama", "slon", "hroch", "velbloud", "nosorožec", "bažant", "medvěd", "slepice", "morče", "ovce", "prase", "koza", "kráva", "kohout", "králík", "zajíc", "tygr", "vlk", "veverka", "žába", "tuleň", "ježek", "fredka", "křeček"};
        }
        if(okruh==4){
                poleInfo  = new String[] {"audi", "bmw", "citroen", "dacia", "fiat", "ferrari", "kia", "honda", "škoda", "hyundai", "chevrolet", "jaguar", "jeep", "mazda", "mercedes", "mitsubishi", "nissan", "opel", "peugeot", "porsche", "renault", "rover", "saab", "seat", "subaru", "suzuki", "toyota", "volkswagen", "volvo", "bentley", "bugatti", "cadillac", "lada", "dodge", "infinity", "lancia", "lexus", "maybach", "pagani", "proton", "tatra", "trabant", "volha", "zastava"};
        }
        delkaInfo = poleInfo.length;
        Random ranInfo = new Random();
        int losInfo = ranInfo.nextInt(delkaInfo-1);
        slovo=poleInfo[losInfo];
}

Dostáváme se k metodě uprav(). Ta vytvoří reference na objekty TextView od 3 do 10, protože nejkratší slova budou mít 2 znaky a nejdelší 10 znaků. Na základě délky slova pomocí GONE "zruší" určitý počet TextView. Parametrem je slovo, které bylo vylosováno k hádání.

private void uprav(String HadaneSlovo){
        TextView[] pismena = new TextView[10];
        pismena[0] = (TextView) findViewById(R.id.tvp1);
        pismena[1] = (TextView) findViewById(R.id.tvp2);
        pismena[2] = (TextView) findViewById(R.id.tvp3);
        pismena[3] = (TextView) findViewById(R.id.tvp4);
        pismena[4] = (TextView) findViewById(R.id.tvp5);
        pismena[5] = (TextView) findViewById(R.id.tvp6);
        pismena[6] = (TextView) findViewById(R.id.tvp7);
        pismena[7] = (TextView) findViewById(R.id.tvp8);
        pismena[8] = (TextView) findViewById(R.id.tvp9);
        pismena[9] = (TextView) findViewById(R.id.tvp10);

        int vel = HadaneSlovo.length();

        for (int i = vel; i < 10; i++)
        {
                pismena[i].setVisibility(View.GONE);
        }
}

Začněme realizovat vložení písmena. Podmínka vyhodnocuje, zda se zadané písmenko vyskytuje v abecedě, popř. zda to je český znak. (ě, š, č atd.). For cyklus porovná všechna písmena v hádaném slově se zadaným písmenem (ZadaneP). Pokud dojde ke shodě, připočítá +1 k PocetVyskytu a zavolá metody ZapisSpravne() a ScorePlus().

Po každém dokončeném cyklu se připočítá hodnota PocetVyskytu k hodnotě delkaSlova. delkaSlova použijeme ke kontrole, zda jsme už uhádli všechna písmena. Také nesmíme zapomenout přidat zadaný znak (ZadaneP) do proměnné PomDelka. Tím zajistíme, že nepřičteme počet uhádnutých písmen vícekrát než jednou.

Po zvednutí hodnoty PomDelka kontrolujeme podmínkou, zda jsme už dosáhli délky hádaného slova. Pokud ano, hru jsme vyhráli a voláme metodu Vyhra(). Pokud je PocetVyskytu roven nule, znamená to, že se zadané písmeno v hádaném slově nevyskytuje. Proto voláme metody ZapisSpatne() a ScoreMinus().

Na konci musíme vždy vynulovat „počítadlo shod“ PocetVyskytu. Pomocí parametru View v se metoda stane viditelná, abychom nastavili metodu onClick v XML.

public void Vlozeni(View v){
        EditText edte = (EditText) findViewById(R.id.Zadani);
        String zadani = edte.getText().toString().toLowerCase();
        if (zadani.length()>=1){
                char ZadaneP = zadani.charAt(0);
                edte.setText("");
                if ((ZadaneP>=97 && ZadaneP <= 122) || (ZadaneP==283) || (ZadaneP==353) || (ZadaneP==357) || (ZadaneP==269) || (ZadaneP==345) || (ZadaneP==382) || (ZadaneP==253) || (ZadaneP==225)|| (ZadaneP==237)|| (ZadaneP==233)|| (ZadaneP==367)||(ZadaneP==250)||(ZadaneP==243)) {

                        for (int i=0; i< slovo.length();i++){
                                if (slovo.charAt(i)==ZadaneP){
                                        PocetVyskytu++;
                                        ZapisSpravne(ZadaneP, i);
                                        ScorePlus(ZadaneP);
                                }
                        }

                        if (PomDelka.indexOf(ZadaneP)==-1){
                                delkaSlova+=PocetVyskytu;
                                PomDelka+=ZadaneP;
                        }

                        if(delkaSlova==slovo.length()){
                                Vyhra();
                        }
                        if (PocetVyskytu==0){
                                ZapisSpatne(ZadaneP);
                                ScoreMinus(ZadaneP);
                        }
                }
                else {
                        Toast.makeText(getApplicationContext(), "Není zadáno správné písmeno", Toast.LENGTH_LONG).show();
                }
        }

        PocetVyskytu=0;
}

Přidáváme metodu pro zapsání uhádnutého písmena do slova. Přepíšeme určité textView z původního „_“ na zadané písmeno. Prametry jsou zadané písmeno a pozice písmena ve slově.

private void ZapisSpravne(char pismeno, int pozice){
        TextView[] pismena = new TextView[10];
        pismena[0] = (TextView) findViewById(R.id.tvp1);
        pismena[1] = (TextView) findViewById(R.id.tvp2);
        pismena[2] = (TextView) findViewById(R.id.tvp3);
        pismena[3] = (TextView) findViewById(R.id.tvp4);
        pismena[4] = (TextView) findViewById(R.id.tvp5);
        pismena[5] = (TextView) findViewById(R.id.tvp6);
        pismena[6] = (TextView) findViewById(R.id.tvp7);
        pismena[7] = (TextView) findViewById(R.id.tvp8);
        pismena[8] = (TextView) findViewById(R.id.tvp9);
        pismena[9] = (TextView) findViewById(R.id.tvp10);

        pismena[pozice].setText(String.valueOf(pismeno));
}

Podobně obsloužíme i zadání špatného písmena. Do stringu "chyby" načteme obsah textView, kam vypisujeme chybná písmena. Pokud v řetězci chybné písmeno (parametr) ještě není, zvedneme hodnotu proměné "chyba" o +1 a chybné písmeno přidáme do tV. Na základě hodnoty chyba se zobrazí správný obrázek s tím, že pokud dojde k deváté chybě, voláme metodu KonecHry(). Parametrem je chybné písmeno, to proto, že ho budeme připisovat do textView, aby hráč měl přehled, která písmena už hádal.

private void ZapisSpatne(char pismeno){

        ImageView plocha = (ImageView) findViewById(R.id.ZaverecnaPlocha);
        TextView spatne = (TextView) findViewById(R.id.Chyby);

        String chyby = spatne.getText().toString();

        if (chyby.indexOf(pismeno)==-1){
                chyba++;
                spatne.append(String.valueOf(pismeno));

                if (chyba==1){
                        plocha.setImageResource(R.drawable.krok2m);
                }
                else if (chyba==2){
                        plocha.setImageResource(R.drawable.krok3m);
                }
                else if (chyba==3){
                        plocha.setImageResource(R.drawable.krok4m);
                }
                else if (chyba==4){
                        plocha.setImageResource(R.drawable.krok5m);
                }
                else if (chyba==5){
                        plocha.setImageResource(R.drawable.krok6m);
                }
                else if (chyba==6){
                        plocha.setImageResource(R.drawable.krok7m);
                }
                else if (chyba==7){
                        plocha.setImageResource(R.drawable.krok8m);
                }
                else if (chyba==8){
                        plocha.setImageResource(R.drawable.krok9m);
                }
                else if (chyba==9){
                        KonecHry();
                }
        }
}

Metodu ScorePlus() voláme v případě, že hráč písmeno uhádl. Parametrem je uhádnuté písmeno, to kvůli tomu, že ho přidáme do pomocného řetězce Suhadnute, abychom score za uhádnuté písmeno připsali pouze poprvé. Musíme totiž ošetřit případ, kdy hráč zadá několikrát za sebou stejné písmeno.

Pokud je tedy podmínka splněna, vytvoří se objekt MediaPlayer mp, který bere zdrojové soubory (v tomto případě mp3) ze složky raw, která je v resources. Hned po vytvoření se jednou přehraje, do řetězce se přidá uhádnuté písmeno, zvedne se multiplikátor a vypočte se score.

private void ScorePlus(char Pismeno){
        if (Suhadnute.indexOf(Pismeno)==-1){
                MediaPlayer mp = MediaPlayer.create(this, R.raw.sucpis);
                mp.start();
                Suhadnute+=Pismeno;
                multiplikator++;
                score+=(500*multiplikator);
        }
}

ScoreMinus() voláme v případě, že hráč písmeno neuhádl. je to obdobná funkce jako ScorePlus(). Jediné, co se mění je to, že od score odečítáme 1000 a multiplikátor nastavíme na 0;

private void ScoreMinus(char Pismeno){
        if (ZapocitaneChyby.indexOf(Pismeno)==-1){
                MediaPlayer mp = MediaPlayer.create(this, R.raw.failpis);
                mp.start();
                ZapocitaneChyby+=Pismeno;
                score-=1000;
                multiplikator=0;
        }
}

KonecHry() voláme v případě, že hráč prohrál a Vyhra() v případě, že hráč hru vyhrál. Pomocí Intentu přeskočíme do aktivity EndGameActivity. Jako extra data si vezmeme hodnotu score, hádané slovo a informaci o tom zda hráč prohrál nebo vyhrál.

private void KonecHry(){
        Intent EndGame = new Intent(this, EndGameActivity.class);
        EndGame.putExtra("VYHRA_PROHRA", 0);
        EndGame.putExtra("ID_PROMENNE", score);
        EndGame.putExtra("SLOVO", slovo);
        startActivity(EndGame);
        finish();
}

private void Vyhra(){
        Intent EndGame = new Intent(this, EndGameActivity.class);
        EndGame.putExtra("VYHRA_PROHRA", 1);
        EndGame.putExtra("ID_PROMENNE", score);
        EndGame.putExtra("SLOVO", slovo);
        startActivity(EndGame);
        finish();
}

Kódování charu

Pokud někomu stále není jasné, proč se v metodě Vlozeni() objevila určitá čísla v podmínce, doporučuji se pozorně podívat na následující snímek.

Kódování UTF-16 v Javě

Obrázek 8 - příklad kódování UTF-16

Můžete se podívat i na UTF-16 ASCII tabulku.

Příště hru dokončíme přidáním aktivit pro konec hry a zobrazení skóre.


 

  Aktivity (1)

Článek pro vás napsal Jiří Hlavík
Avatar
Autor se věnuje programování v C# a vývoji aplikací pro platformu Android a dalším věcem spojeným s Android OS

Jak se ti líbí článek?
Celkem (2 hlasů) :
333 33


 



 

 

Komentáře

Avatar
nalimleinad
Člen
Avatar
nalimleinad:

A co tak uvolnit MediaPlayer z paměti ?

 
Odpovědět 21.5.2015 23:02
Avatar
Jiří Hlavík
Redaktor
Avatar
Odpovídá na nalimleinad
Jiří Hlavík:

Ahoj nalimleinad. Díky za postřeh.. Uvolnit MediaPlayer z paměti se dá pomocí metody release(). Nevidím důvod to v tomto případě použít. Kdybychom používali více MP na jedné aktivitě, například je podle něčeho střídali nebo tak, mělo by to smysl, ovšem pokud se nepletu, při ukončení aktivity, na které MP běží, by měl být release použit automaticky (testováno).

 
Odpovědět 23.5.2015 14:47
Avatar
nalimleinad
Člen
Avatar
Odpovídá na Jiří Hlavík
nalimleinad:

No já nevím, já jen že o tom po spuštění začal logcat vyhazovat errory a někde jsem právě četl, že by se to vždy mělo uvolňovat. ;)

 
Odpovědět 23.5.2015 23:25
Avatar
Pavel Polí Pražák:

Ahoj vubec jsem nepochopil co má byt pod pojmem
animace.addFra­me(getResources()­.getDrawable(R­.drawable.napis1),1000);
.
.
.
co je to jako jednotlivé kroky vykreslování v případě sibenice třeba (1.hlava,2.tě­lo,atd) nebo jak jinak děkuji je to užitečné občas v tom je trochu Junge ale hledáním chyb se človek nejlepe učí

 
Odpovědět 20. května 13:23
Avatar
Jiří Hlavík
Redaktor
Avatar
Odpovídá na Pavel Polí Pražák
Jiří Hlavík:

Ahoj, přiznám se že teď nevím o jaké konkrétně obrázky jde, nemám v současné době moc času abych články mohl překopat, ovšem v následujících dnech mám v plánu nějaký čas najít a chyby/nejasnosti atd. upravit. Ale z5 k tématu..
Pokud mě paměť neklame tak nadpis1 nadpis2 atd. jsou obrázky, kde jsou jednotlivé "jpg/png" kroky animace. Tento typ animace vlastně funguje jako gif. snímek za snímkem
Příkazem addFrame do své ho objektu animace "vložíš" specifické snímky (1000 je čas v ms).
Po spuštění animace se ti budou přehrávat vložené snímky
(zastaralé neefektivní a samozřejmě když už tohle, tak by to samotné "vkládání" určitě šlo vyřešit cyklem :D)

 
Odpovědět 24. května 13:44
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.

Zobrazeno 5 zpráv z 5.