V předchozích článcích jsme si připravili základ jednoduché hry. Teď ještě zbývá přidat nějakou tu omáčku okolo. Tentokrát to bude úvodní obrazovka, kterou se aplikace představuje uživateli, stejně jako vy se představujete podáním ruky.

Úvodní obrazovka (splashscreen)

Po spuštění aplikace se většinou ukáže obrázek (může to být i animace nebo několik obrázků za sebou), který obvykle obsahuje několik základních informací, jako je název hry nebo logo výrobce, a může zobrazovat průběh nahrávání hry. Tento obrázek také může být doprovázen nějakým zvukem, který se však přehraje pouze v případě, že v nastavení hry není přehrávání zvuků vypnuto.

Splashscreen
Úvodní obrazovka (splashscreen)

Úvodní obrazovku můžeme nechat na displeji, dokud uživatel nezmáčkne nějakou klávesu, ale lepší je po několika vteřinách ji nahradit menu hry nebo přímo obrazovkou hry, podle toho, co je u dané hry vhodnější. Také můžeme oba přístupy zkombinovat – po stisku klávesy přejdeme na menu hry či na hru, nestiskne-li uživatel klávesu, přejdeme tam po určené době.

Nejjednodušší varianta

Začneme od nejjednodušší varianty, kdy pouze zobrazíme obrázek a po pěti vteřinách jej nahradíme hrou. Základní úvodní obrazovka je pak velmi jednoduchá třída, která vypadá takto:

public class SplashScreen extends Canvas {
  // úvodní obrázek
  private Image splash;
  // odkaz na instanci midletu
  private GameMIDlet midlet;
  public SplashScreen(GameMIDlet midlet){
    try {
      this.midlet = midlet;
      splash = Image.createImage(„/splash2.png“);
    } catch (Exception e){
      e.printStackTrace();
    }
  }
  /*
   * Tato metoda počká 5 vteřin a pak spustí hru
   */
  public void run(){
    try{
      // vlákno uspíme pouze, nahrál-li se obrázek v pořádku
      if(splash!=null){
        // uspání aktuálního vlákna na 5 vteřin
        Thread.sleep(5000);
      }
    }catch (Exception e){
      e.printStackTrace();
    }
    // zrušení odkazu na obrázek
    splash = null;
  }
  /*
   * Vykreslení obrázku
   */
  protected void paint(Graphics g) {
    if(splash!=null){
      g.drawImage(splash, 0, 0, Graphics.TOP | Graphics.LEFT);
    }
  }
}

V metodě startApp() instance midletu GameMIDlet před zobrazením herního kanvasu GameCanvas zobrazíme úvodní obrazovku SplashScreen a zavoláme její metodu run().

SplashScreen splashScreen = new SplashScreen(this);
Display.getDisplay(this).setCurrent(splashScreen);
splashScreen.run();

V metodě run() zablokujeme běh programu na pět vteřin voláním metody Thread.sleep(5000), která uspí právě spuštěné vlákno na daný počet milisekund.

Obrázky versus paměť

Je dobrým zvykem nastavovat na null všechny odkazy na obrázky hned v okamžiku, kdy přestanou být potřeba, aby již nepoužívané obrázky mohl javový virtuální stroj odstranit z paměti. Paměť telefonů je omezená a při hře obsahující hodně obrázků by hra mohla velmi rychle spadnout na nedostatek paměti, pokud bychom tento zvyk nedodržovali.

Nástroj J2ME Wireless Toolkit umožňuje nastavení paměti, která je k dispozici pro běh hry, a sledování aktuálního využití této paměti. Při výskytu chyby OutOfMemoryError je tato vlastnost J2MEWTK celkem příjemná, protože kdo má pořád tu aplikaci nahrávat na telefon, že?

Množství paměti, které má emulátor k dispozici, se nastaví tak, že otevřete položku menu Edit->Preferences… a v tomto okně si nalistujte záložku Storage. položka, která nás zajímá, se jmenuje Heap size.

Nastavení velikosti paměti emulátoru
Nastavení velikosti paměti emulátoru (plná velikost, cca 45 kB)

