Navigace

Hlavnφ menu

 

Kdo si J2ME, nezlobφ - zßklad hry

V tomto Φlßnku se u₧ skuteΦn∞ pustφme do programovßnφ. ZaΦneme ·pln∞ minimßlnφm zßkladem, kter² pak budeme pozd∞ji rozÜi°ovat o r∙znΘ vymo₧enosti. Nejprve vÜak musφme aplikaci spustit a ukonΦit a mezi tφm takΘ n∞co nakreslit na displej.

T°φdy aplikace

Hra se bude pro zaΦßtek sklßdat ze t°φ t°φd:

  • GameMIDlet - hlavnφ t°φda aplikace rozÜi°ujφcφ abstraktnφ t°φdu javax.microedition.midlet.MIDlet.
  • GameCanvas - t°φda zodpov∞dnß za vlastnφ hru.
  • GameSprite - pomocnß t°φda slou₧φcφ k reprezentaci pohybliv²ch objekt∙. Implementuje rozhranφ t°φdy javax.microedition.lcdui.game.Layer z hernφho API MIDP 2.0, ke kterΘmu p°idßvß navφc jeÜt∞ metodu pro kontrolu vzßjemn²ch kolizφ objekt∙ dle vzoru t°φdy javax.microedition.lcdui.game.Sprite z tΘho₧ hernφho API. U telefon∙, kterΘ implementujφ MIDP 2.0, se mφsto tΘto t°φdy pou₧ije t°φda javax.microedition.lcdui.game.Sprite.

GameMIDlet

V naÜem p°φpad∞ bude hlavnφ t°φda velmi jednoduchß, proto₧e pφÜeme minimalistickou aplikaci bez v∞tÜφ logiky. JedinΘ, co musφme ud∞lat, je p°i spuÜt∞nφ aplikace vytvo°it instanci t°φdy GameCanvas a zobrazit ji na displeji.

protected void startApp() throws MIDletStateChangeException {
   if(canvas==null){
      // SpuÜt∞nφ aplikace
      canvas = new GameCanvas(this);
      Display.getDisplay(this).setCurrent(canvas);
      } else {
      // Aktivace aplikace po jejφm pobytu v pasivnφm stavu, v naÜem p°φpad∞ zde nenφ pot°eba d∞lat nic.
   }
}

P°i ukonΦenφ aplikace v metod∞ destroyApp() zatφm takΘ nemusφme d∞lat skoro nic. Pokud bychom vÜak cht∞li uklßdat aktußlnφ stav hry, pat°ila by tato akce sem.

protected void destroyApp(boolean arg0) {
   /* Dßvßme aplikaΦnφmu mana₧eru najevo, ₧e midlet p°eÜel do zruÜenΘho stavu */
   notifyDestroyed();
}

Pokud jste v J2ME ·plnφ zaΦßteΦnφci, doporuΦuji p°eΦφst si Φlßnek J2ME v kostce - prvnφ midlet.

GameCanvas

Na displej lze kreslit komponenty, kterΘ implementujφ rozhranφ javax.microedition.lcdui.Displayable. Tyto zobrazitelnΘ komponenty se d∞lφ na zßkladnφ dv∞ skupiny - vysoko·rov≥ovΘ komponenty a nφzko·rov≥ovΘ komponenty.

Vysoko·rov≥ovΘ komponenty neumo₧≥ujφ odchytßvßnφ udßlostφ klßvesnice, ani kreslenφ jednoduÜÜφch ·tvar∙ na konkrΘtnφ sou°adnice. Hodφ se nap°φklad k zobrazovßnφ formulß°∙ a seznam∙ polo₧ek (viz Φlßnek J2ME v kostce - kreslφme na displej). To je pro hru samoz°ejm∞ nedostateΦnΘ, tak₧e t°φda GameCanvas bude rozÜi°ovat t°φdu javax.microedition.lcdui.Canvas, kterß jako jedinß ve specifikaci MIDP 1.0 umo₧≥uje nφzko·rov≥ovou grafiku. Specifikace MIDP 2.0 rozÜi°uje nabφdku nφzko·rov≥ov²ch komponent o formulß°ovou polo₧ku CustomItem, pomocφ kterΘ je mo₧nΘ napsat i jednoduÜÜφ hry, ale jejφ popis nespadß do rßmce tohoto Φlßnku.

