1 CLDC, MIDP verze a současnost



Podobné dokumenty
JSR tutorial 1 Úvod do JSR-184

(JME) Vybrané partie z jazyka Java (NPRG021) Jiří Tomeš

2 Grafický výstup s využitím knihovny

Návod k použití softwaru Solar Viewer 3D

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

umenugr JEDNOTKA PRO VYTVÁŘENÍ UŽIVATELSKÝCH GRAFICKÝCH MENU Příručka uživatele a programátora


VY_32_INOVACE_INF.19. Inkscape, GIMP, Blender

1. Dědičnost a polymorfismus

Bridge. Známý jako. Účel. Použitelnost. Handle/Body

Programátorská příručka

Práce s texty, Transformace rastru, Připojení GPS

Hierarchický model Josef Pelikán CGG MFF UK Praha. 1 / 16

Obsah. Kapitola 1. Předmluva 11 O této knize 13 Konvence...13

Reliance 3 design OBSAH

JAVA. Java Micro Edition

JSR tutorial 2 Transformace v JSR-184

NetBeans platforma. Evropský sociální fond Praha & EU: Investujeme do vaší budoucnosti

Obsah přednášky 9. Skrývání informací. Skrývání informací. Zapouzdření. Skrývání informací. Základy programování (IZAPR, IZKPR) Přednáška 9

Třída DrawingTool. Obrázek 1: Prázdné okno připravené pro kreslení

PHP framework Nette. Kapitola Úvod. 1.2 Architektura Nette

Teoretické minimum z PJV

Při studiu tohoto bloku se předpokládá, že student je zvládá základy programování v jazyce Java s využitím vývojového prostředí NetBeans.

1. Programování proti rozhraní

TÉMATICKÝ OKRUH Softwarové inženýrství

Manuál k programu KaraokeEditor

Obsah. Předmluva 13 Zpětná vazba od čtenářů 14 Zdrojové kódy ke knize 15 Errata 15

Rastrová grafika. Grafický objekt je zaznamenán jednotlivými souřadnicemi bodů v mřížce. pixel ( picture element ) s definovanou barvou

Úloha 1. Text úlohy. Vyberte jednu z nabízených možností: NEPRAVDA. PRAVDA Úloha 2. Text úlohy

Zdroj:

11 Diagram tříd, asociace, dědičnost, abstraktní třídy

Programovací jazyk Java

Obsah přednášky. 12. Dokumentace zdrojového kódu Tvorba elektronické dokumentace UML. Co je diagram tříd. Ing. Ondřej Guth

Tvorba kurzu v LMS Moodle

DATOVÉ FORMÁTY GRAFIKY, JEJICH SPECIFIKA A MOŽNOSTI VYUŽITÍ

TECHNOLOGIE ELASTICKÉ KONFORMNÍ TRANSFORMACE RASTROVÝCH OBRAZŮ

02. HODINA. 2.1 Typy souborů a objektů. 2.2 Ovládací prvky Label a TextBox

Výčtový typ strana 67

Připravil: David Procházka. Vertex Buffer Objects

ZAŘÍZENÍ PRO VZDÁLENÝ SBĚR A PŘENOS DAT FIRMWARE

Matematika v programovacích

Generické programování

Úvod do programovacích jazyků (Java)

Vývoj multiplatformní aplikace v Qt

Architektura rodiny operačních systémů Windows NT Mgr. Josef Horálek

3. Je defenzivní programování technikou skrývání implementace? Vyberte jednu z nabízených možností: Pravda Nepravda

Algoritmizace a programování

Programování v C++ 2, 4. cvičení

Java aplety. Předávání parametrů z HTML

Programování v jazyce C a C++

Využití ICT techniky především v uměleckém vzdělávání. Akademie - VOŠ, Gymn. a SOŠUP Světlá nad Sázavou

1 Webový server, instalace PHP a MySQL 13

Uživatelský manuál. Aplikace GraphViewer. Vytvořil: Viktor Dlouhý

Algoritmizace a programování

Vývojové prostředí,průvodce novou aplikací

Programování v Javě I. Únor 2009

typová konverze typová inference

9. Rozšiřující desky Evb_Display a Evb_keyboard

Programování v Javě I. Leden 2008

PŘETĚŽOVÁNÍ OPERÁTORŮ

Vytvořil Institut biostatistiky a analýz, Masarykova univerzita J. Jarkovský, L. Dušek, M. Cvanová. 5. Statistica

Programování v jazyce C a C++

První kroky s METEL IEC IDE

Pokročilé programování v jazyce C pro chemiky (C3220) Třídy v C++

Stručný obsah. Úvod 15. KAPITOLA 1 První kroky v systému Windows KAPITOLA 2 Hlavní panel a jeho možnosti 41. KAPITOLA 3 Soubory a složky 51

8 Třídy, objekty, metody, předávání argumentů metod

Obsah. Úvod 11 Základy programování 11 Objektový přístup 11 Procvičování 11 Zvláštní odstavce 12 Zpětná vazba od čtenářů 12 Errata 13

J2ME. Java 2 Micro Edition. David Stach Ondřej Dušek

UJO Framework. revoluční architektura beans. verze

FORTANNS. 22. února 2010

Windows a real-time. Windows Embedded

GIS Geografické informační systémy

Platforma.NET 11.NET Framework 11 Visual Basic.NET Základní principy a syntaxe 13

MBI - technologická realizace modelu

MATURITNÍ OTÁZKY ELEKTROTECHNIKA - POČÍTAČOVÉ SYSTÉMY 2003/2004 PROGRAMOVÉ VYBAVENÍ POČÍTAČŮ

Vektorové grafické formáty

TAOS321. Administrace. příručka správce systému. informační terminál systému JSVV

Tematický celek Proměnné. Proměnné slouží k dočasnému uchovávání hodnot během provádění aplikace Deklarace proměnných

Software602 Form Designer

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

Zobrazte si svazy a uspořádané množiny! Jan Outrata

Fakulta informačních technologíı. IZG cvičení 6. - Zobrazování 3D scény a základy OpenGL 1 / 38

IVT. Grafické formáty. 8. ročník

5a. Makra Visual Basic pro Microsoft Escel. Vytvořil Institut biostatistiky a analýz, Masarykova univerzita J. Kalina

INFORMATIKA. Grafické studio ve škole

Základy informatiky část 10

Software pro vzdálenou laboratoř

Google Web Toolkit. Martin Šurkovský, SUR března Katedra informatiky

CSS Stylování stránek. Zpracoval: Petr Lasák

Konstruktory a destruktory

4a. Makra Visual Basic pro Microsoft Excel Cyklické odkazy a iterace Makra funkce a metody

Podklad pro tvorbu ilayer typu

Jazyk C# (seminář 9)

