Individální projekty MPOA

Mikroprocesory s architekturou ARM

Uživatelské nástroje

Nástroje pro tento web


2014:teeter-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
2014:teeter-game [2015/01/19 00:58]
Roman Deneš
2014:teeter-game [2015/01/19 02:17] (aktuální)
Roman Deneš
Řádek 5: Řádek 5:
 Na vývojovém kitu [[http://​www.st.com/​web/​catalog/​tools/​FM116/​SC959/​SS1532/​PF259090|32F429IDISCOVERY]] realizujte androidovou hru teeter. Na základě údajů z gyroskopu se na displeji bude pohybovat kulička. Cílem hry je dopravit kuličku na požadované místo. Při pohybu je nutné se vyhnout případným překážkám (stěny, díry). Na vývojovém kitu [[http://​www.st.com/​web/​catalog/​tools/​FM116/​SC959/​SS1532/​PF259090|32F429IDISCOVERY]] realizujte androidovou hru teeter. Na základě údajů z gyroskopu se na displeji bude pohybovat kulička. Cílem hry je dopravit kuličku na požadované místo. Při pohybu je nutné se vyhnout případným překážkám (stěny, díry).
  
 +
 +  ​
 ==== Použitá zařízení ==== ==== Použitá zařízení ====
-Projekt je realizován na vývojovém kitu [[http://​www.st.com/​web/​catalog/​tools/​FM116/​SC959/​SS1532/​PF259090|32F429IDISCOVERY]],​ který obsahuje 2.4" ​displej ​ QVGA TFT s rozlišením 240x320. Dále byl použit akcelerometr [[http://​www.dipmicro.com/​store/​GY521-MOD|GY-521]].+Projekt je realizován na vývojovém kitu [[http://​www.st.com/​web/​catalog/​tools/​FM116/​SC959/​SS1532/​PF259090|32F429IDISCOVERY]],​ který obsahuje 2.4 palcový ​displej ​ QVGA TFT s rozlišením 240x320. Dále byl použit akcelerometr [[http://​www.dipmicro.com/​store/​GY521-MOD|GY-521]]. 
 + 
 +{{ :​2014:​teeter-game:​imag_teeter.jpg?​300 |Použitá zařízení}}
  
 +  ​
 Zapojení PINů: Zapojení PINů:
  
Řádek 43: Řádek 48:
 </​code>​ </​code>​
  
-Na jednotlivé pozice se pomocí funkce DrawLayout "​vykreslil"​ požadovaný layout v závislosti na aktuální úrovni. ​ Pod číslem 11 jsou uloženy stěny. Pod číslem 12 pak rozšířený prostor do kterého kulička nemůže vstoupit. Tento prostor odpovídá poloměru kuličky. Pod čísly 5 a 6 jsou jednotlivé díry. K nim odpovídají středu jsou uloženy pod čísly 4 a 7. Pro vykreslování děr (kruhů) je použita modifikovaná funkce z knihovny [[http://​stm32f4-discovery.com/​2014/​06/​library-18-ili9341-ltdc-stm32f429-discovery/​|tm_stm32f4_ili9341_ltdc]]. Místo vykreslování jednotlivých pixelů funkce provádí zápis do paměti.+Na jednotlivé pozice se pomocí funkce DrawLayout "​vykreslil"​ požadovaný layout v závislosti na aktuální úrovni. ​ Pod číslem 11 jsou uloženy stěny. Pod číslem 12 pak rozšířený prostor do kterého kulička nemůže vstoupit. Tento prostor odpovídá poloměru kuličky. Pod čísly 5 a 6 jsou jednotlivé díry. K nim odpovídají středy jsou uloženy pod čísly 4 a 7. Pro vykreslování děr (kruhů) je použita modifikovaná funkce z knihovny [[http://​stm32f4-discovery.com/​2014/​06/​library-18-ili9341-ltdc-stm32f429-discovery/​|tm_stm32f4_ili9341_ltdc]]. Místo vykreslování jednotlivých pixelů funkce provádí zápis do paměti.
  
 Na konci funkce je pak dvojitá smyčka, která na základě číselných údajů z matice vykresluje na displej jednotlivé barevné pixely. Na konci funkce je pak dvojitá smyčka, která na základě číselných údajů z matice vykresluje na displej jednotlivé barevné pixely.
Řádek 59: Řádek 64:
     }     }
 </​code>​ </​code>​
 +
 +V následující supersmyčce jsou opakovaně čteny data z připojeného akcelerometru,​ která jsou dále zpracována. Nejprve jsou váhována (60 % předchozí hodnoty + 40% z nově načtené hodnoty) a dále je od těchto hodnot vždy odečtena referenční hodnota, která se načte při zapnutí přistroje. Toto opatření je zejména kvůli nedokonalému připevnění sensoru, který nemusí být v naprosto stejné poloze jako deska.
 +
 <code cpp> <code cpp>
-// cteni dat z akceletometru 
         if (sensor1)         if (sensor1)
         TM_MPU6050_ReadAll(&​MPU6050_Data0);​         TM_MPU6050_ReadAll(&​MPU6050_Data0);​
- 
-    Xpos_old = Xpos; 
-    Ypos_old = Ypos; 
  
     // Nacteni vychozi pozice     // Nacteni vychozi pozice
     if(start == 1){     if(start == 1){
     X_axis_ref = MPU6050_Data0.Accelerometer_X;​     X_axis_ref = MPU6050_Data0.Accelerometer_X;​
-        Y_axis_ref = MPU6050_Data0.Accelerometer_Y;​ +                ​Y_axis_ref = MPU6050_Data0.Accelerometer_Y;​ 
-    ​  ​   start = 0;+    ​  ​           ​start = 0;
     }     }
  
Řádek 78: Řádek 82:
         Y_axis = (Q*Y_axis + (10-Q)*(MPU6050_Data0.Accelerometer_Y - Y_axis_ref))/​10;​         Y_axis = (Q*Y_axis + (10-Q)*(MPU6050_Data0.Accelerometer_Y - Y_axis_ref))/​10;​
  
-           </​code>​+</​code>​ 
 +            
 +Dále se uloží současná poloha a provede se změna na základě údajů z akcelerometru. Zde ukázka pouze pro jeden směr. Poslední podmínka ošetřuje okraj displeje.  
 + 
 +<​code>​ 
 +       ​ if(X_axis < -th1){ 
 +      Xpos++; 
 +       ​if(X_axis < -th2) 
 + ​ Xpos++;​ 
 +       ​if(X_axis < -th3) 
 +            Xpos++; 
 +        if(Xpos > 228) 
 +        Xpos = 228; 
 +      } 
 +                    
 +           // dalsi tri smery ... 
 +             
 +</​code> ​      
 + 
 +Za předpokladu,​ že nově získaná poloha není dostupná (zeď), provede se načtení staré polohy. Tato akce probíhá pro oba směry (x, y) jednotlivě. 
 + 
 +Nově získaná poloha se vykresluje pomocí funkce DrawBall. Nejprve se smaže stará kulička a následně se vykreslí na nových souřadnicích.  
 + 
 +<​code>​ 
 +void DrawBall(uint16_t Xpos, uint16_t Ypos, uint16_t Xpos_old, uint16_t Ypos_old) 
 +
 + 
 + 
 + TM_ILI9341_DrawFilledCircle(Xpos_old,​ Ypos_old, 10, ILI9341_COLOR_BLACK);​ 
 + TM_ILI9341_DrawFilledCircle(Xpos_old,​ Ypos_old, 10, ILI9341_COLOR_BLACK);​ 
 + 
 + TM_ILI9341_DrawFilledCircle(Xpos,​ Ypos, 10, ILI9341_COLOR_BLUE);​ 
 + TM_ILI9341_DrawFilledCircle(Xpos,​ Ypos, 10, ILI9341_COLOR_BLUE);​ 
 + 
 + Delayms(15);​ 
 +
 +</​code> ​        
 + 
 +Před každým vykreslením kuličky je ještě volána funkce ReDrawLayout,​ která překresluje (obnovuje) layout v okolí kuličky. Jde především o vykreslení děr, které mohou být částečně smazány procházející kuličkou. 
 + 
 +<​code>​  
 +void ReDrawLayout(uint16_t Xpos, uint16_t Ypos){ 
 + 
 +    ​static uint16_t i, j; 
 + 
 +       for(i = (Xpos-20); i < (Xpos+20); i++){ 
 +          for(j = (Ypos-20); j < (Ypos+20); j++){ 
 +           ​ if((MATRIX_GET_VALUE(i,​ j)) < 6) 
 +           ​ TM_ILI9341_DrawPixel(i,​ j, ILI9341_COLOR_GREEN);​ 
 + 
 +           ​ if((MATRIX_GET_VALUE(i,​ j)) == 6) 
 +           ​  ​  ​TM_ILI9341_DrawPixel(i,​ j, ILI9341_COLOR_YELLOW);​ 
 + 
 +          if((MATRIX_GET_VALUE(i,​ j)) == 11) 
 +              TM_ILI9341_DrawPixel(i,​ j, ILI9341_COLOR_YELLOW);​ 
 +          } 
 +       } 
 +
 +</​code>​  
 + 
 +V případě, že kulička spadne do díry (načtená souřadnice má hodnotu 5 nebo 6) je volána funkce DrawDrop, která provede animaci kuličky do díry a vykreslení (mezi)výsledků. 
 + 
 +<​code>​  
 +void DrawDrop(uint16_t Xpos, uint16_t Ypos, uint16_t Xpos_old, uint16_t Ypos_old, uint8_t level) 
 +
 + 
 + 
 + TM_ILI9341_DrawFilledCircle(Xpos_old,​ Ypos_old, 10, ILI9341_COLOR_BLACK);​ 
 + 
 + TM_ILI9341_DrawFilledCircle(Xpos,​ Ypos, 10, ILI9341_COLOR_BLUE);​ 
 + 
 + 
 + uint16_t i, j; 
 + uint16_t Xmid, Ymid; 
 + int16_t deltaX, deltaY; 
 + 
 +    for(i = (Xpos-22); i < (Xpos+22); i++){ 
 +     ​  ​ for(j = (Ypos-22); j < (Ypos+22); j++){ 
 +     ​  ​ if((MATRIX_GET_VALUE(i,​ j) == 4 )|(MATRIX_GET_VALUE(i,​ j) == 7 )){ 
 +     ​  ​ Xmid = i; 
 +     ​  ​ Ymid = j; 
 +     ​  ​ } 
 +       ​  ​ } 
 +    } 
 + 
 +    deltaX = (Xmid-Xpos);​ 
 +    deltaY = (Ymid-Ypos);​ 
 + 
 + 
 +    TM_ILI9341_DrawFilledCircle(Xpos,​ Ypos, 10, ILI9341_COLOR_BLUE);​ 
 +    Delayms(50);​ 
 +    TM_ILI9341_DrawFilledCircle(Xpos,​ Ypos, 10, ILI9341_COLOR_BLACK);​ 
 + 
 +    TM_ILI9341_DrawFilledCircle(Xpos+deltaX/​4,​ Ypos+deltaY/​4,​ 10, ILI9341_COLOR_BLUE);​ 
 +    Delayms(50);​ 
 +    TM_ILI9341_DrawFilledCircle(Xpos+deltaX/​4,​ Ypos+deltaY/​4,​ 10, ILI9341_COLOR_BLACK);​ 
 + 
 +    TM_ILI9341_DrawFilledCircle(Xpos+2*deltaX/​4,​ Ypos+2*deltaY/​4,​ 10, ILI9341_COLOR_BLUE);​ 
 +    Delayms(50);​ 
 +    TM_ILI9341_DrawFilledCircle(Xpos+2*deltaX/​4,​ Ypos+2*deltaY/​4,​ 10, ILI9341_COLOR_BLACK);​ 
 + 
 +    TM_ILI9341_DrawFilledCircle(Xpos+3*deltaX/​4,​ Ypos+3*deltaY/​4,​ 10, ILI9341_COLOR_BLUE);​ 
 +    Delayms(50);​ 
 +    TM_ILI9341_DrawFilledCircle(Xpos+3*deltaX/​4,​ Ypos+3*deltaY/​4,​ 10, ILI9341_COLOR_BLACK);​ 
 + 
 +    TM_ILI9341_DrawFilledCircle(Xmid,​ Ymid, 10, ILI9341_COLOR_BLUE);​ 
 +    Delayms(50);​ 
 + 
 + 
 +    // 
 + if((MATRIX_GET_VALUE(Xpos,​ Ypos)) == 5){ 
 + 
 +    TM_ILI9341_DrawFilledCircle(Xmid,​ Ymid, 12, ILI9341_COLOR_BLUE2);​ 
 +    TM_ILI9341_DrawFilledCircle(Xmid,​ Ymid, 10, ILI9341_COLOR_BLUE);​ 
 + 
 + 
 + Delayms(1250);​ 
 + 
 + 
 +    TM_ILI9341_Fill(ILI9341_COLOR_RED);​ 
 +    Delayms(250);​ 
 +    TM_ILI9341_Fill(ILI9341_COLOR_BLACK);​ 
 +    Delayms(250);​ 
 +    TM_ILI9341_Fill(ILI9341_COLOR_RED);​ 
 +    Delayms(250);​ 
 +    TM_ILI9341_Fill(ILI9341_COLOR_BLACK);​ 
 +    Delayms(250);​ 
 +    TM_ILI9341_Fill(ILI9341_COLOR_RED);​ 
 +     ​ Delayms(250);​ 
 +        TM_ILI9341_Fill(ILI9341_COLOR_BLACK);​ 
 +        Delayms(250);​ 
 +        TM_ILI9341_Fill(ILI9341_COLOR_RED);​ 
 + 
 + TM_ILI9341_Puts(50,​ 100, "Game Over", &​TM_Font_16x26,​ 0x0000, ILI9341_COLOR_RED);​ 
 + 
 + while(1){} 
 + 
 +
 +             // Obdobne i pro MATRIX_GET_VALUE(Xpos,​ Ypos)) == 6 -> dalsi kolo. 
 + 
 +
 + 
 + 
 +</​code>​  
 + 
 +==== Závěr ==== 
 + 
 +V projektu byl místo interního gyroskopu využit externí akcelerometr,​ jelikož se na danou aplikace hodí lépe. Zadání bylo splněno, hra je plně funkční. Při popisu byly vynechány některé zřejmé části kódu, které jsou jasné už z jejich popisu. Dále pak některé definice proměnných a další méně podstatné funkce. 
 + 
 +Hra obsahuje dvě úrovně a je nastíněn systém pro přechod mezi jednotlivými úrovněmi. Případné rozšíření o další úrovně je tedy poměrně snadná záležitost.  
 + 
 +Video je k dispozici na adrese https://​www.youtube.com/​watch?​v=NFYOeizr5jU&​feature=youtu.be. Výsledný soubor je uložen v souborovém systému. 
2014/teeter-game.1421625480.txt.gz · Poslední úprava: 2015/01/19 00:58 autor: Roman Deneš