ENIB 2024 : GNOP
Titre de la fiche expérience :
Sommaire
Description
Le projet est de fabriquer un jeu ludique à l'aide d'une carte Arduino, notre jeu est le D1-Pong. Inspiré du sport du tennis de table, il reprend le même principe mais avec des LEDS, la balle se déplace sur les LEDS et dès qu'elle arrive à une extrémité, le joueur en question appuie sur son bouton pour que la balle parte dans l'autre sens et ainsi de suite.
Voici notre équipe :
Photos
Outil et matériel
Pour fabriquer ce jeu, nous avons eut besoin de :
- Carte Arduino Nano
- 2 boutons d'arcade
- Carton
- Fils électriques
- Interupteur
- Batterie
- Ruban de LEDS
- Haut-parleur
Nous nous sommes servis de plusieurs outils :
- Fer à souder
- Pistolet à colle
- Cutter
Fichiers à joindre
On mettra une vidéo
Code Arduino
<syntaxhighlight lang="Arduino" line> /*
Code de fonctionnement pour le jeu PONG. Par les petits debrouillards.
- /
- include <FastLED.h>
// Definition des couleurs const CRGB NOIR = CRGB(0, 0, 0 ); //Création d'une constante de type CRGB de couleur noire const CRGB BLANC = CRGB(255, 255, 255); //Création d'une constante de type CRGB de couleur blanche const CRGB ROUGE = CRGB(255, 0, 0 ); //Création d'une constante de type CRGB de couleur rouge const CRGB VERT = CRGB(0, 255, 0 ); //Création d'une constante de type CRGB de couleur verte const CRGB BLEU = CRGB(0, 0, 255); //Création d'une constante de type CRGB de couleur bleue const CRGB JAUNE = CRGB(255, 255, 0 ); //Création d'une constante de type CRGB de couleur jaune const CRGB ROSE = CRGB(255, 0, 255); //Création d'une constante de type CRGB de couleur rose const CRGB CYAN = CRGB(0, 255, 255); //Création d'une constante de type CRGB de couleur cyan
// Definition des notes de musique const int PONG_SOUND = 250; //380 const int LOOSE_SOUND = 180;
/******************************
PARAMETRES DE BRANCHEMENTS ******************************/
const int LED_PIN = 8; // Numero de branchement de la bande de LEDs const int BUTTON1_PIN = 2; // Numero de branchement du premier bouton const int BUTTON2_PIN = 4; // Numero de branchement du deuxieme bouton const int HAUT_PARLEUR_PIN = 5; // Numero de branchement du haut parleur (optionnel)
/***********************
PARAMETRES GENERAUX ***********************/
const int NUM_LEDS = 60; // Nombre de LEDs sur la bande const CRGB PLAYER1_COLOR = VERT; // Couleur Player 1 const CRGB PLAYER2_COLOR = ROUGE; // Couleur Player 2
/***********************
PARAMETRES PONG ***********************/
const float BALL_SPEED = 0.5; // Vitesse de la balle const float ACCELERATION = 9; // Accélération de la balle a chaque tir, si ACCELERATION = 10 on augmente la vitesse de 10 pourcent a chaque tir const int HIT_ZONE = 8; // Nombre de LED pendant lesquelles on peut renvoyer la balle const int MAX_SCORE = 3; // Score maximum avant la fin du jeu
const CRGB BALL_COLOR = BLANC; // Couleur de la balle
/*******************************
PARAMETRES TIR A LA CORDE *******************************/
const float INCREMENT = 0.05; // De combien avance la corde lorsqu'on appuie sur le bouton const float ROPE_SMOOTH = 1.0; // Paramètre servant a lisser la position de la corde
const float WAVE_LENGTH = 0.2; // Taille des ondes const float WAVE_SPEED = 1.0; // Vitesse des ondes
/******************************
VARIABLES GENERALES ******************************/
// Players enum Player {
PERSONNE, PLAYER1, PLAYER2
};
// Etats du jeu enum GameState {
START, PONG, // Mode pong TAC // Mode tir a la corde
};
unsigned long lastMillis = 0; unsigned long beginTimer = 0; unsigned int counter = 0;
Player player = PLAYER1; // Prochain joueur a appuyer sur son bouton Player lastWinner = PERSONNE;
CRGB leds[NUM_LEDS]; GameState gameState = START;
/**********************************************
FONCTIONS DE FONCTIONNEMENT GENERALES **********************************************/
// Fonction permettant de changer la couleur d'une LED relativement au player 1 ou 2 void ledColor(Player player, int pos, CRGB color) {
if (player == PLAYER1) { leds[pos] = color; } else // player == PLAYER2 { leds[NUM_LEDS - pos - 1] = color; }
}
// Fonction permettant de changer la couleur d'une LED void ledColor(int pos, CRGB color) {
leds[pos] = color;
}
/*********************************************
VARIABLES DE FONCTIONNEMENT DU PONG *********************************************/
float ballSpeed = BALL_SPEED; // Vitesse de la balle float ballPosition = 1; // Position de la balle sur la bande de led (Si ballPosition = 0, la balle est devant le player 1. Si ballPosition = 1, la balle est devant le player 2) int player1Score = 0; // Score du player 1 int player2Score = 0; // Score du player 2
/**********************************************
FONCTIONS DE FONCTIONNEMENT DU PONG **********************************************/
// Fonction servant a afficher les scores void showScore() {
// On commence par effacer toutes les couleurs de led FastLED.clear();
// On allume le nombre de led correspondant au score du player 1 for (int i = 0; i < player1Score; i++) { ledColor(PLAYER1, NUM_LEDS / 2 - (i + 1), PLAYER1_COLOR); }
// On allume le nombre de led correspondant au score du player 2 for (int i = 0; i < player2Score; i++) { ledColor(PLAYER2, NUM_LEDS / 2 - (i + 1), PLAYER2_COLOR); }
// On envoie les nouvelles couleurs a la bande de led FastLED.show();
// On fait clignotter trois fois if (lastWinner == PLAYER1) { for (int i = 0; i < 3; i++) { // On eteint la derniere LED pendant 0.5s delay(500); ledColor(PLAYER1, NUM_LEDS / 2 - player1Score, NOIR); FastLED.show();
// On allume la derniere LED pendant 0.5s delay(500); ledColor(PLAYER1, NUM_LEDS / 2 - player1Score, PLAYER1_COLOR); FastLED.show(); } } else // lastWinner == PLAYER2 { for (int i = 0; i < 3; i++) { // On eteint la derniere LED pendant 0.5s delay(500); ledColor(PLAYER2, NUM_LEDS / 2 - player2Score, NOIR); FastLED.show();
// On allume la derniere LED pendant 0.5s delay(500); ledColor(PLAYER2, NUM_LEDS / 2 - player2Score, PLAYER2_COLOR); FastLED.show(); } }
// Si la partie est terminee on va a l'affichage de fin if (player1Score == MAX_SCORE || player2Score == MAX_SCORE) { gameState = START;
// On reinitialise les scores player1Score = 0; player2Score = 0;
// On reinitialise la vitesse ballSpeed = BALL_SPEED;
// On reinitialise les leds FastLED.clear(); } // Sinon on reprend le jeu else { gameState = PONG; ballSpeed = BALL_SPEED; }
}
/***************************************
FONCTION PRINCIPALE DU PONG ***************************************/
void pong_loop() {
// Calcul du temps ecoule entre deux boucles unsigned long currentMillis = millis();
// On calcule le numero de la LED allumee int ballLed = ballPosition * NUM_LEDS;
// On s'assure que la position de la balle ne depasse pas la taille de la bande de LED ballLed = min(ballLed, NUM_LEDS - 1);
// On regarde qui est en train de jouer if (player == PLAYER1) { // On regarde si le player a appuye sur son bouton et si le delai de debut de jeu est passe if (digitalRead(BUTTON1_PIN) == LOW && currentMillis - beginTimer > 500) { // Si la balle est hors de la zone de tir, l'autre player marque un point if (ballLed >= HIT_ZONE) { player2Score += 1; lastWinner = PLAYER2; ballPosition = 0;
// On joue le son de defaite tone(HAUT_PARLEUR_PIN, LOOSE_SOUND, 800);
// On passe en mode affichage des scores showScore();
// C'est a l'autre player de jouer player = PLAYER2;
// Actualisation de la variable lastMillis lastMillis = millis(); } else { // On accelere la balle ballSpeed *= 1.0 + ACCELERATION / 100;
// C'est a l'autre player de jouer player = PLAYER2;
// On joue la note de musique tone(HAUT_PARLEUR_PIN, PONG_SOUND, 100); }
return; }
// On fait avancer la balle ballPosition -= ballSpeed * (currentMillis - lastMillis) * 0.001f;
// On regarde si la balle est sortie de la zone if (ballPosition < 0.0f) { // Si oui le player 2 marque un point player2Score += 1; lastWinner = PLAYER2; ballPosition = 0;
// On joue le son de defaite tone(HAUT_PARLEUR_PIN, LOOSE_SOUND, 800);
// On passe en mode affichage des scores showScore();
// C'est a l'autre player de jouer player = PLAYER2;
// Actualisation de la variable lastMillis lastMillis = millis(); return; } } else // player == PLAYER2 { // On regarde si le player a appuye sur son bouton et si le delai de debut de jeu est passe if (digitalRead(BUTTON2_PIN) == LOW && currentMillis - beginTimer > 500) { // Si la balle est hors de la zone de tir, l'autre player marque un point if (ballLed < NUM_LEDS - HIT_ZONE) { player1Score += 1; lastWinner = PLAYER1; ballPosition = 1;
// On joue le son de defaite tone(HAUT_PARLEUR_PIN, LOOSE_SOUND, 800);
// On passe en mode affichage des scores showScore();
// C'est a l'autre player de jouer player = PLAYER1;
// Actualisation de la variable lastMillis lastMillis = millis(); } else { // On accelere la balle ballSpeed *= 1.1;
// C'est a l'autre player de jouer player = PLAYER1;
// On joue la note de musique tone(HAUT_PARLEUR_PIN, PONG_SOUND, 100); }
return; }
// On fait avancer la balle dans l'autre sens ballPosition += ballSpeed * (currentMillis - lastMillis) * 0.001f;
// On regarde si la balle est sortie de la zone if (ballPosition >= 1) { // Si oui le player 1 marque un point player1Score += 1; lastWinner = PLAYER1; ballPosition = 1;
// On joue le son de defaite tone(HAUT_PARLEUR_PIN, LOOSE_SOUND, 800);
// On passe en mode affichage des scores showScore(); // C'est a l'autre player de jouer player = PLAYER1;
// Actualisation de la variable lastMillis lastMillis = millis(); return; } }
///// AFFICHAGE BANDE DE LEDs ///// // Premierement on efface toutes les couleurs precedentes FastLED.clear();
// Ensuite on allume faiblement les LEDs correspondant a la zone de chaque cote for (int i = 0; i < HIT_ZONE; i++) { // On allume de chaque cote ledColor(PLAYER1, i, PLAYER1_COLOR / 10); // On divise la couleur par 10 pour la rendre 10 fois moins puissante ledColor(PLAYER2, i, PLAYER2_COLOR / 10); }
// Ensuite on allume faiblement les LEDs correspondant aux scores // Pour le player 1 for (int i = 0; i < player1Score; i++) { ledColor(PLAYER1, NUM_LEDS / 2 - (i + 1), PLAYER1_COLOR / 15); } // Pour le player 2 for (int i = 0; i < player2Score; i++) { ledColor(PLAYER2, NUM_LEDS / 2 - (i + 1), PLAYER2_COLOR / 15); }
// Ensuite on actualise la position de la balle // On donne la couleur de la led en fonction de si la balle est dans la zone d'un player ou non
// Si la balle est dans le camp d'un des player, elle est rouge. if (ballLed < HIT_ZONE || ballLed >= NUM_LEDS - HIT_ZONE) { ledColor(ballLed, ROUGE); } // Si elle en est proche, elle est jaune else if (ballLed < 2 * HIT_ZONE || ballLed >= NUM_LEDS - 2 * HIT_ZONE) { ledColor(ballLed, JAUNE); } // Sinon la balle a sa couleur par defaut else { ledColor(ballLed, BALL_COLOR); }
// On envoie la couleur des leds a la bande de leds FastLED.show();
// On actualise la variable lastMillis pour la boucle suivante lastMillis = currentMillis;
}
/*******************************************************
VARIABLES DE FONCTIONNEMENT DU TIR A LA CORDE *******************************************************/
float ropePosition = 0.5; // Position non lissee de la corde float displayedRopePosition = 0.5; // Position lissee de la corde bool player1Pushed = false; bool player2Pushed = false;
float player1Waves[10] = { 0 }; float player2Waves[10] = { 0 };
/***********************************************
FONCTION PRINCIPALE DU TIR A LA CORDE ***********************************************/
void tac_loop() {
// Calcul des temps unsigned long ms = millis(); float dt = (ms - lastMillis) * 0.001f; lastMillis = ms;
// Si moins d'une seconde s'est ecoule depuis le debut, on ne fait rien (pour eviter d'appuyer sans faire expres) if (ms - beginTimer < 1000) return;
bool player1Push = !digitalRead(BUTTON1_PIN); bool player2Push = !digitalRead(BUTTON2_PIN);
if (player1Push && !player1Pushed) { // On incremente la position de la corde ropePosition += INCREMENT;
// On lance une nouvelle onde for (int i = 0; i < 10; i++) { if (player1Waves[i] == 0.0f) { //player1Waves[i] = WAVE_SPEED * dt; player1Waves[i] = 0.01f; break; } } } if (player2Push && !player2Pushed) { // On incremente la position de la corde ropePosition -= INCREMENT;
// On lance une nouvelle onde for (int i = 0; i < 10; i++) { if (player2Waves[i] == 0.0f) { player2Waves[i] = 0.99f; break; } } }
// Memorisation des etats des boutons player1Pushed = player1Push; player2Pushed = player2Push;
// On calcule la position lissee de la corde (displayedRopePosition correspond a la variable ropePosition avec un lissage supplementaire) displayedRopePosition += (ropePosition - displayedRopePosition) * dt / ROPE_SMOOTH;
// On regarde si player 1 a gagne if (displayedRopePosition >= 1.0f) { lastWinner = PLAYER1; gameState = START; beginTimer = millis();
ropePosition = 0.5f; displayedRopePosition = 0.5f;
FastLED.clear(); return; } // On regarde si player 2 a gagne else if (displayedRopePosition <= 0.0f) { lastWinner = PLAYER2; gameState = START; beginTimer = millis();
ropePosition = 0.5f; displayedRopePosition = 0.5f;
FastLED.clear(); return; }
// On propage les ondes float dx = WAVE_SPEED * dt;
for (int wave = 0; wave < 10; wave++) { // Ondes player 1 if (player1Waves[wave] != 0.0f) { player1Waves[wave] += dx;
// Si toute l'onde depasse le point de la corde, on l'arrete if (player1Waves[wave] - WAVE_LENGTH > displayedRopePosition) { player1Waves[wave] = 0.0f; } }
// Ondes player 2 if (player2Waves[wave] != 0.0f) { player2Waves[wave] -= dx;
// Si toute l'onde depasse le point de la corde, on l'arrete if (player2Waves[wave] + WAVE_LENGTH < displayedRopePosition) { player2Waves[wave] = 0.0f; } } }
// On actualise la bande de leds float ledLuminosity; float ledPosition;
FastLED.clear();
// On commence par calculer le numero de la led correspondant a la position de la corde int ropeLedPosition = NUM_LEDS * displayedRopePosition;
// On dessine la zone du player 1 // Pour cela on calcule la luminosite led par led for (int led = 0; led < ropeLedPosition; led++) { // La luminosite minimale d'une led est 10% de la luminosite max ledLuminosity = 0.1f; ledPosition = float(led) / float(NUM_LEDS);
// Pour chaque onde, on ajoute la luminosite a la led for (int wave = 0; wave < 10; wave++) { // Si l'onde n'est pas active ou si l'onde est avant la led, on n'ajoute aucune luminosite if (player1Waves[wave] == 0.0f || player1Waves[wave] < ledPosition) continue;
// On ajoute de la luminosite de facon decroissante. plus l'onde est loin, moins on ajoute de luminosite. ledLuminosity += max(0.0f, 0.9f - (player1Waves[wave] - ledPosition) / WAVE_LENGTH); } // La valeur maximale de luminosite est 1.0 if (ledLuminosity > 2.0f) ledLuminosity = 2.0f;
// On actualise la valeur de luminosite de la led ledColor(led, PLAYER1_COLOR / int(2.0f / ledLuminosity) / 5); }
// On dessine la zone du player 2 for (int led = ropeLedPosition + 1; led < NUM_LEDS; led++) { // La luminosite minimale d'une led est 10% de la luminosite max ledLuminosity = 0.1f; ledPosition = float(led) / float(NUM_LEDS);
// Pour chaque onde, on ajoute la luminosite a la led for (int wave = 0; wave < 10; wave++) { // Si l'onde n'est pas active ou si l'onde est avant la led, on n'ajoute aucune luminosite if (player2Waves[wave] == 0.0f || ledPosition > player2Waves[wave]) continue;
// On ajoute de la luminosite de facon decroissante. plus l'onde est loin, moins on ajoute de luminosite. ledLuminosity += max(0.0f, 0.9f - (player2Waves[wave] - ledPosition) / WAVE_LENGTH); } // La valeur maximale de luminosite est 1.0 if (ledLuminosity > 2.0f) ledLuminosity = 2.0f;
// On actualise la valeur de luminosite de la led ledColor(led, PLAYER2_COLOR / int(1.0f / ledLuminosity) / 5); }
// On actualise la led correspondant a la position de la corde ledColor(ropeLedPosition, BLANC); FastLED.show();
}
/****************************************************************
Cette fonction s'execute une fois lorsque la carte s'allume. ****************************************************************/
void setup() {
// Initialisation des LEDs FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
// Initialisations des boutons pinMode(BUTTON1_PIN, INPUT_PULLUP); pinMode(BUTTON2_PIN, INPUT_PULLUP);
// Initialisation du haut parleur pinMode(HAUT_PARLEUR_PIN, OUTPUT);
// COULEUR DES LEDS EN DEBUT DE PARTIE FastLED.clear(); // Couleurs player 1 ledColor(PLAYER1, 0, PLAYER1_COLOR); ledColor(PLAYER1, 1, PLAYER1_COLOR); ledColor(PLAYER1, 2, PLAYER1_COLOR); ledColor(PLAYER1, 3, PLAYER1_COLOR); ledColor(PLAYER1, 4, PLAYER1_COLOR);
// Couleurs player 2 ledColor(PLAYER2, 0, PLAYER2_COLOR); ledColor(PLAYER2, 1, PLAYER2_COLOR); ledColor(PLAYER2, 2, PLAYER2_COLOR); ledColor(PLAYER2, 3, PLAYER2_COLOR); ledColor(PLAYER2, 4, PLAYER2_COLOR);
// On envoie les changements a la bande de leds FastLED.show();
// Initialisation du temps d'allumage beginTimer = millis();
}
/*************************************************************
Cette fonction s'execute en continue tout au long du jeu. *************************************************************/
void loop() {
switch (gameState) { case START: // Si un player a gagne, on affiche l'arc en ciel du cote du vainqueur if (lastWinner == PLAYER1) { fill_rainbow(leds, NUM_LEDS / 2, counter++, 7); FastLED.show(); } else if (lastWinner == PLAYER2) { fill_rainbow(leds + NUM_LEDS / 2, NUM_LEDS / 2, counter++, 7); FastLED.show(); }
// On regarde si un temps minimim s'est ecoule et si un des boutons est appuye if (millis() - beginTimer > 1000 && (digitalRead(BUTTON1_PIN) == LOW || digitalRead(BUTTON2_PIN) == LOW)) { unsigned long pushBegin = millis();
while (digitalRead(BUTTON1_PIN) == LOW || digitalRead(BUTTON2_PIN) == LOW);
if (millis() - pushBegin < 1000) { gameState = PONG; } else { gameState = TAC; }
// On joue la note de musique tone(HAUT_PARLEUR_PIN, PONG_SOUND, 100);
// Initialisation de la varable lastMillis lastMillis = millis();
// Initialisation du temps de debut de jeu beginTimer = millis(); }
break;
case PONG: pong_loop(); break;
case TAC: tac_loop(); break; }
}
Étapes de fabrication
Voici toutes les étapes de fabrication de notre projet :
Étape 1
Tout d'abord on se rend compte du matériel qu'on nous donne et on regarde les différentes étapes à suivre sur le Wikidébrouillard
Étape 2
On soude des fils électriques au ruban de LEDS et sur les pattes des interrupteurs
Étape 2-1
En même temps, on construit le support sur lequel le jeu va être joué
Étape 3
On soude aussi les broches de support sur la carte Arduino
Étape 4
On réalise le câblage sur la plaquette qui nous a été fourni pour pouvoir tester le code
Étape 5
Puis on commence à mettre tous nos composants sur la maquette réelle
Étape 6
Ensuite, le jeu peut être utilisé !