T°φda GameCanvas je celkem komplexnφ. Musφ vykreslovat hru, pravideln∞ aktualizovat polohu p°edm∞t∙, reagovat na stisk klßves u₧ivatelem a umo₧nit u₧ivateli ukonΦit aplikaci.

Abstraktnφ p°φkaz

Po svΘm p°edku javax.microedition.lcdui.Canvas t°φda GameCanvas zd∞dila mo₧nost ovlßdßnφ pomocφ abstraktnφch p°φkaz∙. Toto ovlßdßnφ je spoleΦnΘ se vÜemi zobraziteln²mi komponentami. PraktickΘ provedenφ je nßsledujφcφ (ukßzka z konstruktoru t°φdy GameCanvas):

/* vytvo°enφ novΘho p°φkazu, prvnφ parametr urΦuje jeho text, druh² jeho typ a t°etφ prioritu */
endCmd = new Command("Konec", Command.EXIT, 1);
/* p°idßnφ p°φkazu komponent∞ */
addCommand(endCmd);
/* nastavenφ posluchaΦe udßlostφ, kter² obsluhuje vyvolßnφ p°φkazu u₧ivatelem */
setCommandListener(this);

Umφst∞nφ a zp∙sob zobrazenφ abstraktnφch p°φkaz∙ na displeji je zcela zßvislΘ na implementaci MIDP v telefonu. ObvyklΘ nap°φklad b²vß, ₧e jeden p°φkaz se zobrazφ na displeji dole k n∞kterΘmu ze softkey (kontextovß klßvesa) a druh² softkey obsahuje rozbalovacφ menu se zbyl²mi p°φkazy. Tento zp∙sob zobrazovßnφ mß tu nev²hodu, ₧e aplikace nemß k dispozici cel² displej, ale je ochuzenß o pruh s abstraktnφmi p°φkazy.

Obrßzek ukazuje, jak abstraktnφ p°φkazy zobrazujφ telefony znaΦky Nokia. Jsou-li p°φkazy maximßln∞ dva, vejdou se vÜechny najednou na displej, je-li jich vφc, vejde se na displej jeden a ostatnφ se zobrazφ po stisknutφ odpovφdajφcφho softkey na zvlßÜtnφ obrazovce.

Nokia - dva p°φkazy
Nokia - dva p°φkazy
Nokia - vφce p°φkaz∙
Nokia - vφce p°φkaz∙
Nokia - menu
Nokia - menu

Telefony znaΦky Siemens p°φtomnost abstraktnφch p°φkaz∙ pouze naznaΦφ Üipkou v pravΘm dolnφm rohu displeje a po stisku odpovφdajφcφho softkey teprve zobrazφ vÜechny p°φkazy.

Siemens - naznaΦenφ p°φtomnosti p°φkaz∙
Siemens - naznaΦenφ p°φtomnosti p°φkaz∙
Siemens - menu
Siemens - menu

Jak si jist∞ pozornφ Φtenß°i vÜimli, t°φda GameCanvas implementuje rozhranφ javax.microedition.lcdui.CommandListener. Toto rozhranφ obsahuje pouze metodu commandAction(Command command, Displayable displayable), kterß slou₧φ k obsluze udßlosti vyvolßnφ p°φkazu. Parametr command obsahuje p°φkaz, kter² byl vyvolßn, a parametr displayable obsahuje zobrazitelnou komponentu, v nφ₧ udßlost nastala. Nßs bude zajφmat pouze parametr command, proto₧e v aplikaci zatφm mßme jen jednu zobrazitelnou komponentu. Kdybychom vÜak m∞li aplikaci slo₧enou z vφce grafick²ch komponent, byl by nap°φklad p°φkaz "Zp∞t" typickou ukßzkou p°φkazu, kter² obsahujφ skoro vÜechny obrazovky a jeho₧ zpracovßnφ se liÜφ v zßvislosti na obrazovce, kde udßlost nastala.

