ENIB 2024 : GNOP : Différence entre versions
(→Étape 14) |
|||
(62 révisions intermédiaires par 2 utilisateurs non affichées) | |||
Ligne 1 : | Ligne 1 : | ||
Titre de la fiche expérience : | Titre de la fiche expérience : | ||
− | == | + | ==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. | |
+ | <br/> | ||
+ | Voici notre équipe : | ||
+ | <br/> | ||
+ | Arthur : | ||
+ | [[Fichier:arthur.jpg|100px]] | ||
+ | Laouen : | ||
+ | [[Fichier:laouen.jpg|100px]] | ||
+ | Ewen 1 : | ||
+ | [[Fichier:ramzi.jpg|100px]] | ||
+ | Ewen 2 : (parti au combat) | ||
+ | [[Fichier:virgule.jpg|100px]] | ||
+ | Alban : (jamais vu) | ||
+ | [[Fichier:alban.jpg|100px]] | ||
− | [[ | + | ==Outil et matériel== |
+ | Pour fabriquer ce jeu, nous avons eut besoin de : | ||
+ | * Carte Arduino Nano | ||
+ | * 2 boutons d'arcade | ||
+ | * Carton | ||
+ | * Fils électriques | ||
+ | * Batterie externe | ||
+ | * Ruban de LEDS | ||
+ | * Haut-parleur | ||
+ | * Bois | ||
+ | <br/> | ||
+ | Nous nous sommes servis de plusieurs outils : | ||
+ | * Fer à souder | ||
+ | * Pistolet à colle | ||
+ | * Cutter | ||
+ | * Scie à bois | ||
+ | * Lime à bois | ||
+ | * Découpeuse Vinyle | ||
+ | |||
+ | ==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() { | 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() { | 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; | ||
+ | } | ||
} | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | La biblothèque FastLED est nécéssaire pour pouvoir faire fonctionner le programme. | ||
+ | <br/> | ||
+ | Pour l'installer il faut télécharger FastLED avec ce lien : https://github.com/FastLED/FastLED et le mettre dans le répertoire des bibliothèques d'Arduino. Et sur Arduino IDE avec celui-là : https://www.arduino.cc/en/main/software. | ||
+ | <br/> | ||
+ | Sur le ligociel, il faut chosir la bonne carte, le bon port de sortie et il suffit enfin de téléverser pour pouvoir charger le programme sur la carte. | ||
+ | <br/> | ||
+ | Et maintenant, pour pouvoir utiliser le jeu partout, il faut tout simplement utiliser une batterie (avec piles ou externe) et la brancher à la carte qui à été préalablement chargée avec le programme. | ||
+ | |||
+ | ==Étapes de fabrication== | ||
+ | Nous avons fait nos étapes dans cet ordre là car nous avons suivi les étapes dans le [[Wikidabrouillard]] | ||
+ | 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 | ||
+ | <br/> | ||
+ | [[Fichier:ruban_led.png|200px]] | ||
+ | [[Fichier:bouton.jpg|100px]] | ||
+ | |||
+ | ===É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 | ||
+ | <br/> | ||
+ | [[Fichier:Schema.png]] | ||
+ | |||
+ | ===Étape 5=== | ||
+ | Puis on commence à mettre tous nos composants sur la maquette réelle | ||
+ | <br/> | ||
+ | [[Fichier:board_pres.jpg|200px]] | ||
+ | |||
+ | ===Étape 6=== | ||
+ | Ensuite, le jeu peut être utilisé ! | ||
− | </ | + | ===Étape 7=== |
+ | On commence à créer notre produit final qui sera fait tout en bois | ||
+ | |||
+ | ===Étape 8=== | ||
+ | Pour cela, on va venir couper une planche en bois, et les chutes serviront à faire le maintien de la planche. | ||
+ | <br/> | ||
+ | [[Fichier:final.jpg|200px]] | ||
+ | |||
+ | ===Étape 9=== | ||
+ | Ensuite, on fait des trous pour faire passer les boutons d'arcade, vous pouvez le voir sur la photo ci-dessus. | ||
+ | |||
+ | ===Étape 10=== | ||
+ | On en fait un aussi pour faire passer les fils connectés au ruban de LEDS | ||
+ | |||
+ | ===Étape 11=== | ||
+ | On reconnecte tout le système sur notre maquette finale | ||
+ | |||
+ | ===Étape 12=== | ||
+ | On colle notre BreadBoard au dos de notre planche pour qu'elle ne soit pas vue | ||
+ | |||
+ | ===Étape 13=== | ||
+ | On colle aussi les câbles pour ne pas les vois tomber | ||
+ | |||
+ | ===Étape 14=== | ||
+ | Pour ajouter un peu d'esthétique à notre projet, nous avons gravé à la découpeuse vinyle le titre de notre projet.* | ||
+ | <br/> | ||
+ | [[Fichier:GNOP.jpg|200px]] | ||
− | == | + | ===Étape 15=== |
− | + | Le jeu peut être pleinement apprécié !! | |
− | == | + | ==Problèmes rencontrés== |
− | + | Nous avons confronté un certain nombre de problèmes durant la conception de ce projet. | |
− | + | <br/> | |
− | + | Une fois que nous avions fini le projet sur la première maquette, le téléversement ne se faisait pas, sur Arduino IDE, dans l'onglet Tools>Processor il fallait prendre la rubrique "Old Bootloader" et nous étions sur celui de base, mais si l'un ne marche pas c'est que l'autre fonctionne, nous avons donc réussi à résoudre ce problème. | |
− | + | <br/> | |
+ | Nous avons aussi également essayé d'incorporer un haut-parleur classique pour faire du son dès qu'un bouton est appuyé, mais le son n'était clairement pas assez fort donc on a voulu utilisé un amplificateur mais nous n'avons pas réussi à bien le brancher. On a donc opter d'utiliser un buzzer pour que le son soit plus fort pour être entendu. | ||
+ | <br/> | ||
+ | Une des broches de notre carte n'a plus été fonctionnel, nous avons mis du temps à comprendre qu'un de nos problèmes venait de là, on a donc tout simplement changer de broche. | ||
+ | <br/> | ||
+ | Nous utilisions au début, une batterie à pile, mais celle-ci ne délivrait pas assez de puissance pour faire fonctionner la carte et le programme, nous avons changé cette batterie et opter pour une batterie externe rechargeable qui, elle, convenait parfaitement avec le système. | ||
==Sources et documentation complémentaire== | ==Sources et documentation complémentaire== | ||
+ | [[Catégorie:Enib2024]] |
Version actuelle datée du 25 janvier 2024 à 15:25
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 :
Arthur :
Laouen :
Ewen 1 :
Ewen 2 : (parti au combat)
Alban : (jamais vu)
Outil et matériel
Pour fabriquer ce jeu, nous avons eut besoin de :
- Carte Arduino Nano
- 2 boutons d'arcade
- Carton
- Fils électriques
- Batterie externe
- Ruban de LEDS
- Haut-parleur
- Bois
Nous nous sommes servis de plusieurs outils :
- Fer à souder
- Pistolet à colle
- Cutter
- Scie à bois
- Lime à bois
- Découpeuse Vinyle
Code Arduino
1
2 /*
3 Code de fonctionnement pour le jeu PONG.
4 Par les petits debrouillards.
5 */
6
7 #include <FastLED.h>
8
9 // Definition des couleurs
10 const CRGB NOIR = CRGB(0, 0, 0 ); //Création d'une constante de type CRGB de couleur noire
11 const CRGB BLANC = CRGB(255, 255, 255); //Création d'une constante de type CRGB de couleur blanche
12 const CRGB ROUGE = CRGB(255, 0, 0 ); //Création d'une constante de type CRGB de couleur rouge
13 const CRGB VERT = CRGB(0, 255, 0 ); //Création d'une constante de type CRGB de couleur verte
14 const CRGB BLEU = CRGB(0, 0, 255); //Création d'une constante de type CRGB de couleur bleue
15 const CRGB JAUNE = CRGB(255, 255, 0 ); //Création d'une constante de type CRGB de couleur jaune
16 const CRGB ROSE = CRGB(255, 0, 255); //Création d'une constante de type CRGB de couleur rose
17 const CRGB CYAN = CRGB(0, 255, 255); //Création d'une constante de type CRGB de couleur cyan
18
19 // Definition des notes de musique
20 const int PONG_SOUND = 250; //380
21 const int LOOSE_SOUND = 180;
22
23
24 /******************************
25 PARAMETRES DE BRANCHEMENTS
26 ******************************/
27
28 const int LED_PIN = 8; // Numero de branchement de la bande de LEDs
29 const int BUTTON1_PIN = 2; // Numero de branchement du premier bouton
30 const int BUTTON2_PIN = 4; // Numero de branchement du deuxieme bouton
31 const int HAUT_PARLEUR_PIN = 5; // Numero de branchement du haut parleur (optionnel)
32
33
34 /***********************
35 PARAMETRES GENERAUX
36 ***********************/
37 const int NUM_LEDS = 60; // Nombre de LEDs sur la bande
38 const CRGB PLAYER1_COLOR = VERT; // Couleur Player 1
39 const CRGB PLAYER2_COLOR = ROUGE; // Couleur Player 2
40
41
42 /***********************
43 PARAMETRES PONG
44 ***********************/
45 const float BALL_SPEED = 0.5; // Vitesse de la balle
46 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
47 const int HIT_ZONE = 8; // Nombre de LED pendant lesquelles on peut renvoyer la balle
48 const int MAX_SCORE = 3; // Score maximum avant la fin du jeu
49
50 const CRGB BALL_COLOR = BLANC; // Couleur de la balle
51
52 /*******************************
53 PARAMETRES TIR A LA CORDE
54 *******************************/
55 const float INCREMENT = 0.05; // De combien avance la corde lorsqu'on appuie sur le bouton
56 const float ROPE_SMOOTH = 1.0; // Paramètre servant a lisser la position de la corde
57
58 const float WAVE_LENGTH = 0.2; // Taille des ondes
59 const float WAVE_SPEED = 1.0; // Vitesse des ondes
60
61
62
63 /******************************
64 VARIABLES GENERALES
65 ******************************/
66 // Players
67 enum Player
68 {
69 PERSONNE,
70 PLAYER1,
71 PLAYER2
72 };
73
74 // Etats du jeu
75 enum GameState
76 {
77 START,
78 PONG, // Mode pong
79 TAC // Mode tir a la corde
80 };
81
82 unsigned long lastMillis = 0;
83 unsigned long beginTimer = 0;
84 unsigned int counter = 0;
85
86 Player player = PLAYER1; // Prochain joueur a appuyer sur son bouton
87 Player lastWinner = PERSONNE;
88
89 CRGB leds[NUM_LEDS];
90 GameState gameState = START;
91
92
93 /**********************************************
94 FONCTIONS DE FONCTIONNEMENT GENERALES
95 **********************************************/
96
97 // Fonction permettant de changer la couleur d'une LED relativement au player 1 ou 2
98 void ledColor(Player player, int pos, CRGB color)
99 {
100 if (player == PLAYER1)
101 {
102 leds[pos] = color;
103 }
104 else // player == PLAYER2
105 {
106 leds[NUM_LEDS - pos - 1] = color;
107 }
108 }
109
110 // Fonction permettant de changer la couleur d'une LED
111 void ledColor(int pos, CRGB color)
112 {
113 leds[pos] = color;
114 }
115
116 /*********************************************
117 VARIABLES DE FONCTIONNEMENT DU PONG
118 *********************************************/
119 float ballSpeed = BALL_SPEED; // Vitesse de la balle
120 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)
121 int player1Score = 0; // Score du player 1
122 int player2Score = 0; // Score du player 2
123
124 /**********************************************
125 FONCTIONS DE FONCTIONNEMENT DU PONG
126 **********************************************/
127 // Fonction servant a afficher les scores
128 void showScore()
129 {
130 // On commence par effacer toutes les couleurs de led
131 FastLED.clear();
132
133 // On allume le nombre de led correspondant au score du player 1
134 for (int i = 0; i < player1Score; i++)
135 {
136 ledColor(PLAYER1, NUM_LEDS / 2 - (i + 1), PLAYER1_COLOR);
137 }
138
139 // On allume le nombre de led correspondant au score du player 2
140 for (int i = 0; i < player2Score; i++)
141 {
142 ledColor(PLAYER2, NUM_LEDS / 2 - (i + 1), PLAYER2_COLOR);
143 }
144
145 // On envoie les nouvelles couleurs a la bande de led
146 FastLED.show();
147
148 // On fait clignotter trois fois
149 if (lastWinner == PLAYER1)
150 {
151 for (int i = 0; i < 3; i++)
152 {
153 // On eteint la derniere LED pendant 0.5s
154 delay(500);
155 ledColor(PLAYER1, NUM_LEDS / 2 - player1Score, NOIR);
156 FastLED.show();
157
158 // On allume la derniere LED pendant 0.5s
159 delay(500);
160 ledColor(PLAYER1, NUM_LEDS / 2 - player1Score, PLAYER1_COLOR);
161 FastLED.show();
162 }
163 }
164 else // lastWinner == PLAYER2
165 {
166 for (int i = 0; i < 3; i++)
167 {
168 // On eteint la derniere LED pendant 0.5s
169 delay(500);
170 ledColor(PLAYER2, NUM_LEDS / 2 - player2Score, NOIR);
171 FastLED.show();
172
173 // On allume la derniere LED pendant 0.5s
174 delay(500);
175 ledColor(PLAYER2, NUM_LEDS / 2 - player2Score, PLAYER2_COLOR);
176 FastLED.show();
177 }
178 }
179
180 // Si la partie est terminee on va a l'affichage de fin
181 if (player1Score == MAX_SCORE || player2Score == MAX_SCORE)
182 {
183 gameState = START;
184
185 // On reinitialise les scores
186 player1Score = 0;
187 player2Score = 0;
188
189 // On reinitialise la vitesse
190 ballSpeed = BALL_SPEED;
191
192 // On reinitialise les leds
193 FastLED.clear();
194 }
195 // Sinon on reprend le jeu
196 else
197 {
198 gameState = PONG;
199 ballSpeed = BALL_SPEED;
200 }
201 }
202
203
204 /***************************************
205 FONCTION PRINCIPALE DU PONG
206 ***************************************/
207 void pong_loop()
208 {
209 // Calcul du temps ecoule entre deux boucles
210 unsigned long currentMillis = millis();
211
212 // On calcule le numero de la LED allumee
213 int ballLed = ballPosition * NUM_LEDS;
214
215 // On s'assure que la position de la balle ne depasse pas la taille de la bande de LED
216 ballLed = min(ballLed, NUM_LEDS - 1);
217
218 // On regarde qui est en train de jouer
219 if (player == PLAYER1)
220 {
221 // On regarde si le player a appuye sur son bouton et si le delai de debut de jeu est passe
222 if (digitalRead(BUTTON1_PIN) == LOW && currentMillis - beginTimer > 500)
223 {
224 // Si la balle est hors de la zone de tir, l'autre player marque un point
225 if (ballLed >= HIT_ZONE)
226 {
227 player2Score += 1;
228 lastWinner = PLAYER2;
229 ballPosition = 0;
230
231 // On joue le son de defaite
232 tone(HAUT_PARLEUR_PIN, LOOSE_SOUND, 800);
233
234 // On passe en mode affichage des scores
235 showScore();
236
237 // C'est a l'autre player de jouer
238 player = PLAYER2;
239
240 // Actualisation de la variable lastMillis
241 lastMillis = millis();
242 }
243 else
244 {
245 // On accelere la balle
246 ballSpeed *= 1.0 + ACCELERATION / 100;
247
248 // C'est a l'autre player de jouer
249 player = PLAYER2;
250
251 // On joue la note de musique
252 tone(HAUT_PARLEUR_PIN, PONG_SOUND, 100);
253 }
254
255 return;
256 }
257
258 // On fait avancer la balle
259 ballPosition -= ballSpeed * (currentMillis - lastMillis) * 0.001f;
260
261 // On regarde si la balle est sortie de la zone
262 if (ballPosition < 0.0f)
263 {
264 // Si oui le player 2 marque un point
265 player2Score += 1;
266 lastWinner = PLAYER2;
267 ballPosition = 0;
268
269 // On joue le son de defaite
270 tone(HAUT_PARLEUR_PIN, LOOSE_SOUND, 800);
271
272 // On passe en mode affichage des scores
273 showScore();
274
275 // C'est a l'autre player de jouer
276 player = PLAYER2;
277
278 // Actualisation de la variable lastMillis
279 lastMillis = millis();
280 return;
281 }
282 }
283 else // player == PLAYER2
284 {
285 // On regarde si le player a appuye sur son bouton et si le delai de debut de jeu est passe
286 if (digitalRead(BUTTON2_PIN) == LOW && currentMillis - beginTimer > 500)
287 {
288 // Si la balle est hors de la zone de tir, l'autre player marque un point
289 if (ballLed < NUM_LEDS - HIT_ZONE)
290 {
291 player1Score += 1;
292 lastWinner = PLAYER1;
293 ballPosition = 1;
294
295 // On joue le son de defaite
296 tone(HAUT_PARLEUR_PIN, LOOSE_SOUND, 800);
297
298 // On passe en mode affichage des scores
299 showScore();
300
301 // C'est a l'autre player de jouer
302 player = PLAYER1;
303
304 // Actualisation de la variable lastMillis
305 lastMillis = millis();
306 }
307 else
308 {
309 // On accelere la balle
310 ballSpeed *= 1.1;
311
312 // C'est a l'autre player de jouer
313 player = PLAYER1;
314
315 // On joue la note de musique
316 tone(HAUT_PARLEUR_PIN, PONG_SOUND, 100);
317 }
318
319 return;
320 }
321
322 // On fait avancer la balle dans l'autre sens
323 ballPosition += ballSpeed * (currentMillis - lastMillis) * 0.001f;
324
325 // On regarde si la balle est sortie de la zone
326 if (ballPosition >= 1)
327 {
328 // Si oui le player 1 marque un point
329 player1Score += 1;
330 lastWinner = PLAYER1;
331 ballPosition = 1;
332
333 // On joue le son de defaite
334 tone(HAUT_PARLEUR_PIN, LOOSE_SOUND, 800);
335
336 // On passe en mode affichage des scores
337 showScore();
338 // C'est a l'autre player de jouer
339 player = PLAYER1;
340
341 // Actualisation de la variable lastMillis
342 lastMillis = millis();
343 return;
344 }
345 }
346
347 ///// AFFICHAGE BANDE DE LEDs /////
348 // Premierement on efface toutes les couleurs precedentes
349 FastLED.clear();
350
351 // Ensuite on allume faiblement les LEDs correspondant a la zone de chaque cote
352 for (int i = 0; i < HIT_ZONE; i++)
353 {
354 // On allume de chaque cote
355 ledColor(PLAYER1, i, PLAYER1_COLOR / 10); // On divise la couleur par 10 pour la rendre 10 fois moins puissante
356 ledColor(PLAYER2, i, PLAYER2_COLOR / 10);
357 }
358
359 // Ensuite on allume faiblement les LEDs correspondant aux scores
360 // Pour le player 1
361 for (int i = 0; i < player1Score; i++)
362 {
363 ledColor(PLAYER1, NUM_LEDS / 2 - (i + 1), PLAYER1_COLOR / 15);
364 }
365 // Pour le player 2
366 for (int i = 0; i < player2Score; i++)
367 {
368 ledColor(PLAYER2, NUM_LEDS / 2 - (i + 1), PLAYER2_COLOR / 15);
369 }
370
371 // Ensuite on actualise la position de la balle
372 // On donne la couleur de la led en fonction de si la balle est dans la zone d'un player ou non
373
374 // Si la balle est dans le camp d'un des player, elle est rouge.
375 if (ballLed < HIT_ZONE || ballLed >= NUM_LEDS - HIT_ZONE)
376 {
377 ledColor(ballLed, ROUGE);
378 }
379 // Si elle en est proche, elle est jaune
380 else if (ballLed < 2 * HIT_ZONE || ballLed >= NUM_LEDS - 2 * HIT_ZONE)
381 {
382 ledColor(ballLed, JAUNE);
383 }
384 // Sinon la balle a sa couleur par defaut
385 else
386 {
387 ledColor(ballLed, BALL_COLOR);
388 }
389
390 // On envoie la couleur des leds a la bande de leds
391 FastLED.show();
392
393 // On actualise la variable lastMillis pour la boucle suivante
394 lastMillis = currentMillis;
395 }
396
397
398
399 /*******************************************************
400 VARIABLES DE FONCTIONNEMENT DU TIR A LA CORDE
401 *******************************************************/
402 float ropePosition = 0.5; // Position non lissee de la corde
403 float displayedRopePosition = 0.5; // Position lissee de la corde
404 bool player1Pushed = false;
405 bool player2Pushed = false;
406
407 float player1Waves[10] = { 0 };
408 float player2Waves[10] = { 0 };
409
410 /***********************************************
411 FONCTION PRINCIPALE DU TIR A LA CORDE
412 ***********************************************/
413 void tac_loop()
414 {
415 // Calcul des temps
416 unsigned long ms = millis();
417 float dt = (ms - lastMillis) * 0.001f;
418 lastMillis = ms;
419
420 // Si moins d'une seconde s'est ecoule depuis le debut, on ne fait rien (pour eviter d'appuyer sans faire expres)
421 if (ms - beginTimer < 1000)
422 return;
423
424 bool player1Push = !digitalRead(BUTTON1_PIN);
425 bool player2Push = !digitalRead(BUTTON2_PIN);
426
427 if (player1Push && !player1Pushed)
428 {
429 // On incremente la position de la corde
430 ropePosition += INCREMENT;
431
432 // On lance une nouvelle onde
433 for (int i = 0; i < 10; i++)
434 {
435 if (player1Waves[i] == 0.0f)
436 {
437 //player1Waves[i] = WAVE_SPEED * dt;
438 player1Waves[i] = 0.01f;
439 break;
440 }
441 }
442 }
443 if (player2Push && !player2Pushed)
444 {
445 // On incremente la position de la corde
446 ropePosition -= INCREMENT;
447
448 // On lance une nouvelle onde
449 for (int i = 0; i < 10; i++)
450 {
451 if (player2Waves[i] == 0.0f)
452 {
453 player2Waves[i] = 0.99f;
454 break;
455 }
456 }
457 }
458
459 // Memorisation des etats des boutons
460 player1Pushed = player1Push;
461 player2Pushed = player2Push;
462
463
464
465
466 // On calcule la position lissee de la corde (displayedRopePosition correspond a la variable ropePosition avec un lissage supplementaire)
467 displayedRopePosition += (ropePosition - displayedRopePosition) * dt / ROPE_SMOOTH;
468
469 // On regarde si player 1 a gagne
470 if (displayedRopePosition >= 1.0f)
471 {
472 lastWinner = PLAYER1;
473 gameState = START;
474 beginTimer = millis();
475
476 ropePosition = 0.5f;
477 displayedRopePosition = 0.5f;
478
479 FastLED.clear();
480 return;
481 }
482 // On regarde si player 2 a gagne
483 else if (displayedRopePosition <= 0.0f)
484 {
485 lastWinner = PLAYER2;
486 gameState = START;
487 beginTimer = millis();
488
489 ropePosition = 0.5f;
490 displayedRopePosition = 0.5f;
491
492 FastLED.clear();
493 return;
494 }
495
496 // On propage les ondes
497 float dx = WAVE_SPEED * dt;
498
499 for (int wave = 0; wave < 10; wave++)
500 {
501 // Ondes player 1
502 if (player1Waves[wave] != 0.0f)
503 {
504 player1Waves[wave] += dx;
505
506 // Si toute l'onde depasse le point de la corde, on l'arrete
507 if (player1Waves[wave] - WAVE_LENGTH > displayedRopePosition)
508 {
509 player1Waves[wave] = 0.0f;
510 }
511 }
512
513 // Ondes player 2
514 if (player2Waves[wave] != 0.0f)
515 {
516 player2Waves[wave] -= dx;
517
518 // Si toute l'onde depasse le point de la corde, on l'arrete
519 if (player2Waves[wave] + WAVE_LENGTH < displayedRopePosition)
520 {
521 player2Waves[wave] = 0.0f;
522 }
523 }
524 }
525
526 // On actualise la bande de leds
527 float ledLuminosity;
528 float ledPosition;
529
530 FastLED.clear();
531
532 // On commence par calculer le numero de la led correspondant a la position de la corde
533 int ropeLedPosition = NUM_LEDS * displayedRopePosition;
534
535 // On dessine la zone du player 1
536 // Pour cela on calcule la luminosite led par led
537 for (int led = 0; led < ropeLedPosition; led++)
538 {
539 // La luminosite minimale d'une led est 10% de la luminosite max
540 ledLuminosity = 0.1f;
541 ledPosition = float(led) / float(NUM_LEDS);
542
543 // Pour chaque onde, on ajoute la luminosite a la led
544 for (int wave = 0; wave < 10; wave++)
545 {
546 // Si l'onde n'est pas active ou si l'onde est avant la led, on n'ajoute aucune luminosite
547 if (player1Waves[wave] == 0.0f || player1Waves[wave] < ledPosition)
548 continue;
549
550 // On ajoute de la luminosite de facon decroissante. plus l'onde est loin, moins on ajoute de luminosite.
551 ledLuminosity += max(0.0f, 0.9f - (player1Waves[wave] - ledPosition) / WAVE_LENGTH);
552 }
553 // La valeur maximale de luminosite est 1.0
554 if (ledLuminosity > 2.0f)
555 ledLuminosity = 2.0f;
556
557 // On actualise la valeur de luminosite de la led
558 ledColor(led, PLAYER1_COLOR / int(2.0f / ledLuminosity) / 5);
559 }
560
561 // On dessine la zone du player 2
562 for (int led = ropeLedPosition + 1; led < NUM_LEDS; led++)
563 {
564 // La luminosite minimale d'une led est 10% de la luminosite max
565 ledLuminosity = 0.1f;
566 ledPosition = float(led) / float(NUM_LEDS);
567
568 // Pour chaque onde, on ajoute la luminosite a la led
569 for (int wave = 0; wave < 10; wave++)
570 {
571 // Si l'onde n'est pas active ou si l'onde est avant la led, on n'ajoute aucune luminosite
572 if (player2Waves[wave] == 0.0f || ledPosition > player2Waves[wave])
573 continue;
574
575 // On ajoute de la luminosite de facon decroissante. plus l'onde est loin, moins on ajoute de luminosite.
576 ledLuminosity += max(0.0f, 0.9f - (player2Waves[wave] - ledPosition) / WAVE_LENGTH);
577 }
578 // La valeur maximale de luminosite est 1.0
579 if (ledLuminosity > 2.0f)
580 ledLuminosity = 2.0f;
581
582 // On actualise la valeur de luminosite de la led
583 ledColor(led, PLAYER2_COLOR / int(1.0f / ledLuminosity) / 5);
584 }
585
586 // On actualise la led correspondant a la position de la corde
587 ledColor(ropeLedPosition, BLANC);
588 FastLED.show();
589 }
590
591
592
593 /****************************************************************
594 Cette fonction s'execute une fois lorsque la carte s'allume.
595 ****************************************************************/
596 void setup() {
597 // Initialisation des LEDs
598 FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
599
600 // Initialisations des boutons
601 pinMode(BUTTON1_PIN, INPUT_PULLUP);
602 pinMode(BUTTON2_PIN, INPUT_PULLUP);
603
604 // Initialisation du haut parleur
605 pinMode(HAUT_PARLEUR_PIN, OUTPUT);
606
607 // COULEUR DES LEDS EN DEBUT DE PARTIE
608 FastLED.clear();
609 // Couleurs player 1
610 ledColor(PLAYER1, 0, PLAYER1_COLOR);
611 ledColor(PLAYER1, 1, PLAYER1_COLOR);
612 ledColor(PLAYER1, 2, PLAYER1_COLOR);
613 ledColor(PLAYER1, 3, PLAYER1_COLOR);
614 ledColor(PLAYER1, 4, PLAYER1_COLOR);
615
616 // Couleurs player 2
617 ledColor(PLAYER2, 0, PLAYER2_COLOR);
618 ledColor(PLAYER2, 1, PLAYER2_COLOR);
619 ledColor(PLAYER2, 2, PLAYER2_COLOR);
620 ledColor(PLAYER2, 3, PLAYER2_COLOR);
621 ledColor(PLAYER2, 4, PLAYER2_COLOR);
622
623 // On envoie les changements a la bande de leds
624 FastLED.show();
625
626 // Initialisation du temps d'allumage
627 beginTimer = millis();
628 }
629
630 /*************************************************************
631 Cette fonction s'execute en continue tout au long du jeu.
632 *************************************************************/
633 void loop() {
634
635 switch (gameState)
636 {
637 case START:
638 // Si un player a gagne, on affiche l'arc en ciel du cote du vainqueur
639 if (lastWinner == PLAYER1)
640 {
641 fill_rainbow(leds, NUM_LEDS / 2, counter++, 7);
642 FastLED.show();
643 }
644 else if (lastWinner == PLAYER2)
645 {
646 fill_rainbow(leds + NUM_LEDS / 2, NUM_LEDS / 2, counter++, 7);
647 FastLED.show();
648 }
649
650 // On regarde si un temps minimim s'est ecoule et si un des boutons est appuye
651 if (millis() - beginTimer > 1000 && (digitalRead(BUTTON1_PIN) == LOW || digitalRead(BUTTON2_PIN) == LOW))
652 {
653 unsigned long pushBegin = millis();
654
655 while (digitalRead(BUTTON1_PIN) == LOW || digitalRead(BUTTON2_PIN) == LOW);
656
657 if (millis() - pushBegin < 1000)
658 {
659 gameState = PONG;
660 }
661 else
662 {
663 gameState = TAC;
664 }
665
666 // On joue la note de musique
667 tone(HAUT_PARLEUR_PIN, PONG_SOUND, 100);
668
669 // Initialisation de la varable lastMillis
670 lastMillis = millis();
671
672 // Initialisation du temps de debut de jeu
673 beginTimer = millis();
674 }
675
676 break;
677
678 case PONG:
679 pong_loop();
680 break;
681
682 case TAC:
683 tac_loop();
684 break;
685 }
686 }
La biblothèque FastLED est nécéssaire pour pouvoir faire fonctionner le programme.
Pour l'installer il faut télécharger FastLED avec ce lien : https://github.com/FastLED/FastLED et le mettre dans le répertoire des bibliothèques d'Arduino. Et sur Arduino IDE avec celui-là : https://www.arduino.cc/en/main/software.
Sur le ligociel, il faut chosir la bonne carte, le bon port de sortie et il suffit enfin de téléverser pour pouvoir charger le programme sur la carte.
Et maintenant, pour pouvoir utiliser le jeu partout, il faut tout simplement utiliser une batterie (avec piles ou externe) et la brancher à la carte qui à été préalablement chargée avec le programme.
Étapes de fabrication
Nous avons fait nos étapes dans cet ordre là car nous avons suivi les étapes dans le Wikidabrouillard 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é !
Étape 7
On commence à créer notre produit final qui sera fait tout en bois
Étape 8
Pour cela, on va venir couper une planche en bois, et les chutes serviront à faire le maintien de la planche.
Étape 9
Ensuite, on fait des trous pour faire passer les boutons d'arcade, vous pouvez le voir sur la photo ci-dessus.
Étape 10
On en fait un aussi pour faire passer les fils connectés au ruban de LEDS
Étape 11
On reconnecte tout le système sur notre maquette finale
Étape 12
On colle notre BreadBoard au dos de notre planche pour qu'elle ne soit pas vue
Étape 13
On colle aussi les câbles pour ne pas les vois tomber
Étape 14
Pour ajouter un peu d'esthétique à notre projet, nous avons gravé à la découpeuse vinyle le titre de notre projet.*
Étape 15
Le jeu peut être pleinement apprécié !!
Problèmes rencontrés
Nous avons confronté un certain nombre de problèmes durant la conception de ce projet.
Une fois que nous avions fini le projet sur la première maquette, le téléversement ne se faisait pas, sur Arduino IDE, dans l'onglet Tools>Processor il fallait prendre la rubrique "Old Bootloader" et nous étions sur celui de base, mais si l'un ne marche pas c'est que l'autre fonctionne, nous avons donc réussi à résoudre ce problème.
Nous avons aussi également essayé d'incorporer un haut-parleur classique pour faire du son dès qu'un bouton est appuyé, mais le son n'était clairement pas assez fort donc on a voulu utilisé un amplificateur mais nous n'avons pas réussi à bien le brancher. On a donc opter d'utiliser un buzzer pour que le son soit plus fort pour être entendu.
Une des broches de notre carte n'a plus été fonctionnel, nous avons mis du temps à comprendre qu'un de nos problèmes venait de là, on a donc tout simplement changer de broche.
Nous utilisions au début, une batterie à pile, mais celle-ci ne délivrait pas assez de puissance pour faire fonctionner la carte et le programme, nous avons changé cette batterie et opter pour une batterie externe rechargeable qui, elle, convenait parfaitement avec le système.