Hackster is hosting Hackster Holidays, Finale: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Tuesday!Stream Hackster Holidays, Finale on Tuesday!
jysbelfort
Published © LGPL

Hard-Dino LCD Game !!

This is a small game on a 2 lines LCD screen. Help the Dino to jump over the cactus while avoiding the bats. Just push the pushbutton

IntermediateFull instructions provided306
Hard-Dino LCD Game !!

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
RGB LCD Shield Kit, 16x2 Character Display
RGB LCD Shield Kit, 16x2 Character Display
The standard one from the Arduino Starter Kit
×1
Pushbutton Switch, Momentary
Pushbutton Switch, Momentary
The standard one from the Arduino Starter Kit, 1 or 2 according to the option you select
×1
Breadboard (generic)
Breadboard (generic)
The standard one from the Arduino Starter Kit, but 2 for more room
×2
Single Turn Potentiometer- 10k ohms
Single Turn Potentiometer- 10k ohms
The standard one from the Arduino Starter Kit,
×2
Resistor 10k ohm
Resistor 10k ohm
The standard one from the Arduino Starter Kit,
×1
Buzzer
Buzzer
The standard one from the Arduino Starter Kit
×1

Story

Read more

Schematics

Schematics and circuit diagrams

To connect the screen and the potentiometers

Code

Hard-Dino Game, By JY and Antonin Subiger

C/C++
This is a small game on a 2 lines LCD screen. Help the Dino to jump over the cactus while avoiding the nasty birds. Just push the pushbutton
/* the Hard Dino Game
by Jean-Yves Subiger and my son Antonin Subiger
France
13 Nov 2022
*/

#include <LiquidCrystal.h>        // Librairie pour ecran LCD

LiquidCrystal ecran(12, 11, 5, 4, 3, 2);
int PosAnt [16] [2];                  // Position des obstacles ( Tableau )
bool BoutonLache = false;         // Vrai si l'interupteur a été laché
int Inter = 0;                    // etat de l'interupteur High ou low
int LigBonh =1;                   // Ligne du bonhomme 0 ou 1
int II = 0;                       // Index du tableau
int LL = 0;
int Fix = 500;                    // Durée en miliseconde où tout est fixé, rien ne bouge =  vitesse du jeu
int ColBonh = 1;                  // Constante, Numero de colonen du bonhomme, toujour 1
int EspaceAl = 8;                 // Ecart initial entre 2 obstacles
int Espace =0;                    // Nombre de décallage depuis l'introduction du dernier obstacle
int Vie =3;                       // Nombre de vie
long InterAugVitess = 20000;
int Reduit =0;
int InterReduit=0;
unsigned long MeilleurScore=0;
unsigned long Score=0;
unsigned long DepartScore =0;
unsigned long DepartSaut =0;      // moment de départ du sut 
unsigned long DecalObs =0;        // Moment du dernier décallage des obstacles

byte oiseau[8] ={
  0b00001,
  0b00010,
  0b01101,
  0b10110,
  0b01111,
  0b00010,
  0b00000,
  0b00000,
};

byte personnage[8] ={
  0b01110,
  0b01011,
  0b01111,
  0b00110,
  0b10110,
  0b11111,
  0b01110,
  0b01010,
} ;

byte cactus1[8] ={
  0b00100,
  0b00101,
  0b10101,
  0b10111,
  0b10100,
  0b11100,
  0b00100,
  0b00100,
};

byte cactus2[8] = {
  0b00100,
  0b00101,
  0b10101,
  0b10111,
  0b11100,
  0b00101,
  0b00111,
  0b00100,
};

byte coeur[8]={
  0b01010,
  0b11111,
  0b11111,
  0b11111,
  0b01110,
  0b00100,
  0b00000,
  0b00000,  
};

byte coeurvide[8]={
  0b01010,
  0b10101,
  0b10001,
  0b10001,
  0b01010,
  0b00100,
  0b00000,
  0b00000,  
};

byte mort[8]={
  0b01000,
  0b01001,
  0b00101,
  0b00110,
  0b00100,
  0b01110,
  0b01011,
  0b11111,
};

void PauseBouton() {
  Inter = digitalRead(7);   
  while (Inter == LOW) {                    // Pour attendre que le joueur appuie sur le bouton
    Inter = digitalRead(7);                 // Detecter appuie sur le bouton
  }
  while (Inter == HIGH) {                   // Pour attendre que le joueur relache le bouton
    Inter = digitalRead(7);                 // Lit la position du bouton
  }
}

void setup() {
  Serial.begin(9600);
  ecran.createChar(0, personnage);          // définition du personnage
  ecran.createChar(1, cactus1);
  ecran.createChar(2, cactus2);
  ecran.createChar(3, oiseau);
  ecran.createChar(4, coeur);
  ecran.createChar(5, coeurvide);   
  ecran.createChar(7, mort);
  pinMode(7, INPUT);                        // Branchement interupteur pour sauter
  ecran.begin(16,2);
  }  // end of vset up,  Fin de la boucle void