public void commandAction(Command command, Displayable displayable) {
   if(command==endCmd){
      midlet.destroyApp(true);
   }
}

Kreslenφ na displej

VeÜkerΘ kreslenφ probφhß v metod∞ paint(Graphics graphics) zd∞d∞nΘ ze t°φdy javax.microedition.lcdui.Canvas. Nelze p°edpoklßdat, ₧e je stßle zobrazenΘ, co jsme nakreslili p°i p°edchozφm volßnφ tΘto metody, je pot°eba poka₧dΘ nakreslit vÜe znova. Parametr graphics se m∙₧e pou₧φvat pouze v rßmci metody paint() (a samoz°ejm∞ takΘ v rßmci metod volan²ch z tΘto metody).

P°i ka₧dΘm volßnφ metody jsou nastaveny n∞kterΘ vlastnosti grafiky na v²chozφ hodnoty:

  • aktußlnφ barva je Φernß
  • font je nastaven na v²chozφ font
  • styl Φßry je nep°eruÜovan² (Graphics.SOLID)
  • poΦßtek sou°adnic je v levΘm hornφm rohu displeje

AplikaΦnφ mana₧er zavolß metodu paint() jenom v p°φpad∞, ₧e je Canvas prßv∞ zobrazen² na displeji. O p°ekreslenφ displeje lze za₧ßdat metodou repaint(), kterß neblokuje b∞h aplikace (ukonΦφ se nezßvisle na volßnφ metody paint()). To vÜak neznamenß, ₧e bude displej okam₧it∞ p°ekreslen, nebo¥ jeho p°ekreslenφ zßvisφ na viditelnosti p°ekreslovanΘ oblasti.

Pokud si chceme na p°ekreslenφ displeje poΦkat a teprve potΘ pokraΦovat v b∞hu aplikace, musφme pou₧φt po volßnφ metody repaint() jeÜt∞ metodu serviceRepaints(). Tato metoda si vynutφ obsluhu vÜech zatφm neobslou₧en²ch po₧adavk∙ na p°ekreslenφ displeje a ukonΦφ se teprve a₧ po jejφm provedenφ. Jedinou v²jimkou je p°φpad, kdy Canvas nenφ viditeln², v tom p°φpad∞ volßnφ metody serviceRepaints() neprovede nic. P°i zobrazovßnφ n∞jakΘ animace se celkem hodφ vykreslit vÜechny jejφ kroky, tak₧e budeme volat funkci repaint() spolu s funkcφ serviceRepaints().

V konstruktoru t°φdy GameCanvas je takΘ pot°eba nahrßt obrßzky. V naÜem p°φpad∞ m∙₧eme nahrßt klidn∞ vÜechny, vΦetn∞ t∞ch, kterΘ pou₧ijeme a₧ p°i v²buchu lodi. P°i tvorb∞ aplikacφ s v∞tÜφm poΦtem velk²ch obrßzk∙ se vÜak pravideln∞ stßvß, ₧e se vÜechny nevejdou telefonu do pam∞ti. Pak je pot°eba d∙sledn∞ uvol≥ovat vÜechny zdroje v okam₧iku, kdy nejsou pot°eba, a nahrßvat je a₧ t∞sn∞ p°ed jejich pou₧itφm.

Obrßzky v J2MEWTK dßme do adresß°e J2MEWTK_HOME/Blabouch/res. Tyto obrßzky p°i vytvß°enφ JAR souboru s aplikacφ skonΦφ p°φmo v ko°eni tohoto JAR souboru a nahrajφ se nßsledujφcφm zp∙sobem:

try{
   Image background = Image.createImage("/background.png");
} catch(Exception e){
   e.printStackTrace();
}

P°ed ukßzkou metody paint() se hodφ jeÜt∞ blφ₧e popsat zp∙sob umis¥ovßnφ obrßzk∙ a textov²ch °et∞zc∙ na displej. Metody Graphics.drawImage() a Graphics.drawString() v prvnφm parametru dostßvajφ objekt, kter² chceme vykreslit. Druh² a t°etφ parametr urΦujφ sou°adnice kotvy, poslednφ parametr pak °φkß, v jakΘm mφst∞ obrßzku nebo textu se kotva nachßzφ. Umφst∞nφ kotvy se definuje pomocφ bitovΘho souΦtu (operßtor |) konstanty t°φdy Graphics definujφcφ jejφ x sou°adnici a konstanty definujφcφ jejφ y sou°adnici. V nßsledujφcφ ukßzce je kotva umφst∞na v obou p°φpadech v levΘm hornφm rohu objektu:

protected void paint(Graphics g) {
   // nastavenφ barvy na bφlou
   g.setColor(0xffffff);
   // p°ekreslenφ celΘho displeje aktußlnφ barvou
   g.fillRect(0,0,getWidth(), getHeight());
   // nakreslenφ obrßzku background
   g.drawImage(background, 0, 0, Graphics.TOP | Graphics.LEFT);

   /* zde se vykreslujφ jednotlivΘ p°edm∞ty */

   // nastavenφ barvy na Φervenou
   g.setColor(0x840400);
   // nakreslenφ poΦtu bod∙
   g.drawString("" + score, 0, 2, Graphics.TOP | Graphics.LEFT);
}

GameSprite

T°φdu GameSprite pou₧ijeme k reprezentaci lodi, mincφ a bomb. Jak u₧ je °eΦeno v²Üe, je to velmi minimalistickß implementace t°φdy Sprite z hernφho rozhranφ MIDP 2.0. T°φda Sprite navφc umo₧≥uje spoustu praktick²ch v∞cφ, nap°φklad animace obrßzk∙ Φi jejich transformace. TakΘ metoda collidesWith(GameSprite sprite, boolean pixelLevel) v GameSprite bohu₧el v rßmci MIDP 1.0 nemß mo₧nost zjistit kolize na ·rovni pixel∙ (dva obrßzky kolidujφ pouze tehdy, p°ekr²vajφ-li se nepr∙hledn²mi pixely), tak₧e druh² parametr je zde jen do poΦtu z d∙vodu kompatibility se t°φdou Sprite.

T°φda GameSprite obsahuje jeden obrßzek a pozici jeho levΘho hornφho rohu, kterou lze m∞nit relativn∞ (move(int dx, int dy)) nebo nastavit absolutn∞ (setPosition(int x, int y)). Za vykreslenφ je zodpov∞dnß metoda paint(Graphics g). T°φda GameSprite m∙₧e b²t viditelnß Φi neviditelnß. Je-li neviditelnß, metoda paint(Graphics g) neud∞lß nic.

Ke sta₧enφ

VeÜkerΘ zde uvedenΘ zdrojovΘ k≤dy i obrßzky ke h°e a dalÜφ materißl si m∙₧ete stßhnout a pou₧φt.

Bittnerovß, Lucie R·t (12. 5. 2005)
programßtor û analytik Amaio Technologies

Kdo si J2ME, nezlobφ

Projdeme si na konkrΘtnφm p°φkladu krok po kroku vznik J2ME hry a budeme p°itom °eÜit r∙znΘ problΘmy, kterΘ v²voj aplikace na mobilnφ telefon provßzejφ. P°edpokladem je znalost syntaxe programovacφho jazyka Java. Tato sΘrie Φlßnk∙ dosud nebyla ukonΦena!