Projekt do MMIA - Tetris

David Bilko, Lukáš Klozar, UREL, FEEC, VUT Brno
dotazy na: fedrazfeec.vutbr.cz

Obsah:

  1. Úvod
  2. Realizace
  3. Závěr
  4. Literatura

Úvod

Tetris je populární hra, jejíž princip je známý snad každému. Je použito celkem 7 kostek, tvary jsou: kostka, písmenko L, obrácené L, Z, S, I, T. Každé písmenko je možno otáčet, a to v jednom směru. Jednotlivé tvary kostek jsou uloženy ve vícerozměrných polích. Ovládání pohybu kostek je prostřednictvím tří bitů portu B (posun doleva, doprava a rotace).



Realizace

Porty A a C jsou aktivní v log. 0 a určují barvu, kterou má svítit LED ( A-zelená, C-červená), z portu B jsou použity bity 0-2 a určují adresu aktivního řádku. Pro zobrazení hry na poli 8x8 LED diod, připojených na porty A,C a B, je využito dvou polí. Jsou to pole: poule a poule2. V poli poule2 je zobrazována padající kostka a v poli poule je statické okolí (předchozí spadlé kostky). Obě pole jsou rozměru 12x8, kromě osmi spodních řádků vymezujících aktivní oblast zobrazení, jsou ještě přidány čtyři řádky k načtení celého symbolu před zahájením pádu tzv. buff. K položkám pole se přistupuje pomocí pointrů. Jednotlivé kostky vstupující do hry jsou určeny vlastním číslem (proměnnou typu int) označeným c. Generace náhodného čísla c je zajištěna funkcí rand() ve funkci jaky_tvar(). Podle čísla c=0-6 je tedy vybrán symbol zobrazovaný na displeji. Vybírá se podle indexu (proměnná typu int) roto v poli ukazatelů, které ve výsledku směřují na vícerozměrné pole daného symbolu, v němž jsou uloženy možné rotace dané kostky (např. kostka ve tvaru I může nabývat dvou rotací, tedy čtyři aktivní prvky (LED) vedle sebe v horizontální nebo vertikální rovině). Všechny kostky jsou uloženy v polích unsigned char s rozměrem 4. Po vybrání tvaru je nutné načíst aktuální rotaci vybrané kostky, toho se dosahuje ve funkci zap_tvar() zkopírováním adresy posledního řádku symbolu do ukazatele *sp. Poté se určuje ve funkci aktiva() kolik řádků zabírá padající kostka v aktuální rotaci, počet řádků je uložen v proměnné typu int rad. Počet řádků je využíván pro cykly vykreslující posun kostky. Následuje funkce načtení_symbolu() ve které se aktuální tvar kostky načte do stavového pole kostka. Aktivní změna pádu kostky je prostřednictvím stisku tlačítka na klávesnici, která je připojena na port B. Hlavní tělo programu je složeno z posloupnosti funkcí a cyklů, které budou dále popsány. Ve funkci main je chod hry volán funkcí hlavní(), která řídí celý proces od začátku hry po její konec. V případě konce hry, který může nastat pokud je v nejvrchnějším řádku aktivní oblasti pole statického okolí nějaká aktivní LED, se spustí nekonečná smyčka while(1). Tato smyčka čeká na stisk tlačítka připojeného na pin 0 portu D. Pokud dojde ke stisku spustí se opět nová hra funkcí hlavní().





Hlavní tzv. Symbolový cyklus (funkce hlavní()) zahrnuje celý chod programu a počet jeho cyklů vyjadřuje počet padajících kostek. V tomto cyklu je zahrnut kompletní výběr a načtení symbolu do oblasti nad aktivní částí pole pro kostky.



…Součástí tohoto cyklu je tzv. Řádkový cyklus, v němž jsou obsaženy procedury řešící pohyb kostky polem, cyklus zobrazeni na poli 8x8LED a ošetření stisku tlačítek. Počet opakování Řádkového cyklu je roven počtu řádků aktivní oblasti, tedy 8. Na začátku se kontroluje, jestli nedošlo k překrytí aktivních LED. Pokud došlo k překrytí nakopíruje se kostka na předchozí řádek do polí poule a poule2.



V Řádkovém cyklu je pak další cyklus vykreslování v němž jsou nastaveny porty. Délka cyklu určuje dobu vykreslování jednoho stavu kostky na displeji. Samotné zobrazení je provedeno pomocí funkce zobraz_fce().



Dále je nastaven port D a zjišťuje se jestli došlo ke stisku tlačítka piny 3, 2, 1. V případě detekce stisku tlačítka je z důvodu ošetření zákmitů cyklus v němž se zobrazuje na LED poli aktuální stav hry. Po tomto cyklu, je podle pinu, na kterém byla detekována nula, volána některá z funkcí posunP(), posunL(), rotace().
Po skončeni Řádkového cyklu je nakopírována „dopadlá“ kostka do pole statického okolí (stane se z ní nepohyblivé prostředí). Poté skonči padání jedné kostky a začíná nové opakování Symbolového cyklu.



Program je uložen ve dvou souborech. V hlavním zdrojovém souboru tetrix_3.c jsou definovány globální proměnné, definována funkce řídící hru (hlavní();) a je v něm i funkce main. V druhém souboru fce.c jsou definovány funkce volané pro obsluhu hry. Seznam funkcí a jejich popis je níže.

Seznam funkcí

