bebertii

Tetris sur arduino

Aug 23rd, 2020
1,155
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <SPI.h>
  2. #include "Ucglib.h"
  3.  
  4. /*
  5.     Hardware SPI Pins:
  6.     Arduino Uno  sclk=13, data=11
  7.     Arduino Due sclk=76, data=75
  8.     Arduino Mega    sclk=52, data=51
  9.    
  10. */
  11. /*
  12.  
  13. */
  14. Ucglib_ST7735_18x128x160_HWSPI ucg(/*cd=*/ 9, /*cs=*/ 10, /*reset=*/ 8);
  15. //Ucglib_ST7735_18x128x160_SWSPI ucg(/*sclk=*/ 13, /*data=*/ 11, /*cd=*/ 9, /*cs=*/ 10, /*reset=*/ 8);
  16.  
  17.  
  18. byte taille_brique=8; //unité de taille des éléments
  19.  
  20. bool briques[16*7]={ 0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0, //Barre
  21.         0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0, //carré
  22.         0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0, //2
  23.         0,0,0,0,0,0,1,1,0,1,1,0,0,0,0,0, //5
  24.         0,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0, //L
  25.         0,0,1,0,0,0,1,0,0,1,1,0,0,0,0,0, //-L
  26.         0,0,0,0,0,0,1,0,0,1,1,1,0,0,0,0 //T
  27.         };
  28. //valeur du score :
  29. //pas de ligne +2
  30. //1 ligne +10
  31. //2 lignes +20
  32. //3 lignes +50
  33. //4 lignes +100    
  34. byte bonus[]={2,10,20,50,100};
  35. // nombre de points a atteindre pour franchir un niveau
  36. //              9    8     7   6    5    4   3   2  1  
  37. int niveaux[]={3600,2800,2100,1500,1000,600,300,100,0};//finish à 5000
  38.  
  39. byte grille_reelle[10*20]; //c'est la grille telle qu'affichée à l'écran
  40. int score=0;
  41. byte piece_actuelle[16]; //tableau dans lequel est stocké la pièce en cours
  42.  
  43. byte etat=0; //code les différentes étapes du jeu 0:accueil, 1:jeu, 2:game_over
  44. short position_piece[2]={0,0}; //la position de la pièce sur la grille. -2<=x<=12 et -4<=y<=18, selon la forme de la pièce
  45. byte num_prochaine=10; //un numéro supérieur à 8 indique que la pièce n'a pas été définie
  46. byte num_actuelle=10;
  47. short gauche=A2;
  48. short droite=A1;
  49. short bas=A3;
  50. short tourne=A4;
  51.  
  52.  
  53. byte couleurs[3*7]={ 200,0,0,       //rouge
  54.         0,200,0,        //vert
  55.         0,0,200,        //bleu
  56.         150,150,0,      //jaune
  57.         100,100,100,    //gris
  58.         150,0,200,      //violet
  59.         200,100,0   //orange
  60.         };
  61.  
  62.  
  63. void setup(void)
  64. {
  65.     delay(1000);
  66.     ucg.begin(UCG_FONT_MODE_TRANSPARENT);
  67.     ucg.setRotate180();
  68.     background();
  69.     raz();
  70.     choix_piece();
  71.     pinMode(A0,INPUT);
  72.     randomSeed(analogRead(0));
  73.     pinMode(gauche,INPUT_PULLUP);
  74.     pinMode(droite,INPUT_PULLUP);
  75.     pinMode(bas,INPUT_PULLUP);
  76.     pinMode(tourne,INPUT_PULLUP);
  77.  
  78.     Serial.begin(9600);
  79. }
  80.  
  81. void loop(void)
  82. {
  83.     switch (etat){
  84.         case 0:
  85.           background();
  86.           accueil();
  87.           while(digitalRead(tourne)){delay(200);} // on reste sur l'écran d'accueil tant qu'on n'appuie pas de nouveau sur tourne
  88.           etat=1;
  89.           break;
  90.         case 1:
  91.           game();
  92.           break;
  93.         case 2:
  94.           game_over();
  95.           while(digitalRead(tourne)){delay(200);} // on reste sur l'écran game over tant qu'on n'appuie pas de nouveau sur tourne
  96.           etat=0;
  97.           break;
  98.     }
  99.    
  100. }
  101.  
  102. void game(){
  103.     bool perdu=false;
  104.  
  105.  
  106.  
  107.  
  108.     while(!perdu){
  109.         //mise à jour du score et du level
  110.     byte niveau=0;
  111.     while(score<niveaux[niveau]){
  112.       niveau++;
  113.       }
  114.     niveau=9-niveau;
  115.         ucg.setColor(150,200,200);
  116.         ucg.drawBox(11*taille_brique,4*taille_brique,4*taille_brique,2*taille_brique);
  117.         ucg.drawBox(11*taille_brique,9*taille_brique,4*taille_brique,2*taille_brique);
  118.         ucg.setFontPosTop();
  119.         ucg.setFont(ucg_font_helvB08_hr);
  120.         ucg.setFontMode(UCG_FONT_MODE_TRANSPARENT);
  121.         ucg.setColor(80, 80, 80);           // black color for the text
  122.         ucg.setPrintPos(11*taille_brique+2,4*taille_brique+2);
  123.         ucg.print(score);
  124.         ucg.setPrintPos(11*taille_brique+2,9*taille_brique+2);
  125.         ucg.print(niveau);
  126.         //on redessine la grille
  127.         redessine_grille();
  128.         bool passe=true;
  129.         choix_piece();
  130.         position_piece[0]=0;
  131.         position_piece[1]=-4;
  132.         while(passe){
  133.             for(byte i=0;i<5;i++){
  134.                 short move_x=0;
  135.                 short move_y=0;
  136.                 //On regarde si un bouton est pressé
  137.                 if(!digitalRead(gauche)) {
  138.                   move_x=-1;
  139.                   //Serial.println(move_x);
  140.                 }
  141.                 else if(!digitalRead(droite)) {
  142.                   move_x=1;
  143.                   //Serial.println(move_x);
  144.                 }
  145.                 else if(!digitalRead(tourne)) {
  146.                 eff_piece_jeu(position_piece[0],position_piece[1]);
  147.                 rotation();
  148.                 dessine_piece_jeu(position_piece[0],position_piece[1]);
  149.                 //Serial.println("rotation");
  150.                 }
  151.                 else if(!digitalRead(bas)) {
  152.                 move_y=1;
  153.                 //Serial.println(move_y);
  154.                 }
  155.                 if((move_x!=0 || move_y!=0) && translation(move_x,move_y)){
  156.                 eff_piece_jeu(position_piece[0],position_piece[1]);
  157.                 position_piece[0]+=move_x;
  158.                 position_piece[1]+=move_y;
  159.                 dessine_piece_jeu(position_piece[0],position_piece[1]);
  160.                
  161.                 }
  162.                 delay(100-10*niveau);
  163.        
  164.             }
  165.           //si la pièce peut avancer alors elle avance
  166.             if(translation(0,1)){
  167.                
  168.                 eff_piece_jeu(position_piece[0],position_piece[1]);
  169.                 position_piece[1]++;
  170.                 dessine_piece_jeu(position_piece[0],position_piece[1]);
  171.             }
  172.      
  173.             //si elle ne peut pas avancer mais qu'elle n'est pas à sa position intiale
  174.             else if(position_piece[1]>0) {
  175.        
  176.                 //on commence par coller la pièce dans la grille
  177.                 for(byte i=0;i<16;i++){
  178.                     if(piece_actuelle[i]){grille_reelle[position_piece[0]+i%4+10*(position_piece[1]+i/4)]=num_actuelle;}
  179.                 }
  180.                
  181.        
  182.                 //on regarde ensuite si la ligne est complète
  183.                 byte nb_lignes=0; //Nombre de lignes faites
  184.                
  185.                 for(byte i=0;i<20;i++){
  186.                     bool ligne_complete=true;
  187.                     for(byte j=0;j<10;j++){
  188.             //Une case vide a une valeur de 10, donc si on trouve
  189.             //la valeur 10 dans la ligne, on sait qu'elle n'est
  190.             //pas remplie
  191.                         if(grille_reelle[10*i+j]==10) ligne_complete=false;                    
  192.                     }
  193.                     if (ligne_complete){ //si la ligne est complète
  194.                         // on incrémente nb_lignes
  195.                         nb_lignes++;
  196.                         // on déplace les lignes au-dessus que l'on colle
  197.            
  198.                         for (byte k=0;k<10*(i+1);k++){
  199.              
  200.               //on vide la ligne du haut
  201.                             if(10*i+9-k<10) {grille_reelle[10*i+9-k]=10;}
  202.                           //on remplace la valeur des lignes par celles de
  203.               //la ligne au-dessus
  204.                             else {grille_reelle[10*i+9-k]=grille_reelle[10*i+9-k-10];}
  205.                         }
  206.            
  207.                        
  208.                     }
  209.                    
  210.                 }
  211.                 // le score s'incrémente de 3^(nb_lignes+1)
  212.                 score += bonus[nb_lignes];
  213.                 passe=false;
  214.             }
  215.            
  216.             else perdu=true;
  217.            
  218.         }
  219.     }
  220.     etat=2;// c'est le game over
  221. }
  222.  
  223. //assigne comme pièce actuelle la pièce précédémment annoncée
  224. //définit la "nouvelle" future pièce
  225. //et se relance si la pièce actuelle n'est pas encore définie (ie : au départ)
  226. void choix_piece(){
  227.     num_actuelle=num_prochaine;
  228.     for(byte i=0;i<16;i++){
  229.         piece_actuelle[i]=briques[16*num_actuelle+i];
  230.     }
  231.     num_prochaine=random(7);
  232.     dessine_piece_prochaine(11,15);
  233.    
  234.     if(num_actuelle>8)choix_piece();
  235. }
  236.  
  237. //va tester la possibilité de faire tourner la pièce
  238. //càd vérifier qu'il n'y a pas de collision avec le bord ou une pièce déjà placée
  239. void rotation(){
  240. byte piece_test[16]; //tableau temporaire servant à vérifier qu'on peut faire tourner la pièce
  241.     for(byte i=0;i<16;i++){
  242.         piece_test[4*(i/4)+i%4]=piece_actuelle[(i%4)*4+3-i/4]; //On colle la pièce actuelle en tournant de 90° dans la pièce test
  243.     }
  244.     //on vérifie maintenant qu'il n'y a pas de problème avec la pièce test
  245.     //càd qu'aucune partie ne se superpose à une pièce déjà présente sur la grille
  246.     //et qu'aucune partie ne se retrouve à l'extérieur de la grille mise à part
  247.     //l'extrêmité supérieure
  248.     bool collision=0;
  249.     for(byte i=0;i<16;i++){
  250.         //on vérifie d'abord qu'une partie de la pièce n'est pas à l'extérieur de la grille
  251.         if((position_piece[0]+i%4<0 ||position_piece[0]+i%4>9||position_piece[1]+i/4>19) && piece_test[i]!=0) collision=true;
  252.         //on vérifie ensuite qu'avec la rotation, une partie de la pièce n'entre pas en collision avec une pièce présente sur la grille
  253.         else if ((grille_reelle[10*(position_piece[1]+4*i/4)+position_piece[0]+i%4]!=10)&& piece_test[i]!=0) collision=true;
  254.     }
  255.     if(true){   //s'il n'y a pas de problème alors la rotation est validée en envoyant le résultat de la rotation
  256.             // dans la pièce actuelle.
  257.         for(int i=0;i<16;i++){
  258.             piece_actuelle[i]=piece_test[i];
  259.         }
  260.     }
  261.    
  262. }
  263. //va tester la possibilité de déplacer la pièce
  264. //retourne "true" si cela est possible, "false" dans le cas contraire
  265. bool translation(short delta_x,short delta_y){
  266.     bool collision=0;
  267.     for(byte i=0;i<16;i++){
  268.         //on vérifie d'abord qu'une partie de la pièce n'est pas à l'extérieur de la grille
  269.         if((position_piece[0]+i%4+delta_x<0 ||position_piece[0]+i%4+delta_x>9||position_piece[1]+i/4+delta_y>19) && piece_actuelle[i]!=0) collision=true;
  270.         //on vérifie ensuite qu'avec le déplacement, une partie de la pièce n'entre pas en collision avec une pièce présente sur la grille
  271.         else if ((grille_reelle[10*(position_piece[1]+i/4+delta_y)+position_piece[0]+i%4+delta_x]!=10)&& piece_actuelle[i]!=0 && (position_piece[1]+i/4+delta_y)>0) collision=true;
  272.     }
  273.     if(!collision){return true;}
  274.     else return false;
  275. }
  276.  
  277.  
  278. void redessine_grille(){//redessine la grille en fonction des valeurs de ses cases
  279.     for (byte i=0;i<200;i++){
  280.         if(grille_reelle[i]!=10){
  281.             ucg.setColor(couleurs[3*grille_reelle[i]],couleurs[3*grille_reelle[i]+1],couleurs[3*grille_reelle[i]+2]);
  282.            
  283.         }
  284.         else ucg.setColor(200,255,255);
  285.         ucg.drawBox(8*(i%10),8*(i/10),8,8);
  286.     }
  287.    
  288.     }
  289.  
  290. void raz(){
  291.    
  292.     position_piece[0]=0;
  293.     position_piece[1]=-4;
  294.     for(byte i=0;i<200;i++){
  295.         grille_reelle[i]=10; //une case vaut 10 si elle est vide et entre 0 et 7 si elle est pleine, ce nombre définit sa couleur
  296.  
  297.     }
  298.     for(byte i=0;i<16;i++){
  299.         piece_actuelle[i]=0;
  300.        
  301.     }
  302.     num_prochaine=10;
  303.     num_actuelle=10;
  304.     score=0;
  305. }
  306.  
  307. void dessine_piece_prochaine(short posx, short posy){
  308.     for(byte i=0;i<16;i++){
  309.        
  310.         if(briques[16*num_prochaine+i]){
  311.             ucg.setColor(couleurs[3*num_prochaine],couleurs[3*num_prochaine+1],couleurs[3*num_prochaine+2]);
  312.             ucg.drawBox(8*(posx+(i%4)),8*(posy+(i/4)),8,8);
  313.    
  314.         }
  315.         else{
  316.             ucg.setColor(150,200,200);
  317.             ucg.drawBox(8*(posx+(i%4)),8*(posy+(i/4)),8,8);
  318.         }
  319.      
  320.     }
  321. }
  322.  
  323. void dessine_piece_jeu(short posx, short posy){ //dessine une pièce dans la grille de jeu
  324.     for(byte i=0;i<16;i++){
  325.         if(piece_actuelle[i]){
  326.             ucg.setColor(couleurs[3*num_actuelle],couleurs[3*num_actuelle+1],couleurs[3*num_actuelle+2]);
  327.             ucg.drawBox(8*(posx+(i%4)),8*(posy+(i/4)),8,8);
  328.             }      
  329.     }
  330. }
  331.  
  332. void eff_piece_jeu(short posx, short posy){
  333.    
  334.     for(byte i=0;i<16;i++){
  335.      
  336.         if(piece_actuelle[i]){
  337.             ucg.setColor(200,255,255);
  338.             ucg.drawBox(8*(posx+(i%4)),8*(posy+(i/4)),8,8);
  339.         }
  340.     }
  341. }
  342.  
  343. void dessine_brique(short posx, short posy){ //dessine une brique du décors
  344.     byte brique[] = {80,80,80,80,80,200,188,80,80,188,128,80,80,80,80,80};
  345.     for(byte i=0;i<16;i++){
  346.         ucg.setColor(brique[i],brique[i],brique[i]);
  347.         ucg.drawBox(posx+2*(i%4),posy+2*(i/4),2,2);
  348.     }
  349.    
  350. }
  351.  
  352. void background(){
  353.     //zone de jeu
  354.     ucg.setColor(200,255,255);
  355.     ucg.drawBox(0,0,10*taille_brique,20*taille_brique);
  356.     //les briques
  357.     for(byte j=0;j<6;j++){
  358.         for(byte i=0;i<20;i++){
  359.             dessine_brique(80+taille_brique*j,taille_brique*i);
  360.         }
  361.     }
  362.     //les fenêtres d'affichage
  363.     ucg.setColor(150,200,200);
  364.     ucg.drawBox(11*taille_brique,2*taille_brique,4*taille_brique,4*taille_brique);
  365.     ucg.drawBox(11*taille_brique,7*taille_brique,4*taille_brique,4*taille_brique);
  366.     ucg.drawBox(11*taille_brique,12*taille_brique,4*taille_brique,2*taille_brique);
  367.     ucg.drawBox(11*taille_brique,15*taille_brique,4*taille_brique,4*taille_brique);
  368.     //le texte dans les fenêtres
  369.     ucg.setFontPosTop();
  370.     ucg.setFont(ucg_font_helvB08_hr);
  371.     ucg.setFontMode(UCG_FONT_MODE_TRANSPARENT);
  372.     ucg.setColor(80, 80, 80);           // black color for the text
  373.     ucg.setPrintPos(11*taille_brique+2,2*taille_brique+2);
  374.     ucg.print("Score");
  375.     ucg.setPrintPos(11*taille_brique+2,7*taille_brique+2);
  376.     ucg.print("Level");
  377.     ucg.setPrintPos(11*taille_brique+2,12*taille_brique+2);
  378.     ucg.print("NEXT");
  379.  }
  380.  
  381. void game_over(){
  382.     //zone de jeu
  383.     ucg.setColor(200,255,255);
  384.     ucg.drawBox(0,0,10*taille_brique,20*taille_brique);
  385.     //le texte dans les fenêtres
  386.     ucg.setFontPosTop();
  387.     ucg.setFont(ucg_font_helvB08_hr);
  388.     ucg.setFontMode(UCG_FONT_MODE_TRANSPARENT);
  389.     ucg.setColor(80, 80, 80);           // black color for the text
  390.     ucg.setPrintPos(3*taille_brique+2,7*taille_brique+2);
  391.     ucg.print("Game");
  392.     ucg.setPrintPos(3*taille_brique+2,8*taille_brique+2);
  393.     ucg.print("Over");
  394.     }
  395.    
  396. void accueil(){
  397.     //zone de jeu
  398.     ucg.setColor(200,255,255);
  399.     ucg.drawBox(0,0,10*taille_brique,20*taille_brique);
  400.     //le texte dans les fenêtres
  401.     ucg.setFontPosTop();
  402.     ucg.setFont(ucg_font_helvB08_hr);
  403.     ucg.setFontMode(UCG_FONT_MODE_TRANSPARENT);
  404.     ucg.setColor(80, 80, 80);           // black color for the text
  405.     ucg.setPrintPos(3*taille_brique+2,7*taille_brique+2);
  406.     ucg.print("Push");
  407.     ucg.setPrintPos(3*taille_brique+2,8*taille_brique+2);
  408.     ucg.print("Start");
  409.     }
RAW Paste Data