Individální projekty MPOA

Mikroprocesory s architekturou ARM

Uživatelské nástroje

Nástroje pro tento web


2016:brick-game

Rozdíly

Zde můžete vidět rozdíly mezi vybranou verzí a aktuální verzí dané stránky.

Odkaz na výstup diff

Obě strany předchozí revize Předchozí verze
Následující verze
Předchozí verze
2016:brick-game [2017/01/13 15:24]
Viktor Typovský
2016:brick-game [2017/01/13 17:49] (aktuální)
Viktor Typovský
Řádek 25: Řádek 25:
  
 ====== Software ====== ====== Software ======
-Software je psaný v online vývojovém prostředí [[http://​mbed.org|mbed.org]]. Celý zdrojový kód je k distpozici ZDE.\\+Software je psaný v online vývojovém prostředí [[http://​mbed.org|mbed.org]]. Celý zdrojový kód je k distpozici ​[[https://​developer.mbed.org/​users/​xtypov00/​code/​BrickGameRacing/​|ZDE]].\\
 Vzhledem k poměrně podrobnému okomentování ve skriptu budu uvádět pouze stručný popis jednotlivých funkcí.\\ Vzhledem k poměrně podrobnému okomentování ve skriptu budu uvádět pouze stručný popis jednotlivých funkcí.\\
 Volání funkcí, které zajišťují pohyb předem definovaných struktur jsem zvolil pomocí časovačů,​ protože ve while smyčce se mi to zdálo příliš komplikované. Časovač jsem si definoval do třech proměnných,​ pro lepší přehlednost Volání funkcí, které zajišťují pohyb předem definovaných struktur jsem zvolil pomocí časovačů,​ protože ve while smyčce se mi to zdálo příliš komplikované. Časovač jsem si definoval do třech proměnných,​ pro lepší přehlednost
Řádek 33: Řádek 33:
 Funkce main v podstatě řídí celý  algoritmus. Nejprve se provede inicializace, ​ počátečního ​ polohy autíčka hráče a svodidel (autíčka počítače ještě nejsou v inicializačním obraze přítomna). Následně se nastaví časovače. Pomocí nich je realizováno nejen samotné zobrazování,​ ale také pohyb předem nastavených struktur – tj. konstantní pohyb svodidel a aut počítače a počáteční poloha autíčka hráče, definovaná vpravo.\\ Funkce main v podstatě řídí celý  algoritmus. Nejprve se provede inicializace, ​ počátečního ​ polohy autíčka hráče a svodidel (autíčka počítače ještě nejsou v inicializačním obraze přítomna). Následně se nastaví časovače. Pomocí nich je realizováno nejen samotné zobrazování,​ ale také pohyb předem nastavených struktur – tj. konstantní pohyb svodidel a aut počítače a počáteční poloha autíčka hráče, definovaná vpravo.\\
 Následuje nekonečná smyčka while, ve které je realizováno snímání akcelerometru,​ na jehož základě se pak mění poloha autíčka hráče. Dále je zde řešena i možnost kolize. V případě, že se tak stane, dojde k zmrazení matice, místo autíčka hráče se objeví jakýsi myšlený „vrak autíčka“ a celý program se resetuje. ​ Následuje nekonečná smyčka while, ve které je realizováno snímání akcelerometru,​ na jehož základě se pak mění poloha autíčka hráče. Dále je zde řešena i možnost kolize. V případě, že se tak stane, dojde k zmrazení matice, místo autíčka hráče se objeví jakýsi myšlený „vrak autíčka“ a celý program se resetuje. ​
 +
 +<code cpp>
 +int main() ​
 +{  ​
 +    Inicializace(); ​                        //​iniacalizace počátečních podmínek
 +    disptick.attach(&​Zobraz,​ 0.002); ​       //​nastavení časovače pro rozsvicování displaye
 +    tick.attach(&​SvodidlaPohyb,​ 1);         //​nastavení časovače pro volání funkce zabezpečující pohyb svodidel
 +    tick2.attach(&​AutaPohyb,​ 0.25); ​        //​nastavení časovače pro volání funkce zabezpečující pohyb aut počítače
 +    while(1) ​
 +    { 
 +        Pohyb(); ​                               //​ovládání pozice auta hráče pomocí akcelerometru
 +        Kolize(); ​                              //​detekce kolize auta hráče s auty počítače  ​
 +    }
 +}
 +</​code>​
 +
 +
  
  
 ==== Zozbraz ==== ==== Zozbraz ====
-Tato funkce je jedna z nejdůležitějších,​ protože má na starost celé to kouzlo zobrazování. Pracuje s předem definovanými poli 8x8 pro zelené a červené LEDky, jejichž aktuální stav zobrazuje po řádcích. Zbylé funkce tedy již pracují pouze s definovanými poli, jejichž změnou vytvářejí výsledný obraz. Volání funkce je řešeno přes časovač každou 0,002 s.+Tato funkce je jedna z nejdůležitějších,​ protože má na starost celé to kouzlo zobrazování. Pracuje s předem definovanými poli 8x8 pro zelené a červené LEDky, jejichž aktuální stav zobrazuje po řádcích. Zbylé funkce tedy již pracují pouze s definovanými poli, jejichž změnou vytvářejí výsledný obraz. Volání funkce je řešeno přes časovač každou 0,002 s.\\ 
 + 
 +Příklad funkce pro práci s polem zelených LED.
  
 +<code cpp>
 +// pracovní pole pro matici zelených LED                   
 +int poleZeleny[8][8] = {                                       
 +                   {0, 0, 0, 0, 0, 0, 0, 0},             
 +                   {0, 0, 0, 0, 0, 0, 0, 0},    ​
 +                   {0, 0, 0, 0, 0, 0, 0, 0},    ​
 +                   {0, 0, 0, 0, 0, 0, 0, 0},    ​
 +                   {0, 0, 0, 0, 0, 0, 0, 0},    ​
 +                   {0, 0, 0, 0, 0, 0, 0, 0},    ​
 +                   {0, 0, 0, 0, 0, 0, 0, 0},    ​
 +                   {0, 0, 0, 0, 0, 0, 0, 0},  };
 +                   
 +void Zobraz(void)
 +{
 +        static int line = 0;        //proměná inicializující prnví řádek
 +                   
 +        AdresRadku(line); ​          //​adresování řádků pomocí funkce AdresRadku() ​
 +        ​
 +        //​Rozsvicování LEDek je zajištěno jejich uzeměním - tedy, když je na řídící vstup přivedena 0.
 +        //Z důvodu lepší oirentace při práci bylo využito negace, aby v následujícím algoritmu rozsvícení LEDek 
 +        //​způsobovalo číslo 1.
 +                ​
 +        //​rozsvicování zelených LED
 +        zelena0 =! poleZeleny[line][0]; ​     ​
 +        zelena1 =! poleZeleny[line][1];​
 +        zelena2 =! poleZeleny[line][2];​
 +        zelena3 =! poleZeleny[line][3];​
 +        zelena4 =! poleZeleny[line][4];​
 +        zelena5 =! poleZeleny[line][5];​
 +        zelena6 =! poleZeleny[line][6];​
 +        zelena7 =! poleZeleny[line][7];​
 +        ​
 +        wait(0.001); ​               //​zpožděni-aby se to stihlo rozsvitit
 +        line++; ​                    //​přepis proměnné na další řádek
 +        if(line == 8)               //v případě,​že dojde na konec,jede se od zacatku
 +        {              ​
 +                line = 0;
 +        }
 +}
 +</​code>​
 ==== Inicializace ==== ==== Inicializace ====
 Tato funkce proběhne pouze jednou na začátku programu nebo pokaždé při restartu zařízení. Má za úkol přenastavit pracovní pole tak, aby při každém startu (restartu) začínala hra za stejných počátečních podmínek (ze stejného počátečního obrazu). Nastaví tedy počáteční polohu oranžových svodidel a zeleného autíčka hráče. Tato funkce proběhne pouze jednou na začátku programu nebo pokaždé při restartu zařízení. Má za úkol přenastavit pracovní pole tak, aby při každém startu (restartu) začínala hra za stejných počátečních podmínek (ze stejného počátečního obrazu). Nastaví tedy počáteční polohu oranžových svodidel a zeleného autíčka hráče.
  
 +<code cpp>
 +void Inicializace(void){
 +    int col;
 +    int row;
 +/​*------------inicializace svodidel--------------*/ ​   ​
 +    for(col=0;​col < 8; col = col+7)
 +    {    ​
 +        for(row = 0; row < 8; row++)
 +        {  ​
 +            if(row == 0 ||row == 4)
 +            {      ​
 +                poleCerveny[row][col]=0; ​
 +                poleZeleny[row][col]=0;​
 +            }                                                      ​
 +            else
 +            {
 +               ​poleCerveny[row][col]=1;​
 +               ​poleZeleny[row][col]=1;​
 +            } 
 +        }
 +    } 
 +/​*----inicializace auta hráče - pozice napravo---*/​
 +        poleZeleny[4][4] = 1;
 +        poleZeleny[5][4] = 1;
 +        poleZeleny[6][4] = 1;
 +        poleZeleny[4][5] = 1;
 +        poleZeleny[5][5] = 1;
 +        poleZeleny[6][5] = 1;   
 +}
 +</​code>​
 ==== SvodidlaPohyb ==== ==== SvodidlaPohyb ====
 Úkolem této funkce je zajištění konstantního pohybu oranžových svodidel na okrajích matice. Pohyb je dán rychlostí 1 pixel / 1 sekundu (podle nastavení časovače, který tuto funkci volá). Úkolem této funkce je zajištění konstantního pohybu oranžových svodidel na okrajích matice. Pohyb je dán rychlostí 1 pixel / 1 sekundu (podle nastavení časovače, který tuto funkci volá).
  
 +<code cpp>
 +void SvodidlaPohyb(void)
 +{
 +    int col;
 +    int row;
 +    int pom1; //pomocná proměnná ​   ​
 +    ​
 +    pom1 = poleCerveny[7][0];​ //uloží hodnotu v poslendím 8. radku
 +    ​
 +    //posune svodidla o 1 pozici směrem dolu při každém zavolání funkce ​   ​
 +    for(col=0;​col < 8; col = col+7) ​    //​pracuje pouze v 1. a v posledním sloupci
 +    {
 +        for(row = 7; row > 0; row--) ​   //7. až 1. řádek přepíše na 8. až 2.
 +        {
 +          poleCerveny[row][col] = poleCerveny[row-1][col]; ​
 +          poleZeleny[row][col] = poleZeleny[row-1][col]; ​    
 +        }
 +    }   
 +    //poslední řádek přepíše jako 1. 
 +    poleCerveny[0][0] = pom1;
 +    poleCerveny[0][7] = pom1;
 +    poleZeleny[0][0] = pom1;
 +    poleZeleny[0][7] = pom1;
 +}
 +</​code>​
 ==== AutaPohyb ==== ==== AutaPohyb ====
 Tato funkce generuje auta počítače nalevo nebo napravo, v závislosti na hodnotě binární pseudonáhodné sekvence. Kromě rozsvicování LEDek v místech, kde se nachází auta počítače,​ však funkce musí dále zhasínat ty LEDky, kudy auto počítače prošlo. To řeší pomocí pomocných proměnných,​ které si pamatují předcházející polohy aut počítače,​ v závislosti na tom, zda byli vpravo či vlevo. Funkce je opět volána pomocí časovače každou 0,25 s. Tato funkce generuje auta počítače nalevo nebo napravo, v závislosti na hodnotě binární pseudonáhodné sekvence. Kromě rozsvicování LEDek v místech, kde se nachází auta počítače,​ však funkce musí dále zhasínat ty LEDky, kudy auto počítače prošlo. To řeší pomocí pomocných proměnných,​ které si pamatují předcházející polohy aut počítače,​ v závislosti na tom, zda byli vpravo či vlevo. Funkce je opět volána pomocí časovače každou 0,25 s.
  
 +Tato funkce je příliš dlouhá a komplexní na to, abych ji sem dával nebo jenom její část. Hlavní myšlenka je však stejná jako u předchozí funkce SvodidlaPohyb(),​ i když je tato funkce podstatně komplikovanější.
 ==== Pohyb ==== ==== Pohyb ====
 Tato funkce je volána v nekonečné smyčce a má na starost snímání Y-ové osy akcelerometru. Při překročení určitého prahu náklonu pak tato funkce rovnou zajistí změnu polohy autíčka počítače,​ ve kterém autíčko setrvá, dokud nedojde opět k překročení prahu náklonu (vlevo či vpravo). Tato funkce je volána v nekonečné smyčce a má na starost snímání Y-ové osy akcelerometru. Při překročení určitého prahu náklonu pak tato funkce rovnou zajistí změnu polohy autíčka počítače,​ ve kterém autíčko setrvá, dokud nedojde opět k překročení prahu náklonu (vlevo či vpravo).
- + 
 +Ukázka funkce pro náklon vpravo 
 +<code cpp> 
 +void Pohyb(void) 
 +{    
 +    prah = 0.3;          //​nastavení prahu, vymezující úhel detekce 
 +    ay = float(acc.getAccY()); ​         //​odečítání Y-ové osy akcelerometru 
 + 
 +       
 +    if((ay > prah)) ​    //​náklon vpravo 
 +    {        
 +        poloha =4;  //pravý (5.) sloupec 
 +        //rožnout auto hráče napravo 
 +        poleZeleny[4][poloha] = 1; 
 +        poleZeleny[5][poloha] = 1; 
 +        poleZeleny[6][poloha] = 1; 
 +        poleZeleny[4][poloha+1] = 1; 
 +        poleZeleny[5][poloha+1] = 1; 
 +        poleZeleny[6][poloha+1] = 1; 
 +        //zhasnout auto hráče vlevo 
 +        poleZeleny[4][poloha-2] =! 1; 
 +        poleZeleny[5][poloha-2] =! 1; 
 +        poleZeleny[6][poloha-2] =! 1; 
 +        poleZeleny[4][poloha-1] =! 1; 
 +        poleZeleny[5][poloha-1] =! 1; 
 +        poleZeleny[6][poloha-1] =! 1; 
 +    }  
 +
 +</​code>​
 ==== Kolize ==== ==== Kolize ====
 Tato funkce hlídá, jestli nejsou hodnoty červeného a zeleného pole v určitých definovaných místech shodné. Pokud ano, tak se jedná o kolizi autíček. Následné pak funkce zmrazí všechny pohyby, zobrazí místo autíčka hráče „vrak autíčka“ a zavolá funkci Reset. Tato funkce hlídá, jestli nejsou hodnoty červeného a zeleného pole v určitých definovaných místech shodné. Pokud ano, tak se jedná o kolizi autíček. Následné pak funkce zmrazí všechny pohyby, zobrazí místo autíčka hráče „vrak autíčka“ a zavolá funkci Reset.
  
 +<code cpp>
 +void Kolize(void)
 +{  ​
 +    if (poleZeleny[4][poloha] == poleCerveny[4][poloha] || poleZeleny[6][poloha] == poleCerveny[6][poloha])
 +    {
 +        //při detekci kolize dojde ke zmražení všech pohybů
 +        tick.detach(); ​
 +        tick2.detach();​
 +        ​
 +    //​-----zobrazí se oranžový vrak auta-----// ​   ​
 +        poleZeleny[4][poloha-1] = 1;
 +        poleZeleny[5][poloha] = 1;
 +        poleZeleny[6][poloha-1] = 1;
 +        poleZeleny[4][poloha+2] = 1;
 +        poleZeleny[5][poloha+1] = 1;
 +        poleZeleny[6][poloha+2] = 1;
 +        ​
 +        poleCerveny[4][poloha-1] = 1;
 +        poleCerveny[5][poloha] = 1;
 +        poleCerveny[6][poloha-1] = 1;
 +        poleCerveny[4][poloha+2] = 1;
 +        poleCerveny[5][poloha+1] = 1;
 +        poleCerveny[6][poloha+2] = 1;
 +        ​
 +        wait(2); //​zachování tohoto statického obrazu na dobu 2s
 +        Reset(); // zavolá funkci reset
 +    }
 +}
 +</​code>​
 ==== Reset ==== ==== Reset ====
 Z názvu funkce vyplývá, že tato funkce má na starost restart a reinicializaci počátečních podmínek a hodnot. Nejprve však celou RG LED matici vybarví na 2s do červena a následně provede reinicializaci a zruší zmražení všech pohybů. Z názvu funkce vyplývá, že tato funkce má na starost restart a reinicializaci počátečních podmínek a hodnot. Nejprve však celou RG LED matici vybarví na 2s do červena a následně provede reinicializaci a zruší zmražení všech pohybů.
 +
 +<code cpp>
 +void Reset(void)
 +
 +//---na 2s se zobrazí pouze červené LED na celé ploše matice---// ​   ​
 +    for(col = 0; col < 8; col++)
 +    {
 +        for(row = 0; row < 8; row++)
 +        {
 +            poleZeleny[row][col]=0;​
 +            poleCerveny[row][col]=1; ​
 +        }
 +    } 
 +    wait(2);
 +    ​
 +//​--------proběhne resetovací fáze--------//​
 +//zhasnutí celé LED matice
 +    for(col = 0; col < 8; col++)
 +    {
 +        for(row = 0; row < 8; row++)
 +        {
 +            poleCerveny[row][col]=0; ​
 +        }
 +    } 
 +//​re-inicializace ​   ​
 +    Inicializace();​
 +    pocitadlo = 0;
 +    rowAuto = 0;
 +    poloha =4;
 +    ​
 +//zrušení zmražení všech pohybů ​  
 +    tick.attach(&​SvodidlaPohyb,​ 1);
 +    tick2.attach(&​AutaPohyb,​ 0.25);
 +}
 +</​code>​
 +
 +====== Video ======
 +Aby nedošlo k jisté mistifikaci,​ chtěl bych podotknout, že hra ve videu začíná od restartu (červená plocha na počátku), z čehož je patrná následná reinicializace a opětovné spuštění hry.
 +
 +{{youtube>​gO0bwEQUUOA?​medium}}
 +
 +====== Závěr ======
 +Cílem tohoto projektu bylo zrealizovat hru z jednoho kdysi populárního herního zařízení pomocí RG LED 8x8 matice a vývojové desky FRDM KL25Z. ​ Zadání se podařilo splnit v plném požadovaném rozsahu. Byla využita barevnost matice. Ovládání bylo zrealizované pomocí akcelerometru.\\ ​
 +Hra je poměrně jednoduchá na ovládání a celkový chod programu byl vyladěn, aby nedošlo k nějakým zásadním chybám. Šlo by však uvažovat o následujících modifikacích. Hra je aktuálně jednoúrovňová,​ což znamená, že auta počítače se pohybují konstantní rychlostí. Bylo by však možné tuto rychlost měnit například pomocí slideru, který je zakomponován v desce KL25Z. Také by šlo nahradit psedonáhodnou binární sekvenci přímo generováním náhodných jedniček a nul pomocí funkce rand(). ​
  
2016/brick-game.1484317448.txt.gz · Poslední úprava: 2017/01/13 15:24 autor: Viktor Typovský