Programmer le jeu dinosaure de Google sur l’ESP32 2432s028

Vous voyez ce jeu du dinosaure qui se lance automatiquement sur Chrome lorsque nous perdons la connexion internet ?

il est tout à fait possible d’en installer une version simplifiée sur l’ESP32 CYD. Si vous avez suivi le tutoriel de base sur « comment configurer l’Arduino IDE pour l’ESP32 2432S028 » vous n’aurez aucune bibliothèque a installer. Uniquement téléverser le code ci-dessous.

Le jeu se jour en appuyant sur le bouton « boot » situé a l’arrière de notre carte ESP32 CYD. (Encadré en rouge sur l’image ci-dessous)

Code pour installer le jeu du dino de Google sur l’ESP32 2432S028

#include <TFT_eSPI.h>
#include <SPI.h>

TFT_eSPI tft = TFT_eSPI();

// Constantes du jeu simplifiées
#define DINO_X 30
#define DINO_Y 180
#define DINO_WIDTH 24
#define DINO_HEIGHT 24
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
#define GROUND_Y 204
#define GRAVITY 1.2
#define JUMP_FORCE -12

// Sprite du T-Rex (inchangé)
const uint8_t DINO_SPRITE[] = {
    0b00000000, 0b11111000, 0b00000000,
    0b00000001, 0b11111100, 0b00000000,
    0b00000001, 0b11111110, 0b00000000,
    0b00000001, 0b11111110, 0b00000000,
    0b00000001, 0b11111111, 0b00000000,
    0b00000001, 0b11111111, 0b00000000,
    0b00000001, 0b11111111, 0b00000000,
    0b00000001, 0b11111111, 0b10000000,
    0b00000001, 0b11111111, 0b00000000,
    0b11000001, 0b11111111, 0b00000000,
    0b11100001, 0b11111111, 0b00000000,
    0b11110001, 0b11111111, 0b00000000,
    0b11111001, 0b11111111, 0b00000000,
    0b11111101, 0b11111110, 0b00000000,
    0b11111111, 0b11111100, 0b00000000,
    0b01111111, 0b11111000, 0b00000000,
    0b00111111, 0b11111000, 0b00000000,
    0b00011111, 0b11111000, 0b00000000,
    0b00001111, 0b11110000, 0b00000000,
    0b00000111, 0b11100000, 0b00000000,
    0b00000011, 0b11000000, 0b00000000,
    0b00000000, 0b11000000, 0b00000000,
    0b00000001, 0b01000000, 0b00000000,
    0b00000001, 0b10000000, 0b00000000
};

// Variables du jeu
float dinoY = DINO_Y;
float jumpVelocity = 0;
int obstacleX = SCREEN_WIDTH;
int score = 0;
int highScore = 0;
bool isJumping = false;
bool gameOver = false;

void updateScores() {
    // Efface les anciennes zones de score
    tft.fillRect(5, 5, 150, 20, TFT_WHITE);    // Zone score actuel
    tft.fillRect(220, 5, 95, 20, TFT_WHITE);   // Zone high score, déplacée plus à droite
    
    // Affiche le score actuel
    tft.setTextColor(TFT_BLACK, TFT_WHITE);
    tft.setTextSize(2);
    tft.setCursor(5, 5);
    tft.print("Score: ");                      // Ajout du mot "Score"
    tft.print(score);
    
    // Affiche le meilleur score, déplacé plus à droite
    tft.setCursor(220, 5);                    // Position plus à droite
    tft.print("HI: ");
    tft.print(highScore);
}

void setup() {
    pinMode(0, INPUT_PULLUP);
    
    tft.init();
    tft.setRotation(1);
    tft.fillScreen(TFT_WHITE);
    
    // Optimisation SPI
    SPI.beginTransaction(SPISettings(80000000, MSBFIRST, SPI_MODE0));
    
    // Écran de démarrage
    tft.setTextColor(TFT_BLACK, TFT_WHITE);
    tft.setTextSize(2);
    tft.drawString("Appuyez sur BOOT", 40, 100);
    
    while(digitalRead(0) == HIGH) delay(10);
    
    tft.fillScreen(TFT_WHITE);
    tft.drawFastHLine(0, GROUND_Y, SCREEN_WIDTH, TFT_BLACK);
    updateScores();
}

