sobota 4. prosince 2004

Animace - díl pátý: Zahraj to ještě jednou, Joe

autor: George K.


5.1 Události bez komentáře

Jak jistě neuniklo minule vaší pozornosti, výpis animačního programu se skládal ze dvou částí - kratší (komentované), která ukládala Joa do paměti, a delší (nekomentované), která postavičku uváděla do pohybu. K této pasáži programu si nyní něco řekneme.
Za návěstím START je nejprve nastaveno přerušení IM 1 a je povoleno. To je důležité, protože jinak by nebylo možné použít instrukci HALT (u návěstí WA1) přesněji - program by se na ní zastavil a normálně už by s ním nikdo nehnul.
Proč je použití HALTu tak důležité? Tato instrukce nedělá nic jiného, než že podrží program do té doby, než naběhne přerušení. Pro nás je ovšem zajímavé, že v té samé chvíli začne obvod ULA od levého horního rohu přenášet obsah videoram na obrazovku televizoru (nekreslí se jen bitová videoram, ale i border - prostě úplně stejně, jako cokoliv jiného v televizi). To je třeba mít na paměti, protože takhle si co nejjednodušeji můžete zařídit, aby figurka při chůzi nepoblikávala. Při větším počtu sprajtů je potřeba napsat algoritmus poněkud lépe, ale pro našeho Joa, je ten uvedený až moc dorý.
Když je přerušení, tak jak má být, je obrazovka zaplněna vzorkem. Vzorek (ve výpisu -1, což je totéž jako 255, čili %11111111) můžete libovolně měnit, nejlépe je funkce masky vidět právě při hodnotě 255. Můžete samozřejmě nahrát do obrazovky cokoliv - třeba nějakou pěknou ulici, po které by Joe chodil.
Následuje inicializace. Podprogram INIT nastaví na počátek tabulku pozic, pak nastaví souřadnice Joa (ld hl,#4022) a schová do paměti obsah místa, kam bude postavička nakreslena (call HIDE). Potom je do hl dána adresa první fáze (P+0) a figurka je nakreslena (podprogram DRAW). Výchozí pozici Joa je možné měnit, jak je organizována videoram popisovat nebudu, to už vyšlo v každém časopise snad 50x. Číslo (oněch #4022) můžete měnit, ale sami si hlídejte, aby Joe "neodešel" do atributů a dál do paměti.
No a teď už jenom ta chůze. Řádkem ld b,80 chtěl autor říci, že figurka se 80-krát pohne, číslo lze opět měnit v rozsahu 0 - 255. Podprogram WAIT čeká (překvapivé, co?) a tím ovlivňuje rychlost Joeovy chůze. Zpomalení dosáhnete, když na řádku WAIT ld b,5 dáte do b číslo větší než 5, zrychlení, když je číslo menší než 5. Pozor, nula odpovídá 256.
Podprogram BACK vrací do videoram to, co tam bylo, než byl nakreslen Joe - tedy koná činnost naprosto opačnou k HIDE.
Teď je čas na to, aby byl nakreslen nový Joe a k tomu musí být známa jeho nová fáze a z té odvozena adresa její grafiky. To dělá část programu mezi návěstími POSIT a GO1.
Podíváte-li se na tab. DIRECT, můžete z ní vyčíst fáze pohybu: 2, 3, 4, 1, 5, 6, 7, 1. Fáze 1 je základní, kterou chůze začíná a která je vykreslena při inicializaci. Čísla zvětšená o 128 značí, že při kreslení této pozice bude potřeba zároveň posunout figurku o znak doprava. Nula na konci tabulky znamená skutečně jen konec tabulky a to, že tabulka se musí číst opět od začátku. V tabulce je "chyba": defw 128+1,0 je to samé jako defb 128+1,0,0,0 a jsou tam tedy dvě nuly navíc.
Další tabulka TABLE v sobě nese adresy grafických dat jednotlivých fází. Pro fázi 1 je to adr. P+68, atd.
Poslední tabulkou je SPACE, kam se ukládá původní obsah videoram, tedy místo, kam byl nakreslen Joe.
Nová pozice Joa je určena takto: de ukazuje na začátek a hl někam do tabulky fází (POSIT ld hl,DIRECT - to platí jen na počátku, v průběhu programu je adresa měněna!!!). Hl a de se navzájem zamění a z de je přečteno číslo fáze. Je-li to nula, proběhne záměna znovu a tím se dostáváme opět na počátek tabulky. Fáze je schována do registru b a pak je vymazán 7. bit (ono +128), číslo je vynásobeno dvěma a přičteno k hodnotě TABLE. Jelikož první pozice je 1 (2x1=2) a ne 0 (2x0=0), je třeba místo TABLE použít TABLE-2. Pak je z tabulky získána do de adresa grafických dat a je uložena pro další použití na adr. GO2+1. Do hl se dá adresa ve videoram a byl-li nastaven bit 7 v registru b (fáze), je proveden posun o znak vpravo (inc hl).
Pak už je postup stejný jako při inicializaci - nejprve je pozadí uloženo do tabulky SPACE (call HIDE) a pak je vykreslena nová figurka (call DRAW) a tento celý proces je opakován (djnz GOES). Toť vše.
Studium podprogramů HIDE a BACK si proveďte sami - jsou si navzájem dost podobné, dělají přibližně totéž a hlavně: dělají to dost rychle (ale ne nejrychleji). Rychlost by šla zvýšit nahrazením podprogramu NEXTHL jeho přímým zařazením do rutiny, ušetřilo by se 17 taktů v každém průchodu. Rychlejší instrukce přesunu než ldi už neexistují, ale daly by se obejít pomocí push a pop; v tom případě by musely být rutiny úplně předělány a navíc by bylo třeba v nich zakázat přerušení.
Pro zajímavost si zkuste napsat rutinu, mající tyto vstupní parametry: hl = volné místo v paměti, de = levý horní roh sprajtu, bc = 256*výška+šířka (nebo číst nějakým způsobem odpovídající); a přemisťující obdélník o šířce c znaků a výšce b bodů z videoram do paměti (nebo naopak). Pak tento podprogram protrasujte monitorem assembleru Prometheus a zjistěte jeho časovou náročnost (T-cykly) - schválně jak se vám to povede (pro porovnání kvality rutin musíte ovšem mít stejné vstupní parametry, resp. rozměry obdélníčku).
Kreslicí podprogram DRAW je dost podobný tomu z AnimAce č. 3. Všimnete si, že není univerzální (univerzální nejsou ani HIDE a BACK), a že dokáže kreslit jen sprajty o šířce dva znaky (výška může být libovolná). Pro rychlou animaci je výhodnější používat na míru šité rutiny, většinou tím odpadne nějaká opakovací smyčka a tím pádem se ušetří i spousta času.
Uvedený a popsaný algoritmus lze ještě krásně zoptimalizovat a zrychlit: když schováte do paměti pozadí a když vzápětí kreslíte novou figurku, pohybujete se na obrazovce vždy na tom samém místě - proč tedy nenapsat podprogram jeden, který by dělal obě dvě věci najednou? Ušetřil by se čas za opakovací smyčku a za předávání parametrů - uvědomíte-li si, jak často se podprogramy provádějí, pochopíte, že zde by neměl být "ani takt nazmar", protože může celkem drasticky ovlivnit výslednou rychlost programu.
Tímto končí nejen pátý díl AnimAce, ale vlastně i seriál samotný. Příště už se nebudeme pouštět do ničeho velkého, připravím pro vás jen nějaké vánoční překvapení (jak se znám, určitě to nebude nic hezkého...) a rozloučíme se. Rád bych se dozvěděl, zda vám byly mnou sdělené informace k něčemu dobré, zda vás seriál zaujal, co všechno byste chtěli vědět o animaci a bojíte se na to zeptat, zda má cenu pro příští rok připravovat pokračování a na jak složité úrovni. Zde bych upozornil, že nerad píšu pro úplné začátečníky - asi proto, že když jsem se sám učil programovat, nemohl jsem se z časopisů dozvědět nikdy víc než to, že znak vytiskneme RST #10, což omílali (a stále ještě omílají) všude nejmíň padesátkrát (oblíbené téma je i videoram na Spectru, jak jsem se zmínil již výše). Na výuku je nejlepší knížka, kde je všechno pohromadě - takových "učebnic" se dá sehnat několik na dost dobré úrovni.
Pokud tedy AnimAce II, pak jedině pro pokročilé.
(pokračování příště)