Jeu labyrinthe avec touch pad

De Les Fabriques du Ponant
Aller à : navigation, rechercher

Description

Labyrinthe-retro-game.jpg

Qui ne connaît pas le jeu du labyrinthe à bille : Un jeu qui consiste à faire sortir une bille d'un labyrinthe en utilisant deux molettes permettant de faire pencher le plateau du labyrinthe vers le haut ou le bas, et vers la droite ou la gauche, le tout en évitant de faire tomber la bille dans les trous qui parsèment le chemin.

Ce projet a donc eu pour objectif de pouvoir jouer au jeu du labyrinthe en commandant les inclinaisons du plateau grâce à un touch pad depuis un téléphone portable.

Liste du matériel

Électronique

Impression 3D

Les fichiers nécessaires à l'impression 3D du modèle utilisé dans ce tutoriel sont accessibles A COMPLETER

Coût

Pour l'ensemble du projet, il faut compter un coût global électronique + impression 3D de 15 euros environ.

Réalisation du projet

La réalisation de ce projet est relativement simple. Elle se résume en 4 étapes :

  1. Initier les impressions 3D selon les modèles de fichiers listés dans la section Impression 3D ;
  2. Réaliser le câblage du D1 mini Wemos avec les servomoteurs selon le schéma de câblage fourni ci-dessous dans la partie Schéma ;
  3. Télécharger le programme dans le D1 mini Wemos ;
  4. Jouer.

Schéma

Code

Le code nécessaire à ce projet se sépare en deux parties :

  1. Web (HTML/CSS/JavaScript) permettant d'afficher un touch pad sur le téléphone portable et de commander l'inclinaison du plateau du labyrinthe ;
  2. C++ (Arduino) permettant de programmer le D1 mini Wemos pour qu'il ouvre une connexion WIFI et d'adresser les commandes reçues aux servomoteurs contrôlant l'inclinaison du plateau du labyrinthe.

HTML

 1 <!DOCTYPE html>
 2 <html lang='fr'>
 3 <head>
 4     <meta charset='UTF-8'>
 5     <meta name='viewport' content='width=device-width, initial-scale=1.0'>
 6     <title>Jeu du labyrinthe</title>
 7 </head>
 8 <body>
 9     <!-- Affiche le touch pad -->
10     <div id='pad'>
11         <!-- Affiche une croix au centre du touch pad -->
12         <div id='centrePad'>+</div>
13     </div>
14 </body>
15 </html>

CSS

 1 <style>
 2     /* Dessine la forme/couleur du touch pad */
 3     #pad {
 4         background-color: #f0f0f0;
 5         border-radius: 50%;
 6         position: relative;
 7         user-select: none;
 8     }
 9     /* Positionne la croix au milieu du touch pad et définit la taille de la croix */
10     #centrePad {
11         position: absolute;
12         top: 50%;
13         left: 50%;
14         transform: translate(-50%, -50%);
15         font-size: 24px;
16     }
17 </style>

JavaScript

 1 <script>
 2     const pad = document.getElementById('pad');
 3     const rect = pad.getBoundingClientRect();
 4     // Permet de stocker la vitesse sur les axes x et y par rapport à la position du doigt sur le touch pad
 5     let vitesse = [0, 0];
 6     // Définit la vitesse max autorisée pour les deux axes - Valeur modifiable
 7     let vitesseMax = 4;
 8     /************************************************************/
 9     /* Détermine le nombre de vitesses qu'il y a sur chaque axe */
10     /* Il faut prévoir aussi bien le mouvement en positif qu'en */
11     /* négatif, et ne pas oublier 0 (pas de mouvement).         */
12     /* Avec vitesseMax = 4, on obtient 9 vitesses possibles :   */
13     /* [-4 ; -3 ; -2 ; -1 ; 0 ; 1 ; 2 ; 3 ; 4]                  */
14     /************************************************************/
15     let nbVitesses = vitesseMax * 2 + 1;
16     // Définit la taille du touch pad en pixel - Valeur modifiable
17     let taillePad = 180;
18     let pallierVitesse = taillePad / nbVitesses;
19     let timerId = null;
20 
21     pad.style.width = pad.style.height = taillePad + 'px';
22 
23     function envoiMouvement() {
24         const xhr = new XMLHttpRequest();
25         xhr.open('Mouvement', 'mouvement?x=' + vitesse[0] + '&y=' + vitesse[1], true);
26         xhr.send();
27     }
28 
29     pad.addEventListener('touchstart', (position) => {
30         vitesse[0] = Math.trunc((position.touches[0].clientX - rect.left)/pallierVitesse) - vitesseMax;
31         vitesse[1] = vitesseMax - Math.trunc((position.touches[0].clientY - rect.top)/pallierVitesse);
32         envoiMouvement();
33         timerId = setInterval(envoiMouvement, 10);
34     });
35 
36     pad.addEventListener('touchmove', (position) => {
37         if(position.touches[0].clientX < rect.left || position.touches[0].clientX > (taillePad + rect.left) ||
38             position.touches[0].clientY < rect.top || position.touches[0].clientY > (taillePad + rect.top))
39                 return;
40 
41         vitesse[0] = Math.trunc((position.touches[0].clientX - rect.left)/pallierVitesse) - vitesseMax;
42         vitesse[1] = vitesseMax - Math.trunc((position.touches[0].clientY - rect.top)/pallierVitesse);
43 
44     });
45 
46     pad.addEventListener('touchend', (position) => {
47         vitesse[0] = vitesse[1] = 0;
48         clearInterval(timerId);
49         envoiMouvement();
50         timerId = null;
51     });
52 </script>

C++

1 

Explications

Pour aller plus loin