void mazani (void) //pokud bylo po skončeni cesty jedné kostky v nějakém řádku
  //samé jedničky tak je smaže a zbytek posune
int jaky_tvar() // náhodný vyber tvaru kostky
void zap_tvar(int stav) //aktivuje příslušnou rotaci kostky>
void aktiva (unsigned char *isp) //funkce na počítání nenulových řádků padající kostky
void nacteni_symbolu (void //načte symbol do stavového pole koska(pk2)
void kontrola_kauzality(int ix) //kontroluje jestli kostka ve stavovém poli nepřekryla
  // aktivní LED ve statickém obrazu
void posunP (void) //posune kostku ve stavovém poli doprava
void posunL (void) //posune kostku ve stavovém poli doleva
void rotace ( void ) // funkce která otočí kostku
void zobraz_fce(void) // funkce vykreslující stav hry na LED


Popis funkcí

Funkce: mazani

Uplatňuje se pokud byl nějaký řádek v poli statického okolí zcela zaplněn. Smaže řádek a posune zbytek pole. Kontroluje pole poule od poslední adresy pomocí ukazatele ppouk. V případě detekce plně obsazeného řádku posune obraz nad aktuálním řádkem o jeden řádek níž as pak začne kontrolu opět od posledního řádku pole poule.



Funkce: jaky_tvar
Náhodný výběr tvaru nové kostky



Funkce: zap_tvar
Načte adresu aktuálního tvaru kostky do pomocného ukazatele *sp. Předává se jí parametr, který určuje jaká je aktuální rotace vybrané kostky. V případě, že se kostka již otočila do své maximální polohy, začíná se opět od nuly.




Funkce: aktiva
Počítá aktivní řádky kostky v pomocném ukazateli *sp, který se funkci předává jako parametr *isp. Počet řádků kostky je indikován v proměnné int rad.



Funkce: nacteni_symbolu
Překopíruje aktuální tvar kostky do stavového pole koska pomocí ukazatelů.



Funkce: kontrola_kauzality
Zjišťuje jestli v současném řádku nedošlo k překrytí aktivních LED polí poule a poule2. Pokud je indikováno překrytí inkrementuje kontrolní proměnnou int sta.



Funkce: posunP
Posouvá kostku ve stavovém poli koska o jeden bit doprava. Kontroluje dva problémy které takto mohou nastat. Jestli nebylo dosaženo konce zobrazované plochy ( pomocná proměnná konec_obrazovky) a pokud nebylo posune kostku a kontroluje zda-li posunem nedošlo k překrytí aktivních LED v poli statického okolí (poule), pomocná proměnná prekryti_kostek. Pokud budou obě pomocné proměnné nulové tak bude kostka posunuta a inkrementuje se další stavová proměnná značící, že došlo k posunu (využito ve funkci rotace ()).




Funkce: posunL
Stejné jako posun doprava, jen s tím rozdílem, že posouvá doprava a testuje tedy konec „obrazovky“ na druhou stranu.




Funkce: rotace
Tato funkce slouží k otáčení kostek v jednom směru. Index otočení, neboli proměnná určující v jakém stavu rotace se nachází kostka, je označena int roto. Na začátku se nastaví správná rotace a vypočtou se její aktivní řádky, poté se nahraje do záložního pole save(*rsp). Dále se testuje jestli došlo k posunu doleva nebo doprava (volání funkce posunL(), posunP()) a v případě, že došlo, posune aktuální rotaci o jeden bit. Předtím musí dojít ke kontrole jestli nebylo dosaženo konce „obrazovky“. Nakonec kontroluje jestli posunem či rotací nedošlo k překrytí aktiv. LED v poli statického obrazu poule. Pokud nedošlo k překrytí, zkopíruje se záložní pole save(*rsp) do stavového pole koska(*pk2).




Funkce: zobraz_fce
Tato funkce obstarává správné vykreslení obsahu zobrazovacích polí. Poule2 (*ppou22) do něhož se kopíruje obsah stavového pole koska(*ppou11) a pole poule(*ppou11) v němž je uložen statický obraz. Napřed je vybrán aktuální řádek a jeho číslo je vysláno na portB. Poté se na port A pošle celé slovo (jeden řádek ze zobrazovacího pole). Po vyslání symbolu na port A je čekací funkce delay_ms(1) behěm níž, je na portu A vykreslováno stále stejné slovo.




Ukázka ze hry:



Závěr

V programu je hojně využíváno ukazatelů k adresování položek v polích. Program při zkoušení na vývojové desce v laboratoři se jeví jako funkční. Vylepšení programu by bylo možno přidáním dalších funkcí. Jedna z funkcí by mohla být tzv. rychlý pád, která by posunula padající kostku na konec obrazu, nebo dokud by nedošlo k překrytí LED ve statickém poli. Další by mohla být funkce počítání odbouraných řádků a jejich zobrazování na displeji. Dále by se podle počtu odbouraných řádků mohla zvyšovat rychlost pádu kostky, tedy počet opakování vykreslovacího cyklu(proměnná typu int rychlost). Je použita knihovna delay.c pro zpožďovací cykly.

Ke stažení ZDE.

Literatura

[1] FRÝZA, Tomáš, FEDRA, Zbyněk, ŠEBESTA, Jirí. Mikroprocesorová technika : Laboratorní cvičení. [s.l.] : [s.n.], [199-?]. 51 s. Dostupný z WWW: https://krel.feec.vutbr.cz/VYUKA/M_EST/MMIA/Texty/bmpt_laboratore.pdf.