// // ######################### // # JEU DE LA COURSE A 20 # // ######################### // # Guy Magli 16.10.2019 # // # 24.01.2020 # // ######################### // # Conception, cablages # // # mises a jour, # // # contact... # // # www.magli.fr # // ######################### // // ! ======================== ! // ! LIBRAIRIES ET PARAMETRES ! // ! ======================== ! // // Afin d'eviter les problemes d'affichage et d'impression les signes diacritiques // ont ete retires des commentaires et des chaines de caracteres. // #include // Pour la communication avec un peripherique. #include // Pour l'ecran graphique. #include // Id. #include // Pour la gestion des chaines de caracteres. #include // Clavier. #include // Anneau de leds. #ifdef __AVR__ #include // Required for 16 MHz Adafruit Trinket #endif // // ! ================================================= ! // ! VARIABLES GLOBALES, CONSTANTES ET INITIALISATIONS ! // ! ================================================= ! // Pour les boutons // bool bBoutonAppuyeGauche = false; bool bBoutonAppuyeDroite = false; bool bUnBoutonEstPresse = false; int iCompteurDeClicks = 0; int iBoutonGauche = 25; int iBoutonDroite = 23; #define TEMPS_ANTI_REBOND_MS 30 // // // : -------------- : // : Anneau de Leds : // : -------------- : // #define LED_PIN 53 #define LED_COUNT 24 // Declare our NeoPixel strip object: Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); // // : ------ : // : Divers : // : ------ : // int t; // Pour les boucles diverses. // // : ------------ : // : Pour l'ecran : // : ------------ : // #define LCD_CS A3 #define LCD_CD A2 #define LCD_WR A1 #define LCD_RD A0 #define LCD_RESET A4 #define BLACK 0x0000 #define BLUE 0x001F #define RED 0xF800 #define GREEN 0x07E0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define YELLOW 0xFFE0 #define WHITE 0xFFFF Elegoo_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET); int iPosition = 0; // Pour la position en largeur de l'ecran (en pixels). int iLargeurCaractereTaille4 = 24; // Largeur en pixels d'un caractere en taille 4. // // : -------------------------- : // : Pour le jeu proprement dit : // : -------------------------- : // int iNombreTotalDeBougies = 20; // Nombre total de bougies (course a 20). int iNombreDeBougiesDejaAllumees = 0; // Bougies deja allumees par les deux joueurs. int iNombreDeBougiesAAllumer = 0; // Bougies a allumer pour ce coup de jeu. int iNombreDeBougiesQuOnPeutAllumer = 2; // Bougies qu'on peut allumer a chaque tour. int iNombreDePositionsGagnantes = 0; // Combien y a-t-il de positions gagnantes. int iPositionsGagnantes[20]; // Quelles sont toutes les positions gagnantes ? int iEnCours = 0; // Position qu'on est en train d'examiner ou de jouer. String cCommence = ""; // Doit contenir 'B' pour le boitier ou 'J' pour le joueur. Toutes autres valeurs sont exclues. int iCommence = 0; // Doit contenir 1 pour le JOUeur et 2 pour le BOItier. bool bJeuFini = false; // A-t-on allume la derniere bougie ? int iDelai = 3000; // Temps d'attente. char cChar; // Caractere tape au clavier. // // ! ===== ! // ! Setup ! // ! ===== ! // void setup() { Serial.begin(9600); Serial.println("JEU DE LA COURSE A 20"); Serial.println(" "); #if defined(__AVR_ATtiny85__) && (F_CPU == 16000000) clock_prescale_set(clock_div_1); #endif // Serial.println("Initialisations : "); Serial.println("- Anneau de leds"); strip.begin(); // Initialise l'anneau de leds. strip.show(); // Eteint toutes les leds. strip.setBrightness(1); // Regle la luminosite des leds (max : 255). // // Initialisation des nombres aleatoires. // Serial.println("- Nombres aleatoires"); Serial.println(" "); randomSeed(analogRead(0)); // initialise le generateur de nombre aleatoire en lisant une broche analogique. // // : --------------- : // : Initialisations : // : --------------- : // // Ecran TFT // tft.reset(); uint16_t identifier = tft.readID(); identifier = 0x9341; tft.begin(identifier); // // Anneau de leds // for (t = 0; t < 24; t++) { strip.setPixelColor(t, strip.Color(0, 150, 0)); delay(200); } // // Les boutons // pinMode(iBoutonGauche, INPUT_PULLUP); pinMode(iBoutonDroite, INPUT_PULLUP); } // // ! ==== ! // ! Loop ! // ! ==== ! // void loop() { // // Tant que l'arduino est branchee, on joue, il n'y a pas de sortie possible, c'est une machine dediee apres tout ! // // : --------- : // : Generique : // : --------- : // Serial.println("Affichage du generique sur l'ecran TFT"); Serial.println(" "); tft.fillScreen(BLACK); tft.setRotation(2); tft.setCursor(0, 40); tft.setTextSize(4); tft.setTextColor(WHITE); tft.print("A "); tft.setTextColor(RED); tft.print("EVIAN"); tft.setTextColor(WHITE); tft.print(" EN"); tft.setCursor(00, 90); tft.setTextColor(WHITE); tft.setTextColor(YELLOW); tft.print(" 2020"); tft.setTextColor(WHITE); tft.setCursor(00, 140); tft.print("ON JOUE A"); tft.setCursor(00, 190); tft.print("LA COURSE"); tft.setCursor(00, 240); tft.print(" A "); tft.setTextColor(YELLOW); tft.print("20"); tft.println(" "); Serial.println("Anneau de leds rouge/blanc/jaune"); Serial.println(" "); for (t = 0; t < 8; t++) { colorWipe(strip.Color(255, 0, 0), 50); // Rouge colorWipe(strip.Color(255, 255, 255), 50); // Blanc colorWipe(strip.Color(255, 255, 0), 50); // Jaune } colorWipe(strip.Color(0, 0, 0), 50); // Noir // // : ------------------------------ : // : On demande qui commence le jeu : // : ------------------------------ : // tft.fillScreen(BLACK); tft.setRotation(2); tft.setCursor(0, 40); tft.setTextSize(3); tft.setTextColor(WHITE); tft.println(" QUI "); tft.setCursor(0, 80); tft.println(" COMMENCE ?"); tft.setTextColor(GREEN); tft.setCursor(0, 300); tft.print("VOUS "); tft.setTextColor(BLUE); tft.print("BOITIER"); // On teste si le bouton de gauche est presse bUnBoutonEstPresse = false; bBoutonAppuyeGauche = false; bBoutonAppuyeDroite = false; while (bUnBoutonEstPresse == false) { if (digitalRead(iBoutonGauche) == false) // Le bouton de gauche { bBoutonAppuyeGauche = true; bUnBoutonEstPresse = true; } if (bUnBoutonEstPresse == false) { if (digitalRead(iBoutonDroite) == false) // Le bouton de droite { bBoutonAppuyeDroite = true; bUnBoutonEstPresse = true; } } } if (bBoutonAppuyeGauche == true) { cCommence = "J"; // C'est le joueur qui commence (vert). iCommence = 1; tft.fillScreen(BLACK); tft.setRotation(2); tft.setCursor(0, 40); tft.setTextSize(3); tft.setTextColor(GREEN); tft.println(" VOUS"); tft.setCursor(0, 80); tft.println(" COMMENCEZ"); tft.println(" "); tft.setCursor(0, 120); tft.println(" VOS BOUGIES"); tft.setCursor(0, 160); tft.println("SERONT VERTES"); Serial.println("Le joueur commence. Ses bougies seront vertes."); Serial.println(" "); for (t = 0; t < 10; t++) { colorWipe(strip.Color(0, 255, 0), 50); // Vert. colorWipe(strip.Color(0, 0, 0), 50); // Noir. } } if (bBoutonAppuyeDroite == true) { cCommence = "B"; // C'est le boitier qui commence (bleu). iCommence = 2; tft.fillScreen(BLACK); tft.setRotation(2); tft.setCursor(0, 40); tft.setTextSize(3); tft.setTextColor(BLUE); tft.println(" LE BOITIER"); tft.setCursor(0, 80); tft.println(" COMMENCE"); tft.println(" "); tft.setCursor(0, 120); tft.println(" SES BOUGIES"); tft.setCursor(0, 160); tft.println("SERONT BLEUES"); Serial.println("Le boitier commence. Ses bougies seront bleues."); Serial.println(" "); for (t = 0; t < 5; t++) { colorWipe(strip.Color(0, 0, 255), 50); // Bleu. colorWipe(strip.Color(0, 0, 0), 50); // Noir. } } DebuterLeJeu(); // if (cCommence == "B") { FaireJouerLeBoitier(); } // C'est le boitier qui commence. bJeuFini = false; while (bJeuFini == false) { if (bJeuFini == false) { FaireJouerLeJoueur(); } if (bJeuFini == false) { FaireJouerLeBoitier(); } } } // // ! ========== ! // ! Procedures ! // ! ========== ! // // Un tour complet d'une couleur unie. // void colorWipe(uint32_t color, int wait) { for (int i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, color); strip.show(); delay(10); } } // // : -------------- : // : Debuter le jeu : // : -------------- : // void DebuterLeJeu() { // // On cherche les positions gagnantes. // // On efface les positions gagnantes memorisees precedemment. // iNombreDePositionsGagnantes = 0; for (t = 0; t < iNombreDePositionsGagnantes; t++) // On efface les anciennes positions gagnantes. { iPositionsGagnantes[t] = 0; } // // La derniere bougie est egalement une position gagnante, il convient de ne pas l'oublier ! // iNombreDePositionsGagnantes++; iPositionsGagnantes[iNombreDePositionsGagnantes] = iNombreTotalDeBougies; // // On memorise les positions gagnantes. // iEnCours = iNombreTotalDeBougies; // On examinera toutes les positions gagnantes en commencant par la fin. while (iEnCours >= (iNombreDeBougiesQuOnPeutAllumer + 1)) { iNombreDePositionsGagnantes++; iPositionsGagnantes[iNombreDePositionsGagnantes] = (iEnCours - 1 - iNombreDeBougiesQuOnPeutAllumer); iEnCours = iPositionsGagnantes[iNombreDePositionsGagnantes]; } // // On demarre et on initialise. // iNombreDeBougiesDejaAllumees = 0; // // On allume en blanc les quatre leds "inutiles". // strip.setPixelColor(21, strip.Color(255, 255, 255)); // Blanc. strip.setPixelColor(22, strip.Color(255, 255, 255)); // Blanc. strip.setPixelColor(23, strip.Color(255, 255, 255)); // Blanc. strip.setPixelColor(24, strip.Color(255, 255, 255)); // Blanc. strip.show(); } // // : ---------------------- : // : Faire jouer le boitier : // : -----------------------: // void FaireJouerLeBoitier() { // // On cherche la prochaine position gagnante. // for (t = 1; t <= iNombreDePositionsGagnantes; t++) { // // Il faut que la position gagnante soit superieure au nombre de bougies deja allumees. // if (iPositionsGagnantes[t] > iNombreDeBougiesDejaAllumees) { // // Il ne faut pas allumer plus de bougies que ce qui est autorise. // if ((iPositionsGagnantes[t] - iNombreDeBougiesDejaAllumees) <= iNombreDeBougiesQuOnPeutAllumer) { iNombreDeBougiesAAllumer = iPositionsGagnantes[t] - iNombreDeBougiesDejaAllumees; } } } // // Si les positions gagnantes sont trop loin, on joue un nombre au hasard, dans les limites autorisees. // if ((iNombreDeBougiesAAllumer == 0) || (iNombreDeBougiesAAllumer > iNombreDeBougiesQuOnPeutAllumer)) { iNombreDeBougiesAAllumer = random(1, iNombreDeBougiesQuOnPeutAllumer + 1); } // // On allume physiquement les bougies. // AllumeLesBougies(iNombreDeBougiesAAllumer, 2); // // On redige le message sur l'ecran. // tft.fillScreen(BLACK); tft.setRotation(2); tft.setCursor(0, 20); tft.setTextColor(YELLOW); tft.print(" "); tft.setTextSize(5); tft.setTextColor(YELLOW); tft.setCursor(90, 20); tft.setTextSize(5); if (iNombreDeBougiesDejaAllumees < 10) { tft.print("0"); } tft.print(iNombreDeBougiesDejaAllumees); tft.setCursor(0, 80); tft.setTextSize(3); tft.setTextColor(BLUE); tft.println(" LE BOITIER "); tft.println(" ALLUME "); tft.print(" "); tft.print(iNombreDeBougiesAAllumer); if (iNombreDeBougiesAAllumer == 1) { tft.println(" BOUGIE."); } else { tft.println(" BOUGIES."); } iNombreDeBougiesDejaAllumees = iNombreDeBougiesDejaAllumees + iNombreDeBougiesAAllumer; tft.setCursor(90, 260); tft.setTextColor(RED); tft.setTextSize(5); if (iNombreDeBougiesDejaAllumees < 10) { tft.print("0"); } tft.print(iNombreDeBougiesDejaAllumees); tft.setTextColor(WHITE); delay(iDelai); // // C'est peut-etre la fin du jeu. // if (iNombreDeBougiesDejaAllumees >= iNombreTotalDeBougies) { tft.fillScreen(BLACK); tft.setRotation(2); tft.setTextSize(3); tft.setCursor(0, 20); tft.setTextColor(BLUE); tft.println(" "); tft.println("-------------"); tft.println(" VOUS AVEZ "); tft.println(" PERDU! "); tft.println(" "); tft.println(" HELAS! "); tft.println("-------------"); for (t = 0; t < 5; t++) { colorWipe(strip.Color(0, 0, 255), 50); // Bleu. colorWipe(strip.Color(0, 0, 0), 50); // Noir. } delay(iDelai * 2); bJeuFini = true; iNombreDeBougiesDejaAllumees = 0; } } // // : ---------------------- : // : Faire jouer le joueur : // : ---------------------- : // void FaireJouerLeJoueur() { // // On demande combien de bougies le joueur allume. // // Sur l'ecran. // tft.fillScreen(BLACK); tft.setRotation(2); tft.setTextColor(YELLOW); tft.setCursor(90, 20); tft.setTextSize(5); if (iNombreDeBougiesDejaAllumees < 10) { tft.print("0"); } tft.print(iNombreDeBougiesDejaAllumees); tft.setTextSize(3); tft.setTextColor(GREEN); tft.setCursor(0, 80); tft.println(" COMBIEN DE "); tft.println(" BOUGIES "); tft.println("ALLUMEZ-VOUS?"); tft.setTextColor(WHITE); tft.setCursor(0, 240); tft.print("-------------"); tft.setCursor(0, 270); tft.print("1 2"); tft.setCursor(0, 300); tft.print("-------------"); // On teste si le bouton de gauche est presse bUnBoutonEstPresse = false; bBoutonAppuyeGauche = false; bBoutonAppuyeDroite = false; while (bUnBoutonEstPresse == false) { if (digitalRead(iBoutonGauche) == false) // Le bouton de gauche { bBoutonAppuyeGauche = true; bUnBoutonEstPresse = true; iNombreDeBougiesAAllumer = 1; } if (bUnBoutonEstPresse == false) { if (digitalRead(iBoutonDroite) == false) // Le bouton de droite { bBoutonAppuyeDroite = true; bUnBoutonEstPresse = true; iNombreDeBougiesAAllumer = 2; } } } // On allume physiquement les bougies sur l'anneau de leds AllumeLesBougies(iNombreDeBougiesAAllumer, 1); // // On redige le message. // tft.fillScreen(BLACK); tft.setRotation(2); tft.setCursor(0, 20); tft.setTextColor(YELLOW); tft.print(" "); tft.setTextSize(5); tft.setTextColor(YELLOW); tft.setCursor(90, 20); tft.setTextSize(5); if (iNombreDeBougiesDejaAllumees < 10) { tft.print("0"); } tft.print(iNombreDeBougiesDejaAllumees); tft.setTextColor(GREEN); tft.setCursor(0, 80); tft.setTextSize(3); tft.println(" VOUS "); tft.println(" ALLUMEZ "); tft.print(" "); tft.print(iNombreDeBougiesAAllumer); if (iNombreDeBougiesAAllumer == 1) { tft.println(" BOUGIE."); } else { tft.println(" BOUGIES."); } iNombreDeBougiesDejaAllumees = iNombreDeBougiesDejaAllumees + iNombreDeBougiesAAllumer; tft.setCursor(90, 260); tft.setTextColor(RED); tft.setTextSize(5); if (iNombreDeBougiesDejaAllumees < 10) { tft.print("0"); } tft.print(iNombreDeBougiesDejaAllumees); tft.setTextColor(WHITE); delay(iDelai); // // Est-ce la fin ? // if (iNombreDeBougiesDejaAllumees >= iNombreTotalDeBougies) { // // Message de victoire du joueur sur l'ecran LCD. // tft.fillScreen(BLACK); tft.setRotation(2); tft.setCursor(0, 20); tft.setTextSize(3); tft.setTextColor(YELLOW); tft.setCursor(0, 20); tft.setTextColor(GREEN); tft.println(" "); tft.println("-------------"); tft.println(" VOUS AVEZ "); tft.println(" GAGNE! "); tft.println(" "); tft.println(" BRAVO! "); tft.println("-------------"); for (t = 0; t < 10; t++) { colorWipe(strip.Color(0, 255, 0), 50); // Vert. colorWipe(strip.Color(0, 0, 0), 50); // Noir. } delay(iDelai * 2); bJeuFini = true; iNombreDeBougiesDejaAllumees = 0; } } // // : ------------------ : // : Recommencer le jeu : // : ------------------ : // void RecommencerLeJeu() { iNombreDeBougiesAAllumer = 0; iNombreDeBougiesDejaAllumees = 0; iNombreDePositionsGagnantes = 0; } // // : ------------------ : // : Allume les bougies : // : ------------------ : // void AllumeLesBougies(int iLed, int iCouleur) { for (t = 1; t <= iLed; t++) { if (iCouleur == 1) { strip.setPixelColor(iNombreDeBougiesDejaAllumees + t, strip.Color(0, 255, 0)); // Vert. } else { strip.setPixelColor(iNombreDeBougiesDejaAllumees + t, strip.Color(0, 0, 255)); // Bleu. } } for (t = 21; t <= 24; t++) { strip.setPixelColor(t, strip.Color(0, 0, 0)); // Noir. } strip.show(); }