void loop() {
  ecran.clear();                            // to clear the screen, Pour effacer l'écran
  ecran.setCursor(1, 0) ;
  ecran.print("Hard Dinos Game");
  ecran.setCursor(1, 1);
  ecran.print("Push To Start !");
  PauseBouton();

  if (MeilleurScore <1 ) {                 // Display instruction for the first game only   
    ecran.setCursor(0, 1) ;
    ecran.print("Avoid           ");
    ecran.setCursor(7, 1);
    ecran.write(1); 
    ecran.setCursor(9, 1);
    ecran.write(2);
    ecran.setCursor(11, 1);
    ecran.write(3); 
    PauseBouton();
  }

  ecran.clear();
  for (II=1; II<4; II++) {                  // give the start to play
    ecran.setCursor(3*II+1,0);
    ecran.print("Go");
    tone(8, 400 , 300 );
    delay(500);
  }
  ecran.clear();
  tone(8, 600 , 500 );
  ecran.setCursor(13, 0);                   // Affichage des vies, coeurs pleins
  ecran.write(byte(4));
  ecran.setCursor(14, 0);
  ecran.write(byte(4));
  ecran.setCursor(15, 0);
  ecran.write(byte(4));
  
  for (LL=0; LL<2; LL++) {                // reset the table, Initialisation du tableau
    for (II=0; II<16; II++) { 
      PosAnt[II][LL] =0;
    }
  }
  PosAnt[15] [1] = 1;                     // premier obstacle
  DecalObs = millis();                    // Memorisation 
  DepartScore = millis();
 
  while (Vie > 0) {     

    // 1- obstacles review 
    if (millis()-DecalObs > Fix) {          //   Gestion et affichage des obstacles si pause termine
      DecalObs = millis();
      // 1.1 Move the obstacle to the left
      for (LL=0; LL<2; LL++) {            // Décallage des obsacles vers la gauche
        for (II=0; II<15; II++) {    
          PosAnt[II] [LL]= PosAnt[II+1][LL];   // Décallage des obsacles vers la gauche
        }
      }
      PosAnt[15][1]=0;
      PosAnt[15][0]=0;
      Espace++;
      // 1.2 Add a new obstacle on the right
      if (Espace == EspaceAl) {       // 1.1 Pour afficher un nouvel obstacle de façon aleatoire
        // nouvel obstacle en bas
        if (random(1,10) >2) {  
          // Alros on fait apparaitre un obstacle en haut
          if (random(1,10) >5)  {   
            PosAnt[15][1]=1;
          } 
          else {
            PosAnt[15][1]=2;
          }         // fin else
        }
        else {
          // Sinon on fait apparatire un obstacle en bas
          PosAnt[15][0]=3;
        } //fin else   (random(1,10) >2)
        EspaceAl=random(3,8-Reduit);     // Nouvelle Longueur aleatoire entre 2 obstacles
        Espace=0;
      }  // if (Espace == EspaceAl)
    // 1.3 Display the obstacles
    for (LL=0; LL<2; LL++) {                        // 1.2 Affichage de tous les obstacles de la colonne 0 à 15
      for (II=0; II<16; II++) {      
        ecran.setCursor(II, LL);
        if (PosAnt[II][LL] > 0) { ecran.write(PosAnt[II][LL]); }     // si tableau des positions =1 ou 2 alors on affiche un obstacle
        else {                                       // sinon on efface 
          if (II != ColBonh ) {                      // Pour ne pas effacer le bonhomme
            ecran.print(" ");
          }
          else {                                      // Pour effacer quand le bonhomme est en haut
            // on est sur la colonne du bonhomme
            if (LL==1 && LigBonh == 0 ){ecran.print(" ");}  
            if (LL==0 && LigBonh == 1 ){ecran.print(" ");}  
          }
        } 
      } // fin for II
    }   // Fin for LL affiche obstacles
    }   // Fin de la gestion et affichage des obstacles

    // 2- Check if we need to start to jump
    Inter = digitalRead(7);             // Lit l'entrée 7 de la carte, le bouton poussoir
    if (Inter == HIGH && LigBonh == 1 && BoutonLache == true) {   // 2) Debut du saut
      DepartSaut = millis();            // Reset jump time  
      BoutonLache = false;
      LigBonh = 0;                      // le bonhome va sur la ligne du haut (0)
      ecran.setCursor(ColBonh,1);
      ecran.print(" ");                 // Pour effacer le bonhomme sur la ligne du bas
      tone(8,440,20);                   // haut parleur brancher en 8, note LA pendant 20 ms
    }

    // 3- Check if end of jump 
    if (millis()-DepartSaut>3*Fix && LigBonh == 0) { // 3) Verifie la fin du saut
      LigBonh = 1;                      // Le bonhomme va sur la ligne du bas (1)
      ecran.setCursor(ColBonh,0);
      ecran.print(" ");                 // Pour effacer le bonhomme sur la ligne du haut
    }

    // 4- Write the dinosaure on line "LigBonh"
    ecran.setCursor(ColBonh,LigBonh);
    ecran.write(byte(0));               // Ecrit le bonhomme sur la ligne du haut ou du bas

    // 5 
    if (Inter == LOW && LigBonh == 1) { BoutonLache=true; }  // Pour ne pas que le joueur puisse laisser le bouton enfoncé tout le temps

    // 6- Check if one accident on top or bottom line
    if ((PosAnt[ColBonh][1] >0 && LigBonh == 1) || (PosAnt[ColBonh][0] >0 && LigBonh == 0) ) {    // 4) Obstacle sur la meme colone que le bonhome et bonhome en bas : predu
      Vie--;                               // Perdu, une vie en moins
      ecran.setCursor(0, 0);
      ecran.print(" Oups !!");
      for (II=0; II< Vie; II++) {
          ecran.setCursor(15-II, 0);      // Affichage des vies, coeurs pleins
          ecran.write(byte(4));
      }
      ecran.setCursor(15-Vie, 0);
      ecran.write(5);                     // Affiche le coeur vide
      ecran.setCursor(1, 1);
      ecran.write(byte(7));               // Display dead Dino, Affiche le mort
      Fix = 500 ;                         // the speed is reset to the inital value but not the distance betwwen obstacles. La vitesse reprend plus lentement
      for (II=550; II>300; II--) {        // Option pour Bruitage buzer
        tone(8,II,10);                    // Option pour Bruitage buzer
        delay(5);                         // Option pour Bruitage buzer
      }                                   // Option pour Bruitage buzer
      noTone(8);                          // Option pour Bruitage buzer
      delay(500);
      ecran.setCursor(15-Vie, 0);
      ecran.print(" ");
      ecran.setCursor(0, 0);
      ecran.print("             ");
      ecran.setCursor(1, 1);
      ecran.write(byte(0));                // Display normal dino
    }  // Fin perdu

    // 7- Check if speed must be increase 
    if (millis() - DepartScore > InterAugVitess ){      // 5) Pour augmenter la vitesse du jeu regulierement
      Fix -= 30;                        // How much the speed increase    
      InterAugVitess += 20000;          // How often the speed increase
      InterReduit++;
      if (InterReduit>2 && Reduit <4 ) {  // How often and how small the length between each obstacler become
        InterReduit=0;
        Reduit++;                 // EspaceAl=random(3,8-Reduit); 
      }
      tone(8, 800 , 600 );
    }
  }   //  while (Vie > 0) 

  // End of one game
  ecran.clear();
  ecran.setCursor(3, 0);
  ecran.print("GAME OVER");
  ecran.setCursor(0, 1);
  ecran.print("Score: ");
  ecran.setCursor(8, 1);
  Score = millis() - DepartScore;
  ecran.print(Score);
  PauseBouton();

  if ( MeilleurScore > 0) {
    ecran.clear();
    if ( Score > MeilleurScore) {
      ecran.setCursor(3, 1);
      ecran.print(Score);
      MeilleurScore = Score;
      Inter=LOW;
      while (Inter == LOW) {                    
        Inter = digitalRead(7);                 
        ecran.setCursor(0, 0);
        ecran.print("New Best Score !!");
        DepartSaut=millis();
        while (millis()-DepartSaut<300 && Inter == LOW ) {
          Inter = digitalRead(7); 
        }
        ecran.setCursor(0, 0);
        ecran.print("                  ");
        DepartSaut=millis();
        while (millis()-DepartSaut<300 && Inter == LOW ) {
          Inter = digitalRead(7); 
        }
      }
    }
    else {
      ecran.setCursor(0, 1);
      ecran.print("Your: ");
      ecran.setCursor(6, 1);
      ecran.print(Score);
      ecran.setCursor(0, 0);
      ecran.print("Best: ");
      ecran.setCursor(6, 0);
      ecran.print(MeilleurScore);
    }
    PauseBouton();
   }
  else {
    MeilleurScore = Score;
  }
  // Reset the value before to testart the new game
  Vie = 3;
  EspaceAl = 8;
  Espace = 0;  
  Fix = 500;              
  InterAugVitess = 20000;
  Reduit = 0;
  InterReduit=0;
  Score = 0;
  
}// fin void loop 

Credits

jysbelfort
0 projects • 1 follower

Comments