Monitor paměti dost zpomaluje běh aplikace, takže se nehodí k neustálému použití, ale občas může být prospěšný. Nastavuje se v záložce Monitor hned v její první položce Enable Memory Monitor.

Nastavení monitoru paměti
Nastavení monitoru paměti (plná velikost, cca 85 kB)

Logo výrobce

Nahradit obrázek v hotové aplikaci je tak jednoduchá operace, že ji zvládne i průměrný počítačový uživatel. Prostě vymění obrázek v JAR souboru, kde je zabalená aplikace, za jiný stejného jména. Jste-li lehce paranoidní a trváte-li na tom, že uživatel by měl na začátku hry vidět, kdo hru vytvořil, existuje snadná pomoc. Odstraňte logo z hotového obrázku a kreslete jej v programu v rámci metody paint() třídy SplashScreen.

Pokud jste skromní nebo bojujete s limitem velikosti aplikace, můžete se spokojit s použitím vestavěného fontu telefonu a nakreslit logo takto:

g.drawString(„United Nesmysls“,
             getWidth() – 1,
             getHeight() – 1,
             Graphics.RIGHT | Graphics.BOTTOM);

Trváte-li na logu se vším všudy, nabízí se následující metoda. PNG soubor s logem (na průhledném pozadí) převeďte na pole bajtů pomocí třídy PNGToByteArray, kterou jsem pro vás připravila.

Dejte si do jednoho adresáře soubory PNGToByteArray.class a logo.png, který obsahuje obrázek s logem. Pak v tomto adresáři zavolejte následující příkaz:

java -cp . PNGToByteArray logo.png

Výsledný řetězec, který se vypíše na standardní výstup, stačí zkopírovat do proměnné typu byte[] a zobrazit následujícím kódem:

byte[] logoBytes = {…} // nezajímavé dlouhatánské pole bajtů
Image logo = Image.createImage(logoBytes, 0, logoBytes.length);
g.drawImage(logo,
            getWidth()-1,
            getHeight()-1,
            Graphics.RIGHT | Graphics.BOTTOM);

Odchyt stisku klávesy

Další vylepšení, které provedeme, umožní přerušit zobrazení úvodní obrazovky při stisku libovolné klávesy. Přidáme proměnnou pressed s výchozí hodnotou false, která určuje, zda byla stisknuta klávesa. Hlavní vlákno aplikace už nemůžeme uspat na celých pět vteřin, ale musíme pravidelně kontrolovat, zda nebyla stisknuta klávesa, a pakliže byla, ukončíme metodu run().

// je-li true, stiskl uživatel klávesu
private boolean pressed = false;
/*
* Tato metoda počká 5 vteřin a pak spustí hru
* nebo ji spustí ihned po stisku libovolné klávesy
*/
public void run(){
  try{
    // vlákno uspíme pouze, nahrál-li se obrázek v pořádku
    if(splash!=null){
      int i = 50;
      while(i>0){
        // uspání aktuálního vlákna na 0,1 vteřiny
        Thread.sleep(100);
        if(pressed){
          // přerušení cyklu, byla-li stisknuta klávesa
          break;
        }
        i–;
      }
    }
  }catch (Exception e){
    e.printStackTrace();
  }
  // zrušení odkazu na obrázek
  splash = null;
}
/*
* Tuto metodu zavolá aplikační manažer,
* nastane-li událost stisk klávesy
*/
protected void keyPressed(int key) {
  pressed = true;
}

Stejným způsobem, jakým jsme se vypořádali s úvodní obrazovkou, můžeme aplikaci přidat i závěrečnou obrazovku, která se zobrazí mezi zavoláním abstraktního příkazu „Konec“ a oznámením aplikačnímu manažeru, že je aplikace připravena se ukončit. Pozor ovšem, abychom uživatele neotrávili reklamními informacemi natolik, že by si od nás příště už žádnou hru nepořídil.

Ke stažení

Veškeré zde uvedené zdrojové kódy, obrázky ke hře a hotovou aplikaci si můžete stáhnout a použít pro vlastní potřebu.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět