<meta http-equiv='pics-label' content='(pics-1.1 "http://www.icra.org/ratingsv02.html" comment "ICRAonline EN v2.0" l gen true for "http://interval.cz" r (nz 1 vz 1 lz 1 oz 1 cz 1) "http://www.rsac.org/ratingsv01.html" l gen true for "http://interval.cz" r (n 0 s 0 v 0 l 0))' />
<p id='prepend'>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.</p>
<h3>T°φdy aplikace</h3>
<p>Hra se bude pro zaΦßtek sklßdat ze t°φ t°φd:</p>
<ul>
<li><code>GameMIDlet</code> - hlavnφ t°φda aplikace rozÜi°ujφcφ abstraktnφ t°φdu <code>javax.microedition.midlet.MIDlet</code>.</li>
<li><code>GameCanvas</code> - t°φda zodpov∞dnß za vlastnφ hru.</li>
<li><code>GameSprite</code> - pomocnß t°φda slou₧φcφ k reprezentaci pohybliv²ch objekt∙. Implementuje rozhranφ t°φdy <code>javax.microedition.lcdui.game.Layer</code> 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 <code>javax.microedition.lcdui.game.Sprite</code> z tΘho₧ hernφho API. U telefon∙, kterΘ implementujφ MIDP 2.0, se mφsto tΘto t°φdy pou₧ije t°φda <code>javax.microedition.lcdui.game.Sprite</code>.</li>
</ul>
<h3>GameMIDlet</h3>
<p>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 <code>GameCanvas</code> a zobrazit ji na displeji.</p>
<br /> <span class='comment'>// Aktivace aplikace po jejφm pobytu v pasivnφm stavu, v naÜem p°φpad∞ zde nenφ pot°eba d∞lat nic.</span>
<br /> }
<br />}
</div>
<p>P°i ukonΦenφ aplikace v metod∞ <code>destroyApp()</code> 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.</p>
<div class='sample'>
protected void destroyApp(boolean arg0) {
<br /> <span class='comment'>/* Dßvßme aplikaΦnφmu mana₧eru najevo, ₧e midlet p°eÜel do zruÜenΘho stavu */</span>
<br /> notifyDestroyed();
<br />}
</div>
<p>Pokud jste v J2ME ·plnφ zaΦßteΦnφci, doporuΦuji p°eΦφst si Φlßnek <a href='http://interval.cz/clanek.asp?article=1595' title='Bittnerovß, Lucie R·t: J2ME v kostce - prvnφ midlet'>J2ME v kostce - prvnφ midlet</a>.</p>
<h3>GameCanvas</h3>
<p>Na displej lze kreslit komponenty, kterΘ implementujφ rozhranφ <code>javax.microedition.lcdui.Displayable</code>. Tyto zobrazitelnΘ komponenty se d∞lφ na zßkladnφ dv∞ skupiny - <em>vysoko·rov≥ovΘ komponenty</em> a <em>nφzko·rov≥ovΘ komponenty</em>.</p>
<p>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 <a href='http://interval.cz/clanek.asp?article=1668' title='Bittnerovß, Lucie R·t: J2ME v kostce - kreslφme na displej'>J2ME v kostce - kreslφme na displej</a>). To je pro hru samoz°ejm∞ nedostateΦnΘ, tak₧e t°φda <code>GameCanvas</code> bude rozÜi°ovat t°φdu <code>javax.microedition.lcdui.Canvas</code>, 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 <code>CustomItem</code>, pomocφ kterΘ je mo₧nΘ napsat i jednoduÜÜφ hry, ale jejφ popis nespadß do rßmce tohoto Φlßnku.</p>
<p>T°φda <code>GameCanvas</code> 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.</p>
<h4>Abstraktnφ p°φkaz</h4>
<p>Po svΘm p°edku <code>javax.microedition.lcdui.Canvas</code> t°φda <code>GameCanvas</code> 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 <code>GameCanvas</code>):</p>
<div class='sample'>
<span class='comment'>/* vytvo°enφ novΘho p°φkazu, prvnφ parametr urΦuje jeho text, druh² jeho typ a t°etφ prioritu */</span>
<br />endCmd = new Command("Konec", Command.EXIT, 1);
<p>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.</p>
<p>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.</p>
<div class='image'>
<img src='podklady/bittnerova/1158/1.png' title='Nokia - dva p°φkazy' alt='Nokia - dva p°φkazy' />
<br /><span class='comment'>Nokia - dva p°φkazy</span>
<p>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.</p>
<p>Jak si jist∞ pozornφ Φtenß°i vÜimli, t°φda <code>GameCanvas</code> implementuje rozhranφ <code>javax.microedition.lcdui.CommandListener</code>. Toto rozhranφ obsahuje pouze metodu <code>commandAction(Command command, Displayable displayable)</code>, kterß slou₧φ k obsluze udßlosti vyvolßnφ p°φkazu. Parametr <code>command</code> obsahuje p°φkaz, kter² byl vyvolßn, a parametr <code>displayable</code> obsahuje zobrazitelnou komponentu, v nφ₧ udßlost nastala. Nßs bude zajφmat pouze parametr <code>command</code>, 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.</p>
<div class='sample'>
public void commandAction(Command command, Displayable displayable) {
<br /> if(command==endCmd){
<br /> midlet.destroyApp(true);
<br /> }
<br />}
</div>
<h4>Kreslenφ na displej</h4>
<p>VeÜkerΘ kreslenφ probφhß v metod∞ <code>paint(Graphics graphics)</code> zd∞d∞nΘ ze t°φdy <code>javax.microedition.lcdui.Canvas</code>. 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 <code>graphics</code> se m∙₧e pou₧φvat pouze v rßmci metody <code>paint()</code> (a samoz°ejm∞ takΘ v rßmci metod volan²ch z tΘto metody).</p>
<p>P°i ka₧dΘm volßnφ metody jsou nastaveny n∞kterΘ vlastnosti grafiky na v²chozφ hodnoty:</p>
<ul>
<li>aktußlnφ barva je Φernß</li>
<li>font je nastaven na v²chozφ font</li>
<li>styl Φßry je nep°eruÜovan² (<code>Graphics.SOLID</code>)</li>
<li>poΦßtek sou°adnic je v levΘm hornφm rohu displeje</li>
</ul>
<p>AplikaΦnφ mana₧er zavolß metodu <code>paint()</code> jenom v p°φpad∞, ₧e je <code>Canvas</code> prßv∞ zobrazen² na displeji. O p°ekreslenφ displeje lze za₧ßdat metodou <code>repaint()</code>, kterß neblokuje b∞h aplikace (ukonΦφ se nezßvisle na volßnφ metody <code>paint()</code>). To vÜak neznamenß, ₧e bude displej okam₧it∞ p°ekreslen, nebo¥ jeho p°ekreslenφ zßvisφ na viditelnosti p°ekreslovanΘ oblasti.</p>
<p>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 <code>repaint()</code> jeÜt∞ metodu <code>serviceRepaints()</code>. 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 <code>Canvas</code> nenφ viditeln², v tom p°φpad∞ volßnφ metody <code>serviceRepaints()</code> neprovede nic. P°i zobrazovßnφ n∞jakΘ animace se celkem hodφ vykreslit vÜechny jejφ kroky, tak₧e budeme volat funkci <code>repaint()</code> spolu s funkcφ <code>serviceRepaints()</code>.</p>
<p>V konstruktoru t°φdy <code>GameCanvas</code> 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.</p>
<p>Obrßzky v <em>J2MEWTK</em> dßme do adresß°e <em>J2MEWTK_HOME/Blabouch/res</em>. 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:</p>
<p>P°ed ukßzkou metody <code>paint()</code> se hodφ jeÜt∞ blφ₧e popsat zp∙sob umis¥ovßnφ obrßzk∙ a textov²ch °et∞zc∙ na displej. Metody <code>Graphics.drawImage()</code> a <code>Graphics.drawString()</code> 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 <samp>|</samp>) konstanty t°φdy <code>Graphics</code> 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:</p>
<div class='sample'>
protected void paint(Graphics g) {
<br /> <span class='comment'>// nastavenφ barvy na bφlou</span>
<p>T°φdu <code>GameSprite</code> pou₧ijeme k reprezentaci lodi, mincφ a bomb. Jak u₧ je °eΦeno v²Üe, je to velmi minimalistickß implementace t°φdy <code>Sprite</code> z hernφho rozhranφ MIDP 2.0. T°φda <code>Sprite</code> navφc umo₧≥uje spoustu praktick²ch v∞cφ, nap°φklad animace obrßzk∙ Φi jejich transformace. TakΘ metoda <code>collidesWith(GameSprite sprite, boolean pixelLevel)</code> v <code>GameSprite</code> 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 <code>Sprite</code>.</p>
<p>T°φda <code>GameSprite</code> obsahuje jeden obrßzek a pozici jeho levΘho hornφho rohu, kterou lze m∞nit relativn∞ (<samp>move(int dx, int dy)</samp>) nebo nastavit absolutn∞ (<samp>setPosition(int x, int y)</samp>). Za vykreslenφ je zodpov∞dnß metoda <code>paint(Graphics g)</code>. T°φda <code>GameSprite</code> m∙₧e b²t viditelnß Φi neviditelnß. Je-li neviditelnß, metoda <code>paint(Graphics g)</code> neud∞lß nic.</p>
<h3>Ke sta₧enφ</h3>
<p>VeÜkerΘ zde uvedenΘ <a href='podklady/bittnerova/1158/zdroj.zip'>zdrojovΘ k≤dy i obrßzky</a> ke h°e a dalÜφ materißl si m∙₧ete stßhnout a pou₧φt.</p>
<div id='article-about-author'>programßtor û analytik <a href="http://www.amaio.cz">Amaio Technologies</a></div>
</div>
<div class='refer'><h3><a href='http://interval.cz/__redirect/redirect.asp?what=interval_offline&url=http://interval.cz/serial.asp?serial=225' title='p°ehled Φlßnk∙ vΦetn∞ anotacφ'>Kdo si J2ME, nezlobφ</a></h3><p>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!</p><ul><li><a href='http://interval.cz/__redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=3889'>Kdo si J2ME, nezlobφ - trocha pohybu</a></li><li><strong>Kdo si J2ME, nezlobφ - zßklad hry</strong> (prßv∞ Φtete)</li><li><a href='http://interval.cz/__redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=3861'>Kdo si J2ME, nezlobφ - ·vod pro ka₧dΘho</a></li></ul></div>