DSL manuál. Ing. Jan Hranáč. 27. října V této kapitole je stručný průvodce k tvorbě v systému DrdSim a (v

Projekt Obrázek strana 135

Obsah. Základy práce s rastry. GIS1-5. cvičení. ČVUT v Praze, Fakulta stavební, katedra mapování a kartografie

Programové konvence, dokumentace a ladění. Programování II 2. přednáška Alena Buchalcevová

Dynamicky vázané metody. Pozdní vazba, virtuální metody

Možnosti tisku v MarushkaDesignu

Transkript:

1 CLDC, MIDP verze a současnost Vydávání a revize takzvaných JSR (Java Specification Request), což jsou finální uvolněné specifikace pro platformu Java zajišťuje skupina JCP (Java Community Process), založená v roce 1998. 1.1 CLDC V současnosti existují dvě verze CLDC a to původní 1.0 (JSR-30) a novější 1.1 (JSR-139). Existuje ještě verze 1.0.4, ta však byla použita celkem pouze asi v sedmi zařízeních firmy Samsung, tudíž se o ní nebudu zmiňovat. Starší verze, CLDC 1.0, obsahuje, jak již bylo uvedeno definice pro VM, sítě, bezpečnost a základní knihovny. Podrobnější specifikace lze nalézt na internetu [4]. Verze 1.1 se příliš neliší, přidává však velmi důležitou věc a to sice podporu datových typů s plovoucí desetinnou čárkou (float, double). Ty v CLDC 1.0 neexistovaly, protože nebyly hardwarově podporovány. V praxi se tudíž používala (a používá) metoda fixed point, což znamená, že v programu jsou všechna čísla vynásobená např. 10 3 (od toho název fixed point pevná desetinná čárka/přesnost), díky čemuž lze do 3 nejnižších řádů ukládat údaje o desetinných místech. V případě tisku na výstup je pak potřeba číslo správně zobrazit. Dalšími změnami v CLDC 1.1 jsou tzv. weak references 1 nebo zvýšení minimální paměti ze 160kB na 192kB. 1.2 MIDP Tak jako u CLDC i u MIDP existují v současnosti dvě verze 1.0 (JSR-37) a 2.0 (JSR-118). I zde existuje ještě meziverze MIDP 2.1, ta je ale teprve uváděna na trh a vyplňuje jakousi mezeru mezi MIDP 2.0 a dlouho očekávaným MIDP 3.0. MIDP 1.0 implementuje základní rozhraní pro práci s GUI, podporu sítí, RMS (Record Management System) systém pro perzistentní ukládání dat a další. V praxi se však ukázalo, že trpí vážnými nedostatky: nemožnost přístupu k jednotlivým pixelům, nulová podpora pro zvuky a fullscreen (celoobrazovkové) zobrazení, sítě pouze pro bezestavový protokol HTTP či neexistující fronta pro stisk kláves. Tyto nedostatky řešily různá proprietární API výrobců telefonů, jejichž použitím se však aplikace stala nepřenositelnou. A tak 5. listopadu 2002 byla uvolněna specifikace MIDP verze 2.0, přidávající třídy: javax.microedition.media třídy pro podporu zvuku a videa, jsou podtřídou MMAPI 1 Více o weak references na Wikipedii: http://en.wikipedia.org/wiki/weak_reference - 1 -

(více v kapitole 7.1) javax.microedition.lcdui.game zvláštní API pro usnadnění vývoje 2D her sprity, tile manažer, vrstvy, rozšířený canvas (zabudovaný double buffer, klávesová fronta) javax.microedition.pki API pro práci s certifikáty Dalšími přidanými vlastnostmi je například tzv. push registr, který umožňuje spouštění midletu při iniciaci příchozího spojení či sdílení perzistentního úložiště dat mezi aplikacemi. Profil MIDP 3.0 (JSR-271) je zatím stále ve vývoji, nicméně obsahuje mnoho novinek a proto by byla chyba ho zde opomenout. Protože MIDP zařízení jsou mnohem výkonnější než před lety a mají mnohem více paměti, vznikl tlak na požadavek zavedení běhu několika aplikací najednou, respektive běh midletů na pozadí. Dále je zde možnost spouštění midletů hned po startu zařízení, specifikuje komunikační kanál mezi midlety, vylepšuje UI, zavádí podporu více displejů, IPv6 a podstatně rozšiřuje možnosti připojení k síti. Stadium vývoje je možné sledovat na stránkách organizace JCP [5]. Verze CLDC a MIDP jsou na sobě nezávislé a mohou se libovolně kombinovat, tudíž existují zařízení jak s kombinací CLDC 1.1 a MIDP 2.0, tak i CLDC 1.0 a MIDP 2.0. 1.3 Současnost mobilních zařízení V současnosti jsou nejrozšířenějšími MIDP zařízeními mobilní telefony. Vývoj v nich stačil urazit už relativně dlouhou cestu, vždyť první telefony podporující Javu Motorola i80s a i50sx byly uvedeny na trh již v dubnu roku 2001. Černobílý displej s na tu dobu velkým rozlišením 119x64, 256kB heap paměti, 50kB omezení na JAR soubor a žádný zvuk - to jsou parametry i80s. Dnes je nejrozšířenější platformou patrně Series 40 od firmy Nokia, která ve svých už pěti revizích zahrnuje širokou škálu zařízení, od nejstarších, jako je Nokia 2355 se standardním displejem o rozlišení 128x128 až po poslední modely typu Nokia 6301 s QVGA displejem (240x320). Tato platforma představuje dnes jakýsi minimální standard a proto se na ní také primárně vyvíjí aplikace, které se následnou portací pouze rozšiřují. Opačný postup by byl totiž násobně obtížnější a tím pádem i dražší. Standardem je velikost JAR archivu 64kB, heap paměť kolem 200kB u nejslabších modelů, 20kB místa na RMS a standardní rozlišení 128x96 (128x128 u fullscreen módu s použitím Nokia API). 2 Sestavení a nasazení aplikace Abychom mohli aplikaci distribuovat, nestačí nám jen přeložit zdrojové soubory. Poté co máme aplikaci napsanou a přeloženou, je potřeba class soubory preverifikovat. Jak již bylo zmíněno, ve velké Javě se toto děje až při spouštění aplikace a stará se o to virtuální stroj - 2 -

(JVM), v MIDP ale potřebujeme svést co nejvíce těžké práce na počítač na kterém sestavujeme aplikaci. Po preverifikaci nám zbudou upravené class soubory, které konečně můžeme zabalit do JAR archivu. Svou strukturou se jedná o běžný archiv typu ZIP. V něm může být jeden či více midletů a jejich pomocných tříd, zdroje v podobě dalších souborů (texty, obrázky, apod.) a nakonec tzv. MANIFEST soubor. Ten musí být v JARu v adresáři META-INF a jedná se o textový soubor podobný deskriptoru. Deskriptor aplikace je textový soubor s příponou JAD a obsahuje popis soupravy MIDletů ve formátu atribut:hodnota. Atributů je relativně mnoho - některé jsou povinné (jméno aplikace, velikost v bytech, URL JAR souboru atd.) a některé ne. Programátor si může dokonce definovat vlastní, které lze v aplikaci číst metodou Midlet.getAppProperty(String atribut). Hlavní činnost deskriptoru je při stahování aplikací do telefonu, protože poskytuje všechny důležité informace ještě předtím, než se přenese samotná aplikace. Jelikož sestavování aplikace je komplikovaný a náročný proces, vznikly nástroje které ho zjednodušují. Od různých stupňů podpory automatizace ve vývojových prostředích (WTK, EclipseME, Netbeans u těchto nástrojích pojednává kapitola 8) až po skripty. 2.1 Ant, Antenna a J2ME Jak již bylo řečeno, vývoj aplikací na mobilní zařízení a to především využívající multimédií a různých specifik daných modelů kladou velké požadavky na vývojáře. Desítky různých odlišností ve specifikacích zařízení vyžadují portaci (úpravu) aplikace na každý model zvlášť. Aby se vývoj zjednodušil a zefektivnil, vznikl Ant. Ant (respektive jeho odnož pro J2ME Antenna 1 ) je systém pro sestavování aplikací na základě XML skriptu. Podpora Antu (potažmo Antenny) je obvykle integrována ve většině vývojových nástrojů cílených na jazyk Java. Co vlastně Ant umí: základní operace se soubory a adresáři (vytvoření/přejmenování/mazání), spouštění externích programů, preprocessing (úprava kódu ještě před samotným překladem - jako v jazyce C), build, preverifikace, obfuskace, zabalení, vytvoření deskriptoru, spuštění emulátoru a další. Pro bližší informace v češtině je výborný zdroj [2]. Příklad 4.1 Ukázka Antenna skriptu <?xml version="1.0"?> <project name="thegame" default="build" basedir="."> 1 Domovská stránka: http://antenna.sourceforge.net - 3 -

<!-- WTK domaci adresar --> <property name="wtk.home" value="c:\wtk22" /> <!-- Cil k MIDP API--> <property name="wtk.midpapi" value="${wtk.home\lib\midpapi.zip" /> <!-- nazev aplikace --> <property name="midlet.name" value="thegame" /> <!-- build --> <target name="build"> <!-- JAD soubor --> <wtkjad jadfile="${midlet.name.jad" jarfile="${midlet.name.jar" name="${midlet.name"> <midlet name="${midlet.name" class="main" /> </wtkjad> <!-- překlad --> <wtkbuild srcdir="src_prep" destdir="classes" target="1.1" source="1.2" preverify="false" /> <!-- zabaleni --> <wtkpackage jarfile="${midlet.name.jar" jadfile="${midlet.name.jad" obfuscate="true" preverify="true" basedir="classes" libclasspath="res" /> <!-- spusteni emulatoru --> <wtkrun jadfile="${midlet.name.jad" device="nokia_s40_dp20_sdk_1_1" wait="true"/> </target> </project> 2.2 Bajtkód a obfuskace Zdrojový kód Javy se překládá do zvláštního instrukčního jazyka zvaného bajtkód (Bytecode). Díky tomu je možné jednou přeloženou aplikaci do bajtkódu spustit na libovolném virtuálním stroji (VM) Javy na téměř libovolné platformě (VM musí pro tuto platformu samozřejmě existovat), přenositelnost bez rekompilace je jedním ze základních principů jazyka Java. Všechny VM Javy jsou tak napůl interprety a napůl překladače. Nevýhodou bajtkódu je jeho 100% dekompilatovatelnost. S využitím vhodného decompileru (např. DJ Java Decompiler 1 ) je možné z class souboru získat zpět zdrojový kód včetně všech názvů tříd, proměnných atd. Jednou z možností jak tomu zabránit, je tzv. obfuskace. Obfuskace je proces, při kterém program, obfuskátor (obfuscator nejznámější: ProGuard, RetroGuard, JShrink) provede s bajtkódem několik operací: odstraní přebytečné (nepoužité) proměnné, metody a třídy, optimalizuje bajtkód, ale především ořízne veškeré uživatelské názvy tříd, proměnných, metod atd. Takto upravený class soubor je až o 30% menší než původní. Toho se již standardně užívá právě u mobilních aplikací, protože nejenom znemožňuje dekompilaci (respektive znepřehlední dekompilovaný kód), ale zkrácením jmen také výrazně zmenší velikost výsledných class souborů. Ukázka metody před 1 Domovská stránka Decompileru: http://members.fortunecity.com/neshkov/dj.html - 4 -

protected final void startapp() throws MIDletStateChangeException { display = Display.getDisplay(this); splash = new SplashScreen(); display.setcurrent(splash); splash.init(); gamecanvas = new MyGameCanvas(); gamecanvas.init(this); splash.run(); splash = null; menu = new Menu(this); menu.show(0); a po obfuskaci (zůstaly zachovány jen názvy tříd a výjimek z API) protected final void startapp() throws MIDletStateChangeException { a = Display.getDisplay(this); b = new g(); a.setcurrent(b); b.a(); d = new e(); d.a(this); b.b(); b = null; c = new c(this); c.a(0); 2.3 Životní cyklus midletu Spouštění a zavádění MIDletu třídou javax.microedition.midlet.midlet probíhá v několika krocích. Po požadavku OS na spuštění se zavolá bezparametrický konstruktor třídy a je vytvořena nová instance. Aplikace se nachází v tzv. přerušeném stavu. Když je vše připraveno, metoda startapp() uvede midlet do stavu aktivního. Ten označuje normální běh MIDletu. Zavoláním metody notifydestroyed() a následným spuštěním destroyapp(boolean unconditional) je možné MIDlet uvést do stavu zrušení a fakticky ho ukončit. V běžícím stavu je možno ho také přerušit a to buď z programu metodou notifypaused() nebo se o to postará správce aplikací (např. při příchozím hovoru). V obou případech je zavolána metoda pauseapp(). Zpět do aktivního stavu MIDlet vrátí resumerequest(). Všechny metody měnící stavy je možné (a vhodné) překrýt a postarat se v nich o alokaci/dealokaci zdrojů. Obr. 4.1 Životní cyklus midletu, zdroj: přednášky Vybrané partie z jazyka Java, Petr Hnětynka, UK 2.4 Vysoko- a nízko-úrovňová API GUI (Graphics User Interface grafické uživatelské rozhraní) se v MIDP skládá z tzv. - 5 -

vysokoúrovňových a nízkoúrovňových API. 2.4.1 Vysokoúrovňové API Vysokoúrovňové API jak už z názvu vyplývá operuje vysoko nad komponentami grafických a uživatelských rozhraní, je tedy více abstraktní. Jeho obsahem je základní balík grafických komponent podobný knihovně AWT 1 z J2SE. Programátor nemá moc možností jak ovlivnit vzhled aplikace a programování vypadá ve stylu metod nakreslitlacitko() nebo cosevybralozmenu(). Barvy, fonty a celý vzhled aplikace je závislý na implementaci rozhraní výrobcem zařízení. Tím pádem může stejná aplikace na různých zařízeních vypadat různě, avšak právě díky tomu je zaručena absolutní přenositelnost mezi všemi mobilními informačními zařízeními implementujícími daný profil. Mnoho práce tak za nás obstarává již implementace obsluhy GUI v zařízení. Programování je pak nejen jednodušší, ale z hlediska uživatele je výsledek mnohem přívětivější, protože uživatel je navyklý na určitý sjednocený grafický vzhled. Některé součásti, jako je například scrolling, uživatelský vstup, navigace apod. programátor vůbec neřeší, jsou totiž automaticky obstarávány zařízením. Následuje stručný popis tříd spadajících pod vysokoúrovňové API. Screen základní třída reprezentující obrazovku ; pro představu lze použít přirovnání k jedné statické webové stránce: může obsahovat následující prvky List výběrový seznam; ekvivalent HTML prvků checkbox a radio TextBox textové vstupní pole; ekvivalent input type=text Alert dočasné okno s upozorněním Form formulář; obalový prvek; může obsahovat další formulářové prvky: posuvníky, vstupní pole, texty, obrázky, seznamy apod. 2.4.2 Nízkoúrovňové API Nízkoúrovňové API je pak naprostý opak. Důraz je zde kladen na téměř nejnižší přístup ke komponentám zařízení (displej, tlačítka, stylus). Míra abstrakce je zde maximálně potlačena a metody vypadají typově jako nastavbarvupixelu() nebo jestisknutaklavesa(). Dává nám tak maximální přístup k zařízení, avšak právě kvůli tomu se aplikace obvykle stávají závislými na zařízení a následně nepřenositelnými. Pro multimediální aplikace jsou důležitá obě rozhraní. Vysokoúrovňová pro implementaci navigací, menu, formulářových vstupů apod. a nízkoúrovňová pro samotný 1 Článek o grafických rozhraní v J2SE: http://www.neo.cz/~tomas/java.net/2004/05/swing-versus-swt.html - 6 -

výkonný kód. Jelikož klademe důraz na multimediální možnosti mobilních zařízení, zaměříme se pouze na nízkoúrovňová API. 3 MIDP a 2D grafika V současné jsou grafické aplikace postaveny téměř výhradně na třídách Canvas a Image ze standardního balíčku javax.microedition.lcdui, případně na jejich kamarádkách z MIDP 2.0 GameCanvas, Sprite, Layer a dalších z balíku javax.microedition.lcdui.game. Pro začátek věnujeme tedy kousek prostoru těm méně známým a méně používaným rozhraním pro práci s 2D grafikou. 3.1 M2G Mobile 2D Graphics (M2G) známý také jako Scalable 2D vector Graphics API (JSR-226) je nepovinný balíček doplňující profil MIDP. Slouží zásadně pro práci s vektorovou grafikou, jejíž přednosti oproti rastrové grafice jsou především velikost souborů (u mobilních zařízení podstatná výhoda) a snadná možnost transformace (velikosti, natočení atd.), protože vektorový formát je nezávislý na rozlišení. Rozhraní používá otevřený formát SVG-Tiny 1, což je oficiální úprava velkého formátu SVG 2, který nepodléhá žádné licenci a je volně šiřitelný. Setkat se s ním lze například na webu, přičemž sám o sobě umožňuje i animace. Třídy a rozhraní lze nalézt v balíku javax.microedition.m2g, popř. org.w3c.dom.svg. 3.2 Canvas a ti ostatní v MIDP 1.0 Třída Canvas z balíku javax.microedition.lcdui je základní třídou pro aplikace vyžadující přímý přístup k displeji zařízení. Kromě zobrazování se stará také o zpracování vstupu od uživatele poskytuje rozhraní k zachytávání událostí stisku kláves. Každá klávesa má přiřazen konstantní kód, pomocí kterého lze snadno zjistit o kterou klávesu se jedná. Tyto kódy jdou definovány pro standardní ITU-T telefonní klávesnici. Příklad 5.1 Ukázka čtení kláves protected void keypressed(int keycode) { if(keycode > 0) switch(keycode) { case Canvas.KEY_NUM4: // '4' // stisknuta klávesa s číslem 4 break; 1 Domovská stránka: http://www.w3.org/tr/svgmobile/ 2 Domovská stránka: http://www.w3.org/tr/svg/ - 7 -

//... case Canvas.KEY_NUM6: // '6' // stisknuta klávesa s číslem 6 break; Canvas poskytuje také vstupní rozhraní k herním aplikacím. Zde jsou definovány abstraktní akce typu NAHORU, DOLEVA apod. Abstraktní jsou proto, že konstanta UP (nahoru) může na různých klávesnicích znamenat různé klávesy, čímž je ale zaručena přenositelnost. Implementace pak závisí na výrobci telefonu. Obsahem Canvasu jsou i metody na obsluhu stylusu v případě, že jej zařízení podporuje. Instancí této třídy (nebo tříd zděděných, což je obvyklejší) může být při běhu víc. Aktivní (viditelná) však může být v jeden okamžik maximálně jedna. O předávání řízení se v tomto případě starají metody shownotify a hidenotify, které zaregistrují instanci k zachytávání vstupních událostí. Standardně je zobrazovací plochou Canvasu celý displej, nicméně v některých implementacích může být část displeje vyhrazena na nabídku příkazů (třída Command) nebo na titulek. Proto byla v MIDP 2 přidána metoda setfullscreenmode, která explicitně nastaví, zda má třída pokrývat celou plochu displeje. V MIDP 1 bylo toto chování řešit proprietátními API, typicky pro telefony Nokia bylo potřeba při požadavku na fullscreen použít namísto standardního Canvasu třídu FullCanvas z balíku com.nokia.mid.ui. O samotný obsah toho co se má vykreslit se stará metoda protected abstract void paint(graphics g), kterou je třeba překrýt. Kontext, do kterého se bude kreslit je předán v parametru g. Důležité je však vědět, že samotné vykreslení se neděje voláním této metody, ale zprostředkovaně a to sice požadavkem z midletu na překreslení Display.getDisplay().setCurrent() nebo ze sebe sama pomocí metody repaint() popř. systémového volání servicerepaints(), které se liší tím, že pozastaví ostatní systémové akce jako čtení kláves, stylusu apod. a provede pokud možno okamžité překreslení. Třída Graphics je základní třídou pro vykreslování 2D primitiv. Podporovány jsou 24-bitové barvy (RGB - 3x8 bitů) a škála metod pro základní kreslení čar, obdélníků, polygonů, textu, zakřivených čar a dalších. To, zda se na barevnou škálu použije všech 24 bitů záleží samozřejmě na cílovém zařízení. Obecně však lze s touto barevnou hloubkou pracovat, pak je totiž úkolem koncového zařízení provést potřebnou konverzi. Graphics je víceméně grafickým kontextem, který se získá od požadované plochy na kterou chceme kreslit (obrazovka, off-screen) a získává se pomocí Image.getImage(), pokud chceme kreslit do offscreen obrázku (ten musí být vytvořen jako muttable, viz dále) nebo je předáván jako povinný parametr v metodě Canvas.paint(), pokud chceme kreslit přímo na displej. - 8 -

Souřadný systém je zleva-doprava a shora-dolů, pixel v horním levém rohu má koordináty [0;0]. Zajímavé možná je, že koordináty neznamenají jednotlivé pixely, ale mřížku mezi nimi. Nicméně použití je jednoznačné. Jak zmiňuje dokumentace, ukázkový fillrect(0, 0, 3, 2) vyplní samozřejmě předpokládanou oblast 3x2 pixely. Bohužel, při testování jsem se přesvědčil, že někteří výrobci telefonů si dokumentaci vykládají různě a na některých zařízeních ten samý kód kreslil obrázek o pixel nahoru či dolů oproti ostatním. Nastavení barvy pro kreslení všech čar a textů provádí metoda setcolor(int RGB), přičemž parametr lze zapsat obvyklým hexadecimálním zápisem 0x00RRGGBB, u čar lze navíc nastavit styl čáry pomocí setstrokestyle(int style), v aktuální verzi MIDP 2.0 zatím jen ve dvou stylech plná čára a tečkovaně. Tloušťka čáry je vždy jeden pixel. Clipping (ořezávání) je metoda sloužící k nastavení obdélníkové oblasti v objektu Graphics, do níž smí grafický kontext zakreslovat. Používá se převážně k optimalizaci vykreslování, kdy uzamčení části plochy a kreslení do jednoho místa je rychlejší, než když zařízení musí celou plochu zpřístupnit k vykreslování. Další výhodou je možnost tvorby výřezů (viz. příklad). Příklad 5.2 Metoda nahrazující drawregion z MIDP 2 pro MIDP 1 // Parametry // g cílový kontext do kterého se má kreslit // img zdrojový obrázek // xsrc, ysrc, width, heigth hranice výřezu ze zdrojového obrázku // xdst, ydst, anchor umístění výřezu v cíli public static void drawregion(graphics g, Image img, int xsrc, int ysrc, int width, int height, int xdst, int ydst, int anchor) { /* MIDP 1.0 */ g.setclip(xdst, ydst, width, height); g.drawimage(img, xdst - xsrc, ydst - ysrc, anchor); /* MIDP 2.0 g.drawregion(img, xsrc, ysrc, width, height, 0, xdst, ydst, anchor); */ Ořezy nelze kombinovat a vytvářet tak složitější útvary. Každý objekt Graphics může mít jen jeden ořez. K nastavení se používá metoda setclip(). Zarovnání (anchor point) se používá při zobrazení obrázků a textů. Pomocí bitového OR lze snadno nastavit, zda vzhledem k zadanému bodu se má grafika vykreslit nalevo, napravo, uprostřed, nahoře či dole. Tato vlastnost slouží čistě k usnadnění práce programátora a zpřehlednění kódu. Příklad 5.3 Vykreslení obrázku doprostřed displeje klasickou metodou a s využitím anchor // klasicky g.drawimage(img, resolution.x/2 - obrx/2, resolution.y/2 obry/2, 0); // a s anchor point - 9 -

g.drawimage(img, resolution.x/2, resolution.y/2, Graphics.HCENTER Graphics.VCENTER); Třída Image z balíku javax.microedition.lcdui je určena k uchování grafických rastrových dat. Objekt typu Image může vzniknout dvojím způsobem a podle toho se typově dělí na mutable a immutable. Obrazy mutable (měnitelné) vznikají zavoláním Image.createImage(int width, int height). Tato metoda vytvoří prázdný obraz o rozměrech width x height do kterého lze po získání kontextu Graphics kreslit, kopírovat fragmenty či celé další obrázky. Narozdíl od toho obrazy typu immutable (neměnné) nelze po jejich vytvoření a iniciování měnit ani na ně nijak kreslit. Typicky se jedná o proměnné Image vytvořené nahráním ze zdrojového souboru či bloku dat v paměti. Více viz dokumentace na http://java.sun.com. Máme-li však požadavek na editaci grafiky získané ze souboru, lze immutable obrázek snadno přeměnit na muttable pomocí jednoduchého kódu, ostatně jak také zmiňuje dokumentace: Příklad 5.4 Snadná konverze immutable objektu na objekt mutable Image source; // zdrojový obrázek source = Image.createImage(...); Image copy = Image.createImage(source.getWidth(), source.getheight()); Graphics g = copy.getgraphics(); g.drawimage(source, 0, 0, TOP LEFT); Pozn.: častou chybou bývá získávání kontextu např. při každém průchodu cyklem. Nejenom že se kód citelně zpomalí, ale především bude nefunkční, protože získaný kontext je při každém volání getgraphics() jiný. Následující ukázkový kód nebude fungovat korektně: img.getgraphics().setcolor(0x00ff0000); // nastavení barvy štětce na červenou img.getgraphics().drawline(0, 0, 10, 10); // čára se vykreslí implicitní barvou (černou) narozdíl od správného: Graphics g = img.getgraphics(); g.setcolor(0x00ff0000); // nastavení barvy štětce na červenou g.drawline(0, 0, 10, 10); // čára se již vykreslí červeně (pokud nemáme černobílý displej :) Standardním obrazovým formátem je bezeztrátový kompresní formát PNG (Portable Network Graphics 1 ) ve verzi 1.0. Podpora dalších typů je závislá na libovůli výrobce zařízení. Mezi obvyklé patří ještě GIF a BMP, nicméně oproti PNG nepřináší žádnou výhodu BMP jako nekomprimovaný formát je datově příliš veliký pro nasazení na mobilních zařízeních, GIF je pak omezen na škálu maximálně 256 barev a navíc podléhá tvrdé licenční politice. Průhlednost 1 specifikace: http://www.w3.org/tr/rec-png.html - 10 -

Neměnné (immutable) obrazy mohou obsahovat kromě neprůhledných a plně průhledných i poloprůhledné pixely (narozdíl od mutable, které nemohou mít průhledný byť jediný pixel). Implementace Javy na konkrétním zařízení musím umět pracovat s plnou nebo žádnou průhledností. Podpora částečné průhlednosti (alpha blending) je opět implementačně závislá na výrobci a nelze se tedy na její podporu vždy spolehnout. Od MIDP 2 lze alespoň zjistit, kolik úrovní průhlednosti zařízení podporuje metodou Display.numAlphaLevels(). Vrácená hodnota bude vždy alespoň 2, větší číslo znamená podporu částečné průhlednosti. 3.3 Uživatelské rozhraní v MIDP Abstraktní třída Displayable je základním elementem zobrazitelným na displeji. Obsahuje v sobě mechanismus pro práci s příkazy (Commands). Protože třída je definována jako abstraktní, zaměříme se na její potomky. Displayable má dva přímé potomky: Canvas a Screen. Canvas, česky plátno, je zástupce low-level API, Screen, česky obrazovka, je zástupcem high-level API. Obr. 5.1 Hierarchie tříd grafického uživatelského rozhraní MIDP zdroj: JAVA MIDP APPLICATION DEVELOPER S GUIDE FOR NOKIA DEVICES [6] Příkazy (Commands) jsou mechanismem pro obsluhu vysokoúrovňových událostí. Filozofie práce s nimi je taková, že objektu, který je potomkem Displayable, případně potomkem Screen se přiřadí libovolný počet příkazů (Command), každý určeného typu a s určitou prioritou. Protože obsluha těchto příkazů probíhá obvykle pomocí kontextových kláves, kterých je omezené množství (obvykle dvě), pomáhá určení typu a priority sdělit - 11 -

aplikačnímu rozhraní, které příkazy má zobrazit přímo a které se schovají v podnabídce. O následnou obsluhu událostí generovaných těmito příkazy se stará metoda commandaction() z rozhraní CommandListener. Problematika událostí a jejich obsluhy je poměrně široká a není hlavní náplní této práce, případné zájemce lze odkázat na vyčerpávající dokumentaci [7] nebo výbornou příručku [6] začínajících vývojářů od fy Nokia, byť už trochu staršího data. Příklad 5.5 Ukázka použití Commands v praxi public class Main extends MIDlet implements CommandListener { // základní proměnné private List samplelist; // seznam private Command exitcmd = new Command("Exit", Command.EXIT, 1); // příkaz private Command backcmd = new Command("Back", Command.BACK, 1); // příkaz // inicializace při spuštění aplikace public void startapp() { samplelist = new List("Samples", List.IMPLICIT); // inicializace seznamu for (int i = 0; i < SAMPLES.length; i++) { // naplnění seznamu SAMPLES[i].getDisplayable().addCommand(exitCmd); SAMPLES[i].getDisplayable().addCommand(backCmd); SAMPLES[i].getDisplayable().setCommandListener(this); samplelist.append(samples[i].getname(), null); samplelist.addcommand(exitcmd); samplelist.setcommandlistener(this); Display.getDisplay(this).setCurrent(sampleList); // metoda na zachytávání akcí public void commandaction(command command, Displayable displayable) { if (command == exitcmd) { // příkaz konec aplikace destroyapp(true); notifydestroyed(); else if (command == backcmd) { // příkaz krok zpět Display.getDisplay(this).setCurrent(sampleList); // zobrazení seznamu else if (command == List.SELECT_COMMAND) { // zobrazení požadované třídy 3.4 GameCanvas a ti ostatní v MIDP 2.0 S příchodem MIDP 2 se objevily i nové třídy určené primárně k usnadnění vývoje herních aplikací. Jak již bylo uvedeno, bezdrátová zařízení jsou tvrdě limitována výpočetním výkonem a pamětí, proto každý přesun kódu do API knihoven znamená zvýšení výkonu. Game API totiž nepřidává téměř nic, co by nebylo možná napsat pomocí MIDP 1, pouze přenáší obvykle používané konstrukce do standardních knihoven. Metody měnící vlastnosti (pozice, viditelnost...) následujících objektů nemají žádný přímý viditelný výsledek. Hodnoty jsou uloženy uvnitř objektů a změna se projeví až při - 12 -

překreslení metodou paint(). Tento přístup je vhodný právě pro herní aplikace, kde herní cyklus sestává obvykle ze sekvence čtení vstupu-výpočet-vykreslení. Celé API je balíkem pěti tříd: GameCanvas podtřída třídy Canvas poskytuje základní rozhraní pro zobrazovací funkce. Obsahuje všechny zděděné metody a navíc přidává frontu událostí vstupního zařízení tak jako je tomu v desktopových OS (v MIDP 1 se metody pro čtení stavu kláves musely trefit do okamžiku kdy klávesa byla zrovna stisknuta; pokud byla smyčka aplikace příliš dlouhá a uživatel stiskl tlačítko velmi krátce, mohlo dojít k tomu, že se stisk vůbec nezaznamenal) a nativní podporu pro double buffer. Třída je vytvořena děděním a je zpětně kompatibilní, lze tedy používat všechny konstrukce známé z normálního low-level API. Layer abstraktní třída reprezentující viditelný objekt; je definována pozicí, rozměry a viditelností; dědí od ní třídy Sprite a TiledLayer LayerManager zastřešující třída pro objekty typu Layer; usnadňuje vykreslování většího počtu objektů a poskytuje podporu pro snadné vytváření a úpravy pohledu na vykreslovanou scénu; vloženým objektům přiřazuje úroveň vnoření a tím řeší problematiku viditelnosti jakýsi zjednodušený z-buffer Sprite potomek Layer; reprezentuje základní grafický prvek; umožňuje vytváření animací a jednoduchou rotaci či zrcadlení; primární vlastnosti a dovednosti: vytváření frame-sekvencí; obvyklá délka sekvence je rovna počtu framů, je však možné si nadefinovat vlastní sekvenci s libovolným množstvím framů, které se mohou opakovat, vynechávat jednotlivé snímky či vytvářet reverzní animaci; každý Sprite může obsahovat jen jednu libovolně dlouhou sekvenci referenční pixel; chceme-li vykreslit Sprite v bodě [x;y], znamená to, že od tohoto bodu se vykreslí levý horní roh; toto chování lze změnit nastavením referenčního pixelu na libovolný bod v oblasti Spritu transformace; existují zde jen výpočetně nenáročné transformace otáčení při kroku 90 a/nebo zrcadlení kolize; Sprite umožňuje vyhodnocování kolizí mezi Sprity, TiledLayer nebo objektem Image a to buď na úrovni kolizního obdélníku nebo metodou pixel-by-pixel, kde je detekována kolize pixelů s nulovou průhledností TiledLayer třída pro vytváření čtvercových map pomocí tzv. tiles (dlaždic); obvyklá technika pro vytváření různých pozadí; protože mobilní zařízení jsou paměťově výrazně omezená, není možné jako pozadí/mapu použít velký obrázek, proto se používá metoda, kdy - 13 -

jsou do čtvercové sítě kladeny jednotlivé buňky, které na sebe motivem navazují a vytvářejí pocit jednolitého pozadí; princip je podobný jako u Sprite jednotlivé framy mají svůj index a podle matice definující pozadí jsou skládány vedle sebe; jednotlivé buňky mohou být také animovány Obr. 5.2 Matice pozadí a výsledný obraz, zdroj: dokumentace WTK [8] Příklad 5.6 Animace rotace Zeměkoule pomocí Sprite a pomocí MIDP 1 // proměnné private Sprite _sprite1; // sprite podle MIDP1 (Sprite je třída ve standardním balíku private javax.microedition.lcdui.game.sprite _sprite2; // sprite podle MIDP2 // řídící proměnná pro _sprite1 int _actualframe=0; // inicializace _sprite1 _sprite1=new Sprite("/earth.png", 50, 50); // inicializace _sprite2 Image spriteimage=null; try { spriteimage = Image.createImage("/earth.png"); catch(exception e) { e.printstacktrace(); _sprite2=new javax.microedition.lcdui.game.sprite(spriteimage, 50, 50); // vykreslování // _sprite1 _gbuffer.drawimage(_sprite1.getframe(_actualframe++), getwidth(), 0, Graphics.TOP Graphics.RIGHT); if(_actualframe>=_sprite1.m_numframes) _actualframe=0; // _sprite2 _sprite2.paint(_gbuffer); _sprite2.nextframe(); 4 MIDP a 3D grafika 4.1 OpenGL ES OpenGL ES (JSR-239) se nachází ještě ve stádiu vývoje, nicméně už je implementován na některá výkonná zařízení. Je určen především pro vývojáře kteří znají OpenGL na PC. - 14 -

4.2 M3G 4.2.1 Pozadí vzniku Vzhledem ke vzrůstajícímu výkonu mobilních zařízení se postupem času došlo k závěru, že jsou již připravena pro implementaci 3D rozhraní. Prvním byl renderovací engine Mascot Capsule na telefonech firmy SonyEricsson. Jen pro zajímavost, jeho výkon je i dnes obvykle vyšší než dále zmíněné M3G. Na jeho základě vznikla expertní komise předních vývojářů pro mobilní zařízení, která měla za úkol vytvořit standardizované API pod hlavičkou JCP. Tak 19. listopadu 2003 vznikla první finální specifikace JSR-184, nazvaná Mobile 3D Graphics API (M3G API). To je zaměřeno na zařízení s malým výpočetním výkonem a pamětí a která nemají hardwarovou podporu 3D grafiky (myšleno GPU). Implementace rozhraní může být celá dokonce čistě softwarová. Pokud však zařízení má k dispozici specializované hardwarové prostředky pro rychlejší výpočty, API je umí využít. Při návrhu se bralo v potaz i předpokládané využití hry, vizualizace map, spořiče obrazovek, graficky bohatá uživatelská rozhraní a další. Z těchto rozdílných požadavků nakonec vzešlo řešení dvou různých úrovní přístupu retained a immediate mode, viz níže. API vyžaduje podporu čísel s desetinnou čárkou, respektive CLDC 1.1. 4.2.2 Obecná teorie Systém M3G používá pravotočivý souřadný systém. 3D prostor je orientován tak, že horizontální posun značí osa x, vertikální osa y a posun v hloubce osa z. Toto rozložení používají oba majoritní 3D zobrazovací systémy i na platformě PC (Direct3D, OpenGL). Definice se někdy rozchází v tom, zda kladný přírůstek na ose z znamená přiblížení ke kameře (pozorovateli) nebo naopak oddálení. V M3G je osa z orientována (má kladný přírůstek) směrem ke kameře. Objekty v běžných 3D zobrazovacích systémech reprezentují shluky polygonů (núhelníků). Tyto polygony lze pak rozložit na menší jednotky trojúhelníky, které tvoří nejmenší možnou zobrazitelnou plochu. Vrcholy každého trojúhelníku jsou body v prostoru definované třemi [X, Y, Z] souřadnicemi. Tyto vrcholy se nazývají vertexy. - 15 -

Obr. 6.1 View frustum, zdroj: IBM developerworks [9] Již byl zmíněn pojem kamera. Kamera je okem pozorovatele. Je dána svojí pozicí, úhlem natočení (ve všech třech osách), pozorovacím úhlem (viewing angle) a řeznými rovinami. Pozorovací úhel a řezné roviny definují v prostoru jakýsi čtyřstěnný jehlan se seříznutou špicí (view frustum) a všechny objekty které se budou nacházet uvnitř tohoto jehlanu budou zobrazeny na výsledném zobrazovacím zařízení (v našem případě obvykle LCD mobilního zařízení). Mobile 3D Graphics API MIDP CLDC 1.1 Obr. 6.2 vztah M3G, MIDP a CLDC 4.2.3 API Veškeré třídy a rozhraní se nacházejí v balíku javax. microedition.m3g. V aplikaci lze zjistit dostupnost rozhraní zavoláním System.getProperty("microedition.m3g.version"), které vrátí číslo verze, respektive null, pokud API není přítomno. Krom základních tříd jsou v balíku přítomny třídy popisující materiálové vlastnosti, klíčování animací, meshe, textury, systémy hierarchie scény a další. Důležité třídy, tak jak jsou popsány v dokumentaci [10]: - 16 -

Appearance soubor komponent popisujících 3D objekt (textura, materiál, kompozice...) Camera uzel grafu scény popisující pozici a polohu pozorovatele a parametry projekce (pozorovací úhel, perspektiva...) Graphics3D grafický kontext (třída je jedináček singleton, získává se statickou metodou getinstance()), nastavuje cíl renderingu, jeho parametry (antialiasing, dithering...) a realizuje samotné vykreslování pomocí jedné ze čtyř metod render (2 pro retained mode a 2 pro immediate mode) Image2D rastrový obrázek pro použití jako textura, pozadí nebo sprite; může být mutable i immutable (viz. Sprite v kapitole 5.4) Loader třída obsahující dvě statické metody pro vytváření známých datových struktur obecně Object3D (což zahrnuje World, Image2D a další) Mesh uzel grafu scény popisující 3D objekt složený z polygonů Node abstraktní třída obecného uzlu Object3D - abstraktní třída; základ všech objektů umístitelných do 3D prostoru Transform obecná transformační matice 4x4 World úložiště pro graf scény; potomek třídy Group nejvyšší úrovně (kořen scény) Scene graph 1 Graf scény je stromovou strukturou - místo kde se dělí větev se nazývá uzel (node). Uzel na vrcholu této struktury se nazývá kořen (World node). Uzlem mohou být meshe (objekty), sprity, světla a celé skupiny těchto objektů zabalené do uzlu pomocí obalové třídy Group. S těmi se pak zachází jako s jedním objektem, což je výhodné pro skupiny prvků které spolu nějak logicky souvisejí. Přestože World je také typu uzel, nemůže být sám o sobě jeho součástí, tzn. World musí stát vždy na vrcholu pyramidy. Výhoda použití grafu scény je, že s malým programovacím úsilím lze snadno zobrazit komplexní scénu. Stromový typ grafu klade však některá omezení. Jeden uzel (node) může náležet vždy maximálně do jedné skupiny (Group). Graf musí být větvený, tzn. je třeba se vyhnout zacyklení větví. 1 Obecně o scene graph v encyklopedii Wikipedia: http://en.wikipedia.org/wiki/scene_graph - 17 -

Obr. 6.3 restrikce ve stromu grafu, zdroj: Mobile 3D Graphics API Specification [3] Důležité je také přidělování a správa takzvaných user ID jak uvidíme později na příkladu. Ty slouží ke rychlé a jednoznačné identifikaci objektů ve scéně. V modelovacím nástroji je možné používat vícero kamer než je jen jedna. Ty se vyexportují společně se zbytkem scény a lze mezi nimi snadno přepínat právě třeba pomocí user ID. Scene graph se snadno vytvoří exportem z běžného 3D modelovacího nástroje (3D Studio MAX 1 ve verzi 8 má exporter zabudován, Blender 2 pro export existuje Python skript 3 atd.) a to včetně světel, textur a kamer. Zde prezentovaný příklad byl vytvořen právě pomocí open source nástroje Blender. Strukturu je samozřejmě možné vytvořit i programově, za běhu. 1 Domovské stránky 3D Studia MAX: http://www.autodesk.com/3dsmax 2 Domovské stránky Blenderu: http://www.blender.org 3 Blender Export for J2ME: http://www.nelson-games.de/bl2m3g/default.html - 18 -

Obr. 6.4 Ukázka struktury grafu, zdroj: Mobile 3D Graphics API Specification [3] 4.2.4 Immediate a retained mode M3G obsahuje dva zobrazovací módy. Immediate, což je nízkoúrovňové API, založené na derivátu OpenGL ES 1 ), používá se k zobrazování základních prvků vertexů, trojúhelníků, jednotlivých světel atd. Umožňuje absolutní kontrolu nad zobrazovanou scénou, příkazy jsou okamžitě vyhodnoceny a zpracovány grafickou jednotkou. Oproti tomu retained mode představuje abstraktnější vysokoúrovňové API, kde se využívá především importu celých scén vytvořených externími modelovacími programy. Tyto scény v sobě obsahují stromové grafy sestávající z uzlů - meshů (logické celky objektů), systémů světel, virtuálních kamer a dalších objektů, ke kterým se v programu snadno přistupuje přes jednoznačný identifikátor (ID) jak již bylo výše řečeno. Standard dále definuje formát dat modelů, včetně texturování a systému animací. Oba módy lze kombinovat a používat najednou, avšak při použití retained módu a zavolání render(world) se použijí světla a kamera definovaná ve World, ignorují se tedy všechna předchozí nastavení. Toto neplatí při vykreslení pomocí render(node, transform). Popsání alespoň hlavních mechanismů by zabralo více než je obsah celé této práce. Pro co nejrychlejší a nejsrozumitelnější zasvěcení zde budou proto uvedeny pečlivě okomentované příklady. Příklad 6.1 Kostka, retained mode //...inicializace // získání instance g3d = Graphics3D.getInstance(); // nahrání scény ze souboru Object3D[] parts=null; try { parts = Loader.load("/cube.m3g"); catch(exception e) { e.printstacktrace(); _world = (World) parts[0]; // prvek na nultém indexu je vždy hlavní objekt World // získání odkazu na kostku (má definováno userid=12) // pro pozdější snazší manipulaci _cube=(mesh)_world.find(12); // získání a nastavení kamery _camera = _world.getactivecamera(); // nastavení projekce float[] lprojection = {0.0f, 0.0f, 0.0f, 0.0f; _camera.getprojection(lprojection); float aspect = (float)getwidth()/(float)getheight(); 1 Domovské stránka OpenGL ES: http://www.khronos.org/opengles - 19 -

// nastavení prespektivy _camera.setperspective( lprojection[0], // úhel pohledu aspect, // poměr stran lprojection[2], // první ořezávací rovina lprojection[3]); // druhá ořezávací rovina _world.setactivecamera(_camera); //... // a vykreslení _cube.postrotate(2.0f,0.0f,0.0f,1.0f); // rotace kostky try { g3d.bindtarget(g); // nastavení cíle (g je odkaz na grafický kontext) g3d.render(_world); // render finally { g3d.releasetarget(); // uvolnění cíle Příklad 6.2 Kostka, immediate mode // definice proměnných; pozn.: pouze výňatky // vertexy private static final byte[] VERTEX_POSITIONS = { -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, // front 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, // back... ; // indexy vertexů pro vytvoření triangle stripů private static final int[] TRIANGLE_INDICES = { 0, 1, 2, 3, // přední stěna 4, 5, 6, 7, // zadní stěna... ; // délky triangle stripů v TRIANGLE_INDICES private static int[] TRIANGLE_LENGTHS = { 4, 4, 4, 4, 4, 4 ; // koordináty k namapování textury private static final byte[] VERTEX_TEXTURE_COORDINATES = { 0, 1, 1, 1, 0, 0, 1, 0, // přední 0, 1, 1, 1, 0, 0, 1, 0, // zadní... ; // inicializace (zjednodušená) // získání instance graphics3d = Graphics3D.getInstance(); / vytvoření pozadí s barvou _background = new Background(); _background.setcolor(0xff113366); / vytvoření vertex bufferu _cubevertexdata = new VertexBuffer(); / vytvoření a nastavení pole vertexů VertexArray vertexpositions = new VertexArray(VERTEX_POSITIONS.length/3, 3, 1); VertexPositions.set(0, VERTEX_POSITIONS.length/3, VERTEX_POSITIONS); _cubevertexdata.setpositions(vertexpositions, 1.0f, null); / to samé pro textury VertexArray vertextexturecoordinates = new VertexArray(VERTEX_TEXTURE_COORDINATES.length/2, 2, 1); VertexTextureCoordinates.set(0, VERTEX_TEXTURE_COORDINATES.length/2, VERTEX_TEXTURE_COORDINATES); cubevertexdata.settexcoords(0, vertextexturecoordinates, 1.0f, null); // vytvoření polygonů (trojúhelníků) tvořících kostku _cubetriangles = new TriangleStripArray(TRIANGLE_INDICES, TRIANGLE_LENGTHS); // vytvoření a nastavení kamery Camera camera = new Camera(); float aspect = (float) getwidth() / (float) getheight(); camera.setperspective(30.0f, aspect, 1.0f, 1000.0f); - 20 -

Transform cameratransform = new Transform(); cameratransform.posttranslate(0.0f, 0.0f, 10.0f); _graphics3d.setcamera(camera, cameratransform); try { // vytvoření a nastavení textury Image2D image2d = (Image2D) Loader.load("/fel.png")[0]; // načtení ze zdroje _cubetexture = new Texture2D(image2D); _cubetexture.setblending(texture2d.func_decal); // blending; viz. dokumentaci _cubeappearance.settexture(0, _cubetexture); catch (Exception e) { e.printstacktrace(); // a vykreslení _cubetransform.postrotate(2.0f, 0.0f, 1.0f, 0.0f); // rotace kostky (stejné jako u retained mode) try { _graphics3d.bindtarget(g); // nastavení cíle _graphics3d.clear(_background); // překreslení cíle pozadím _graphics3d.render(_cubevertexdata, _cubetriangles, _cubeappearance, _cubetransform); // render finally { _graphics3d.releasetarget(); // uvolnění cíle 4.2.5 Shrnutí M3G je vysokoúrovňové API a jako takové poskytuje rychlé výsledky. Pomocí modelovacího nástroje a několika řádek kódu je možné snadno vytvořit komplexní scénu. Na druhou stranu je prozatím výkon většiny současných přístrojů nedostačující na jakékoliv složitější scény. To je způsobeno především požadavkem na výpočty s plovoucí desetinnou čárkou, který pro uspokojivý běh vyžaduje matematický koprocesor. Stejně jako u 2D, i zde se však lze pomocí optimalizace dosáhnout rozumných výsledků. 5 Zvuky Podpora zvuku se v MIDP oficiálně objevila až od její druhé verze, nicméně už dřívější zařízení s podporou MIDP 1 byla schopna přehrávat zvuky s pomocí proprietárních API výrobců telefonů. Dnes na poli ozvučení existuje několik specifikací (standardů), které si následně rozebereme. Předtím by ještě bylo vhodné uvést několik málo poznámek o typech dat, jež je možno přehrávat. Defakto existují dvě hlavní skupiny lišící se principem, a to samply (datové proudy) a MIDI 1. Hlavní rozdíl je ve způsobu uložení, zatímco samply (wav, amr, mp3 atd.) obsahují pomocí převodníků zdigitalizované zvuky, MIDI definuje pouze kombinaci čas-nota-rychlost-hraný nástroj. Přehrávající zařízení tedy kompletně rekonstruuje (generuje) skladbu. V oblasti grafiky bychom našli analogii rastrová grafika (samply) versus vektorová grafika (MIDI). Z toho následně plynou výhody i nevýhody. Hlavní výhodou, 1 Musical Instrument Digital Interface: http://en.wikipedia.org/wiki/musical_instrument_digital_interface - 21 -

zvláště v oblasti zařízení s malými pamětmi je velikost dat. Protože v midi jsou zaznamenány pouze noty, může i několikaminutová pasáž zabírat pouze několik kb paměti. Na druhou stranu je však zřejmé, že takto zahrát lze pouze na nástroje, jež zařízení podporuje. Z toho plyne, že na různých zařízeních může ta samá skladba znít různě, či se dokonce některé nástroje nemusí přehrát vůbec. MIDI též z principu není schopno přehrát nic jiného než hudbu, nedokáže tedy přehrát řeč, či různé ruchy, od toho jsou zde ostatní formáty. 5.1 Mobile Media API 5.1.1 Obecně MMAPI (JSR-135) obecně slouží k širšímu spektru akcí než je přehrávání zvuku. V závislosti na zařízení umožňuje též přehrávání videa nebo zachytávání zvuku či obrazu z videokamery. API bylo navrhováno jako vysokoúrovňové a dnes je v podstatě standardem, o čemž svědčí i seznam členů MMAPI Expert group: Nokia, Mitsibishi, Motorola, Philips, Siemens, Sun, Symbian, TI, Vodafone a další. Výsledkem jejich práce jsou ve skutečnosti dvě API: MMAPI a MIDP 2.0 Media API, které je pouze podmnožinou předchozího (je s ním tedy plně kompatibilní) a je zacíleno na zařízení s obecně sníženými schopnostmi multimediální reprodukce. Jak zmiňuje Lucie Rút Bittnerová v sérii článků J2ME v kostce jak na zvuk [11], MMAPI je součástí většiny současných zařízení s podporou J2ME od telefonů až po PDA. API se nachází v balíku javax.microedition.media, u některých výrobců bylo ukryto pod vlastní balík (Siemens - com.siemens.mp.media). Protože mají mít knihovny záběr v široké paletě různorodých zařízení, bylo definováno jako vysokoúrovňové. 5.1.2 Základní koncept Architektura systému sestává ze tří hlavních částí: třídy Manager rozhraní Player rozhraní Control - 22 -

Obr. 7.1 Architektura MMAPI, zdroj: developers.sun.com Manager je přístupovým bodem ke všem možnostem přehrávání zvuku. Zodpovídá za dvě hlavní funkce: vytváření instancí Player a k přímému přehrávání tónů. Dále pak obsahuje metody pro zjištění podporovaných datových typů pro dané zařízení (povinná implementace je jen pro WAV a MIDI) metodou getsupportedcontenttypes() a seznam podporovaných protokolů getsupportedprotocols(). Player je objekt, který je prostředníkem mezi zvukovým zdrojem (souborem) a jeho ovládacími prvky. Může být vytvořen třídou Manager buď ze zdroje typu InputStream, který je možno vytvořit například ze zdroje (resource) v JARu nebo z adresy URL. Po vytvoření metodou createplayer() a zavolání start() se co nejrychleji alokují potřebné zdroje a spustí se přehrávání na pozadí, dokud skladba neskončí. To je nejjednodušší příklad použití. Podíváme se trochu hlouběji na kroky, které se provedou před samotným spuštěním skladby. Životní cyklus vytvořeného Player sestává z pěti stavů: UNREALIZED, REALIZED, PREFETCHED, STARTED a CLOSED. Jak se zmiňuje manuál [18], praktický význam těchto stavů je kvůli časové náročnosti jednotlivých kroků při požadavku na přehrání zvuku. Po zavolání createplayer je Player v nerealizovaném stavu. Zavoláním realize() se stav změní na realizovaný a v případě, že zvuková data byla definována jako URL, dojde k jejich stažení. Nakonec zavoláním prefetch() dojde k připravenému stavu, kdy jsou alokována zvuková zařízení a Player je připraven k okamžitému přehrávání. Zavoláním start() se přehraje zvuk a stav se změní na běžící. Skončí-li přehrávání buď metodou stop() nebo tím, že se přehrávač dostane na konec skladby, přejde opět do stavu připravenosti. Uvolnění zdrojů se provede z kteréhokoli předchozího stavu zavoláním close(). Cyklus možná lépe vystihne schéma. - 23 -

Obr. 7.2 stavy objektu Player a jeho přechody, zdroj: J2ME v kostce, jak na zvuk [11] Zavoláním start() ze stavu UNREALIZED dojde k automatickému volání metod realize() a prefetch(), není tedy nutné všechny tyto metody exaktně volat. Pokud bychom vyžadovali zpětnou vazbu od přehrávače, je potřeba vytvořit třídu implementující rozhraní PlayerListener, respektive jeho metodu playerupdate(player player, String udalost, Object dataudalosti) a tuto třídu u požadovaného přehrávače zaregistrovat. Ta se pak automaticky zavolá pokaždé, dojde-li k nějaké z událostí definovaných v rozhraní PlayerListener, například: konec skladby, vynucené stopnutí, změna hlasitosti, apod. Všechny události jsou podrobně rozepsány v dokumentaci [18]. Zajímavou pro praxi je schopnost přehrání několika zvukových vrstev současně. Tato vlastnost se bude jistě lišit přístroj od přístroje, nicméně emulátor i reálné zařízení typu Nokia series 40 toto zvládlo. Control je rozhraní pro implementaci ovládacích prvků objektu Player. Jedná se o předka, který má dva přímé potomky: ToneControl užívá se pro přehrávání sekvencí jednoduchých tónů, více viz Tónový generátor VolumeControl slouží k nastavení hlasitosti 5.1.3 Tónový generátor Tónový generátor je důležitý pro zvukové aplikace jako jsou například hry. U velmi jednoduchých zařízení je to často jediný způsob jak z něj dostat zvuk. Vyvolat ho lze metodou Manager.playTone(int nota, int delka, int hlasitost). Pokud chceme přehrát celou sekvenci tónů (třeba krátkou písničku) je tento způsob nepohodlný. Lze využít vytvoření objektu Player s typem Manager.TONE_DEVICE_LOCATOR a následně přes rozhraní ToneControl nastavit sekvenci not třeba jako pole bytů, respektive datový typ audio/x-tone-seq 1. 1 popsán v http://www.ietf.org/rfc/rfc2234-24 -

6 J2ME a vývojová prostředí 6.1 WTK Sun Java Wireless Toolkit (WTK 1 ), známý také jako J2ME Wireless Toolkit, je základní sada nástrojů pro tvorbu aplikací na platformě J2ME. Obsahuje nástroje pro sestavení aplikace, pomocné utility a základní balík emulátorů. V aktuální verzi 2.5 podporuje OS Windows a OS Linux. 6.2 Eclipse Jak uvádí encyklopedie Wikipedia 2, Eclipse 3 je open source vývojová platforma, která je pro většinu lidí známá jako vývojové prostředí (IDE) určené pro programování v jazyce Java. Flexibilní návrh této platformy dovoluje rozšířit seznam podporovaných programovacích jazyků za pomoci pluginů, například o C++, PHP nebo o návrh UML, či zápis HTML nebo XML. Jedním z těchto pluginů je i EclipseME. Jak uvádí oficiální stránka 4, EclipseME by za vás měl udělat špinavou práci co se týče někdy velmi problémového propojení Eclipse s WTK. Veškerý kód v této práci byl vytvořen právě kombinací Eclipse+EclipseME a nutno podotknout, že šlo o kombinaci bezproblémovou. Druhým rozšířením jsou Mobile Tools for Java (MTJ) 5, který měl být oficiálním rozšířením (EclipseME je software třetí strany) platformy Eclipse. V době psaní této práce (duben 2008) byla poslední verze 0.7 pozastavena a projekt bude reinkarnován a znovupostaven právě na pluginu EclipseME. Ten jako samostatný projekt poté zanikne. 6.3 NetBeans Pro úvodní popis prostředí si opět dovolím citovat Wikipedii: NetBeans 6 je open source projekt s rozsáhlou uživatelskou základnou, komunitou vývojářů a s více než 100 partnery po celém světě. Pod firmu Sun Microsystems, která je hlavním sponzorem projektu, přešel na základě akvizice stejnojmenné české společnosti v říjnu 1999. Pod open-source licencí byl 1 http://java.sun.com/products/sjwtoolkit/ 2 Wikipedia, otevřená encyklopedie: http://www.wikipedia.org 3 http://www.eclipse.org 4 http://eclipseme.org 5 http://www.eclipse.org/dsdp/mtj/ 6 http://www.netbeans.org - 25 -