Aller au contenu
← Tous les projets

Air-hockey sur microcontrôleur

Un jeu vidéo à deux joueurs entièrement programmé sur une carte électronique STM32 : un écran couleur, deux joysticks et une physique de balle réaliste. Et vous pouvez y jouer ici.

Cadre
SAÉ Informatique embarquée · S3
Période
Octobre 2026
Matériel
Nucleo L476RG · ILI9341 · 2 joysticks
Mon rôle
Conception et programmation du jeu
NUCLEO-L476RG · ÉCRAN ILI9341 320×240PWR

Bleu ZQSD · Jaune ↑←↓→ · Espace bouton du joystick · Mobile : un doigt de chaque côté · Premier à 10

En une phraseJ'ai programmé un petit jeu d'air-hockey qui tourne sur une carte électronique, sans ordinateur. Le jeu ci-dessus est le même programme, traduit pour le navigateur : mêmes constantes, même physique.

01L'objectif

Développer une application embarquée complète sur une carte STM32 : lire des entrées analogiques (joysticks), gérer un affichage graphique (écran TFT 320 × 240 en SPI) et faire tourner une boucle de jeu fluide à environ 60 images par seconde.

02Ma contribution, étape par étape

  1. 01Prise en main

    Tester chaque périphérique

    J'ai d'abord écrit de petits programmes de test : afficher sur l'écran, lire les axes des joysticks, détecter l'appui sur leur bouton. J'ai ajouté une zone morte pour que le joueur ne bouge pas tout seul quand le joystick est au repos.

    ⌁ Lecture d'un axe
    // CAN 12 bits : 0..4095, centre ≈ 2048
    int lireAxe(int pin)
    {
      int v = analogRead(pin) - 2048;
      if (abs(v) < 300) return 0;   // zone morte
      return v / 500;                  // vitesse de -4 à +4 pixels/image
    }
  2. 02Affichage

    Le terrain et le score

    J'ai dessiné le terrain avec des constantes (largeur, hauteur des buts, rayon des palets) pour pouvoir tout régler facilement. Pour éviter le scintillement, je n'efface et ne redessine que ce qui bouge.

  3. 03Physique

    Rebonds, effets et accélération

    C'est la partie dont je suis le plus fier. À chaque contact, je calcule la direction entre le centre du palet et la balle pour un rebond miroir. Si le joueur frappe à contre-sens, il renvoie la balle plus fort. Après dix échanges, la balle accélère progressivement.

    ⌁ Collision balle / palet
    float d = sqrt(d2), nx = dx / d, ny = dy / d;   // normale au contact
    b.x = j.x + nx * dmin;  b.y = j.y + ny * dmin;   // sortir la balle du palet
    
    float vn = b.vx * nx + b.vy * ny;
    if (vn >= 0) return;                           // la balle s'éloigne déjà
    
    b.vx -= 2 * vn * nx;  b.vy -= 2 * vn * ny;     // rebond miroir
    if (j.vx * vxEntree + j.vy * vyEntree < 0) {   // frappe à contre-sens
      b.vx += j.vx * FORCE_JOUEUR;  b.vy += j.vy * FORCE_JOUEUR;
    }
    if (++b.echanges > ECHANGES_ACCEL)
      b.vitesse = fminf(VITESSE_MAX, VITESSE_BASE + (b.echanges - ECHANGES_ACCEL) * ACCEL_PAR_ECHANGE);
    fixerVitesse(b);                                // la norme de la vitesse est imposée
  4. 04Méthode

    Outils et suivi de version

    J'ai travaillé avec PlatformIO, le débogueur ST-Link et Git : une dizaine de commits retracent l'avancement, des tests de l'écran jusqu'au jeu complet. La documentation du code est générée avec Doxygen.

60images par seconde
320×240pixels, écran SPI
10commits Git

03Une difficulté, et comment je l'ai résolue

Le problème : la balle « collée »

Quand la balle entrait un peu dans le palet entre deux images, la collision était détectée plusieurs fois de suite : la balle tremblait ou restait coincée.

La solution

À chaque contact, je replace la balle juste à l'extérieur du palet et je ne la fais rebondir que si elle se dirige vraiment vers le joueur. J'impose aussi la norme de la vitesse : le joueur change la direction, pas la vitesse, ce qui garde le jeu contrôlable.

04Ce que j'ai appris

Compétences techniques

  • Programmer un microcontrôleur STM32 en C/C++
  • Lire des entrées analogiques (CAN 12 bits) et piloter un écran SPI
  • Écrire une boucle temps réel et un peu de géométrie vectorielle
  • Utiliser PlatformIO, un débogueur et Git

Compétences transversales

  • Avancer par petites étapes testées
  • Régler un système par essais (vitesse, accélération)
  • Penser à l'utilisateur : un jeu doit être agréable, pas seulement fonctionner
  • C / C++
  • STM32
  • SPI
  • CAN
  • PlatformIO
  • Git
  • Doxygen
  • Autonomie
  • Créativité