6. Obsluha válců
Přikopírujte soubor GAMETAB.INC, který byl vygenerován pomocí programu GAMETAB, a změňte obsah souboru PROGRAM.ASM:
|
Na konec souboru PROGRAM.ASM jsou doplněny některé definice potřebné pro obsluhu válců, které budou později umístěny v jiném souboru. Jsou zde definice konstant symbolů na válcích, pozice symbolů pro jednotlivé výherní linie a prázdné funkce, které budou později nahrazeny obsluhou pro přehrávání zvuku a zobrazení kláves.
Připravte soubor REELS.ASM a naplňte jej následujícím obsahem:
|
Soubor REELS.ASM zajišťuje obsluhu válců - zobrazení válců, animaci jejich otáčení a animaci podsvěcujících žárovek. Při vývoji bychom běžně vytvořili nejdříve funkci pro zobrazení válců a až po jejím vyzkoušení bychom pokračovali animací. Tady tyto dílčí kroky přeskočíme a zaměříme se už na hotový tvar kódu.
Během inicializace programu je volána funkce InitSymbOff, která vypočte offsety symbolů ve zdrojovém obrázku a uschová je do tabulky SymbOff.
Vykreslení jednoho symbolu na válci zajišťuje funkce DrawSymbol. Funkci je ve vstupních parametrech předáno číslo požadovaného symbolu (0 až 5), číslo válce a vertikální souřadnice. Funkce přitom zajistí, že části symbolu spadající mimo okno válců budou ořezány a že směrem k okrajům okna budou linky ztmaveny (aby se tak vytvořil dojem trojrozměrného vzhledu).
Jako první úkon si funkce připraví adresu tabulky jasů linek odpovídající příslušnému číslu válce. Každý válec má svou tabulku jasů linek, aby tak bylo možné zajistit obsluhu podsvěcujících žárovek. Tabulky jsou připraveny funkcí SetBulbs (popsáno později). Adresu tabulky si uschová do registru ES (je to segmentový registr, ale to není nijak na závadu).
Následuje korekce výšky symbolu a příprava počáteční linky. Při této operaci program zjistí, zda symbol nepřesahuje horní nebo dolní okraj okna válců. Pokud ano, sníží zobrazenou výšku symbolu a pro horní přesah opraví první zobrazenou linku symbolu.
Dále si program připraví cílový offset k uložení obrázku (nebo jeho části), který odvodí z čísla válce (horizontální souřadnice) a cílového čísla linky (vertikální souřadnice). Zdrojový offset si program přečte z tabulky offsetů symbolů, k offsetu přičte korekci podle první zobrazené linky symbolu.
Nyní již následuje vykreslení symbolu. Program postupně vykresluje jednotlivé linky a pro každou linku načítá z tabulky jasů linek jas dané linky. Jedná-li se o ztmavenou linku, vypočte adresu příslušné tabulky tmavých barev a vykreslí linku funkcí DrawDark. V opačném případě linku vykreslí funkcí DrawLine.
Funkce DrawReel vykreslí jeden válec. Vstupními parametry jsou: index symbolu na výherní linii 0, relativní offset symbolu v rozsahu 0 až 255 (slouží k jemnému posunu válce) a číslo válce. Z indexu symbolu si funkce připraví offset v tabulce definice symbolů na válci, který ukazuje na symbol na horním okraji vykreslovaného válce. Z relativního offsetu symbolu funkce odvodí vertikální souřadnici prvního symbolu. Z čísla válce si připraví adresu tabulky s definicí symbolů na válci. Následující cyklus postupně vykresluje jednotlivé symboly válce. Z tabulky symbolů určí symbol nacházející se na příslušné pozici. Postupuje směrem shora dolů, až se ocitne pod dolním okrajem okna válců.
Pomocí funke RedrawReels jsou vykresleny všechny 3 válce. Pozice válců je načítána z pole slov ReelPos, ve kterém představuje vyšší bajt index symbolu v seznamu symbolů válce, nižší bajt je relativní posun symbolu v rozsahu 0 až 255.
Funkce SetBulbs nastaví svit žárovek podsvěcujících válce. Každá pozice válce může být podsvícena jednou z 9 žárovek. Vstupem funkce je bitová maska linií, jejichž žárovky mají svítit. Funkce nejdříve vynuluje buffer příznaků svitů žárovek (jedná se o tabulku o 3 sloupcích a 3 pozicích). Poté prochází příznaky svitu jednotlivých linií a za pomoci tabulky pozic v liniích nastavuje příznaky svitu žárovek v liniích.
Po sestavení příznaků svitu jednotlivých žárovek si funkce připraví tabulky jasu linek pro jednotlivé válce jako kopii tabulky jasu linek Darkness, která byla vygenerována funkcí InitDarkTab. Prochází jednotlivé válce a jednotlivé žárovky na nich a pokud narazí na nesvítící žárovku, provede ztmavení příslušné oblasti v tabulce jasů linek ztmavením jasu o 3 stupně.
Kromě zobrazení válců obsluhuje soubor REEL.ASM obsluhu otáčení válců. Aktuální pozice jednotlivých válců se uchovává v poli slov ReelPos. Nižší bajt slova představuje jemný posun jednoho symbolu válce v rozsahu 0 až 255, vyšší bajt je index symbolu na válci nacházející se na výherní linii 1 (tj. střední linie).
Při otáčení válců je vypočítán úsek, o kolik se každý válec má otočit (z rozdílu požadované a aktuální pozice). Rychlost válce je nejdříve rovnoměrně zvyšována a od poloviny úseku opět snižována. Rychlost otáčení není po náběhu omezena na určitou provozní rychlost jako u reálných válců, což je určité zjednodušení (vizuálně není patrný rozdíl) a válce tak dosáhnou své koncové pozice dříve a s rovnoměrnějším dojezdem.
Přípravné výpočty pro otáčení válců provádí funkce CalcReel. Vstupními parametry jsou: maska směrů (každý válec se může točit jiným směrem), příznak rychlého nebo pomalého otáčení (při pomalém otáčení se válce otočí na cílovou pozici pomalou rovnoměrnou rychlostí) a cílová pozice válců.
Na začátku si funkce připraví celý počet otáček válců. Při rychlém otáčení (losování) se první válec otočí navíc o 1 celou otáčku, druhý o 2 a třetí o 3 otáčky. Tím je dosaženo efektu, že se válce zastavují postupně zleva doprava. Při pomalém otáčení nejsou žádné doplňkové otáčky přidávány.
Dále jsou nastaveny časy počátku otáčení válců. Druhý válec se roztáčí s malým zpožděním oproti prvnímu, třetí s malým zpožděním oproti druhému. Tento efekt slouží k vytvoření dojmu roztáčení mechanických válců. V režimu pomalého otáčení se zpoždění nepoužívá.
Následuje příprava parametrů jednotlivých válců pomocí cyklu. Funkce uloží do pole ReelDir požadovaný směr otáčení a do pole ReelEnd požadovanou koncovou pozici válců.
Z požadované koncové a aktuální pozice vypočte rozdíl, o kolik se mají válce otočit, rozdíl zarovná do intervalu 0 až 1 otáčka a přičte jej k čítači zbylých kroků otáčení (na začátku funkce do něj byly připraveny přídavné celé otáčky).
V režimu pomalých otáček funkce odstartuje otáčení nastavením adresy pro pomalé otáčení (podrobněji popsáno dále). V režimu rychlých otáček je zbývající úsek otáčení prodloužen o úsek pro překmit válců, aby byl zvýšen dojem realističnosti simulace válců a nastaví se adresa pro čekání na zahájení otáčení.
Animace otáčení válců je zprostředkována funkcí Int08. Jedná se o obsluhu přerušení Int 08h, které je vyvoláváno hardwarově v daných intervalech. Instalace obsluhy přerušení probíhá ve funkci IntInit v souboru PROGRAM.ASM. Rychlost přerušení od hodin je nastavena na frekvenci 145.652 Hz, přerušení tedy nastává zhruba každých 7 ms, což je osminásobek frekvence standardní obsluhy přerušení Int 08h (18.2 Hz, tj. každých 55 ms). Aby byla zajištěna správná obsluha původního přerušení Int 08h, pokračuje obsluha Int 08h v původním přerušení pouze každou osmou obsluhu, jinak provede sama obsluhu ukončení přerušení. Tím je zajištěna původní obsluha přerušení s frekcencí 18.2 Hz.
Na začátku obsluhy Int 08h se volají pomocné časovací obsluhy - přehrávání zvuku SoundInt a čítač animace blikání kláves. Animace válců je realizována skokem na adresu obsluhy podle pole ReelAddr. V obsluze Int 08h se provádí pouze výpočty pozice válců, zobrazení válců zajišťuje funkce TurnReels. Oddělení části pro časování od části pro vykreslování je potřebné z toho důvodu, že jedno vykreslení může trvat různě dlouhou dobu, třeba i několik časových impulsů. Tímto způsobem je zajištěna stabilní rychlost animace, nezávislá na rychlosti PC.
Obsluha pomalého otáčení válců začíná na adrese Int08Slow. Každý časový impuls se válce posunou o úsek daný konstantou SLOWSPEED a sníží se čítač zbývajících kroků. Dosáhne-li se koncové pozice, změní se adresa následující obsluhy na Int08Stop.
Obsluha rychlého otáčení začíná na adrese Int08Wait. Zde jsou čítány časy pro zahájení otáčení válců. Je-li dosaženo 0, změní se adresa příští obsluhy na Int08In.
Int08In je "náběh" válce. Z počtu kroků uběhlých od počátku animace se vypočte aktuální rychlost, která se s danou akcelerací zvyšuje. Je-li uběhlá část větší než zbývající část, válec se dostal za polovinu počtu kroků a další obsluha se změní na Int08Out.
Int08Out je "doběh" válce. Aktuální rychlost se vypočte z počtu zbývajících kroků, s určitým zpomalením se snižuje. Po uběhnutí daného počtu zbývajících kroků se další obsluha změní na Int08Over.
Int08Over je obsluha zákmitu. Otáčky válce byly nastaveny tak, aby válec o určitý úsek přesáhl cílovou pozici. V obsluze zákmitu se válec dostává na cílovou pozici konstantní doběhovou rychlostí, která je obrácená proti směru otáčení.
Všechny obsluhy otáčení končí na adrese Int08Move, kde se zajistí otočení válce o úsek v obsluze vypočtený. Je přitom rozlišen směr otáčení, aby směr nemusela řešit obsluha otáčení.
Výchozí funkcí animace otáčení válců je funkce TurnReels. Jejím vstupem je maska směrů, příznak rychlého nebo pomalého otáčení a cílová pozice válců. Na začátku funkce je volána příprava parametrů pro otáčení válců CalcReel a zahájeno přehrávání zvuku otáčení válců. Zpětné otáčení je využíváno k indikaci bonusové hry a používá jiný zvuk než otáčení vpřed.
V následujícím cyklu se opakovaně překreslují válce na aktuální pozici. Obsluha přerušení Int 08h, běžící "na pozadí", průběžně počítá aktuální pozici válců během jejich otáčení. Proto jsou v této vykreslovací smyčce neustále testovány adresy pro obsluhu animace. Smyčka animací je ukončena, pokud jsou adresy obsluh všech válců nastaveny na Int08Stop. Ve vykreslovací smyčce je sledován počet točících se válců (válce se zastavují postupně od prvního válce), při snížení počtu točících se válců je přehrán zvuk zastavení válců. Test pro ukončení otáčení válců je prováděn před obsluhou vykreslení válců z důvodu, aby bylo zajištěno alespoň jedno překreslení válců po ukončení otáčení (pokud by obsluha zastavení proběhla v době mezi testem a vykreslením).
Do souboru PROGRAM.ASM jsme přidali generátor náhodného čísla Random. Generátor používá populární algoritmus zveřejněný Microsoftem pro interpreter jazyku BASIC, "náhodné_číslo = předešlé_číslo * 214013 + 2531011". Pro zabránění odvození příštího čísla v posloupnosti pseudonáhodných čísel navrací funkce pouze vyšší slovo 32-bitového náhodného čísla. Generátor náhodných čísel je inicializován funkcí RandomInit z čítače času, čímž je zajištěna náhodnost posloupnosti generovaných čísel.
Hlavní funkce programu je doplněna o obsluhu otáčení válců na náhodnou pozici. Na začátku jsou opět nastaveny palety grafické karty a zobrazeno pozadí obrazovky. Žárovky všech linií jsou rozsvíceny, tím jsou současně vygenerovány jasy linek pro zobrazení válců. Generátorem náhodných čísel je vygenerována náhodná pozice válců, válce jsou poté na tuto pozici natočeny. Je-li následně stisknuta klávesa mezerníku, provede se otočení válců na novou náhodnou pozici, jinak je program ukončen.
Po překladu program spusťte a vyzkoušejte, zda se válce po stisku mezerníku otáčí na náhodnou pozici a zda probíhá správně vykreslování válců.
Download zdrojového kódu obsluhy válců