void loop() {
    if (!gameOver) {
        // Gestion du saut
        if (digitalRead(0) == LOW && !isJumping) {
            isJumping = true;
            jumpVelocity = JUMP_FORCE;
        }
        
        // Mise à jour de la position du dino
        if (isJumping) {
            float oldY = dinoY;
            dinoY += jumpVelocity;
            jumpVelocity += GRAVITY;
            
            if (dinoY >= DINO_Y) {
                dinoY = DINO_Y;
                isJumping = false;
                jumpVelocity = 0;
            }
            
            if ((int)oldY != (int)dinoY) {
                tft.fillRect(DINO_X, (int)oldY, DINO_WIDTH, DINO_HEIGHT, TFT_WHITE);
                drawDino((int)dinoY);
            }
        }
        
        // Déplacement de l'obstacle
        int oldX = obstacleX;
        obstacleX -= 4;
        if (obstacleX < -20) {
            obstacleX = SCREEN_WIDTH;
            score++;
            updateScores();
        }
        
        // Effacement et dessin de l'obstacle
        tft.fillRect(oldX, DINO_Y, 20, 24, TFT_WHITE);
        tft.fillRect(obstacleX, DINO_Y, 20, 24, TFT_BLACK);
        
        // Collision
        if (obstacleX < (DINO_X + DINO_WIDTH - 4) && 
            obstacleX + 16 > (DINO_X + 4) && 
            dinoY + DINO_HEIGHT > DINO_Y) {
            gameOver = true;
            if (score > highScore) {
                highScore = score;
            }
        }
        
        delay(16);
    } else {
        tft.fillScreen(TFT_WHITE);
        tft.setTextColor(TFT_RED, TFT_WHITE);
        tft.drawString("GAME OVER!", 80, 100);
        tft.drawString("Score: " + String(score), 80, 130);
        tft.drawString("HI: " + String(highScore), 80, 160);
        
        while(digitalRead(0) == HIGH) delay(10);
        resetGame();
    }
}

void drawDino(int y) {
    int byteWidth = (DINO_WIDTH + 7) / 8;
    for (int dy = 0; dy < DINO_HEIGHT; dy++) {
        for (int dx = 0; dx < DINO_WIDTH; dx++) {
            int byteIndex = dy * byteWidth + (dx / 8);
            int bitIndex = 7 - (dx % 8);
            if (DINO_SPRITE[byteIndex] & (1 << bitIndex)) {
                tft.drawPixel(DINO_X + dx, y + dy, TFT_BLACK);
            }
        }
    }
}

void resetGame() {
    dinoY = DINO_Y;
    obstacleX = SCREEN_WIDTH;
    score = 0;
    isJumping = false;
    jumpVelocity = 0;
    gameOver = false;
    tft.fillScreen(TFT_WHITE);
    tft.drawFastHLine(0, GROUND_Y, SCREEN_WIDTH, TFT_BLACK);
    updateScores();
}

Comment fonctionne ce code:

Configuration et Constantes :

#define DINO_X 30          // Position X fixe du dinosaure
#define DINO_Y 180         // Position Y de base du dinosaure
#define GRAVITY 1.2        // Force de gravité
#define JUMP_FORCE -12     // Force du saut (négatif car Y diminue vers le haut)
  1. Variables principales :
float dinoY = DINO_Y;      // Position Y actuelle du dino
float jumpVelocity = 0;    // Vitesse verticale du saut
int obstacleX = SCREEN_WIDTH;  // Position X de l'obstacle
int score = 0;             // Score actuel
int highScore = 0;         // Meilleur score
  1. Logique de jeu (dans loop()):
  • Le dinosaure reste à une position X fixe (DINO_X)
  • Les obstacles se déplacent de droite à gauche
  • Le bouton BOOT permet de faire sauter le dinosaure
  • Le score augmente quand un obstacle est passé
  • La collision termine la partie
  1. Mécanisme de saut :
if (digitalRead(0) == LOW && !isJumping) {  // Si bouton pressé et pas déjà en saut
    isJumping = true;
    jumpVelocity = JUMP_FORCE;              // Applique la force de saut
}

// Pendant le saut
if (isJumping) {
    dinoY += jumpVelocity;                  // Déplace le dino
    jumpVelocity += GRAVITY;                // Applique la gravité

    if (dinoY >= DINO_Y) {                  // Si au sol
        dinoY = DINO_Y;
        isJumping = false;
        jumpVelocity = 0;
    }
}
  1. Gestion des obstacles :
obstacleX -= 4;                    // Déplace l'obstacle vers la gauche
if (obstacleX < -20) {            // Si l'obstacle sort de l'écran
    obstacleX = SCREEN_WIDTH;      // Nouveau obstacle à droite
    score++;                       // Augmente le score
}
  1. Système d’affichage :
  • drawDino() : Dessine le sprite du dinosaure pixel par pixel
  • updateScores() : Met à jour l’affichage des scores
  • Les obstacles sont des rectangles noirs simples
  • Une ligne noire représente le sol
  1. Collision :
if (obstacleX < (DINO_X + DINO_WIDTH - 4) &&  // Si collision
    obstacleX + 16 > (DINO_X + 4) && 
    dinoY + DINO_HEIGHT > DINO_Y) {
    gameOver = true;
    if (score > highScore) {
        highScore = score;
    }
}
  1. Game Over :
  • Affiche « GAME OVER! »
  • Montre le score final et le high score
  • Attend un appui sur le bouton pour recommencer
  • Réinitialise le jeu avec resetGame()

La logique principale est :

  1. Le joueur appuie sur BOOT pour faire sauter le dino
  2. Les obstacles défilent automatiquement
  3. Le joueur doit éviter les obstacles en sautant
  4. Le score augmente à chaque obstacle passé
  5. La collision avec un obstacle termine la partie
  6. Le meilleur score est conservé

C’est une version simplifiée mais fonctionnelle du jeu du dinosaure de Chrome, adaptée pour un écran TFT avec un seul bouton de contrôle.