ENIB 2024 : CatchTheJackpot : Différence entre versions
(→Outils) |
(→Code :) |
||
Ligne 42 : | Ligne 42 : | ||
code, ficher d'impression 3D, de découpe laser ou vinyle, ... | code, ficher d'impression 3D, de découpe laser ou vinyle, ... | ||
− | + | ==Code :== | |
− | + | ||
+ | //Programme fait sur carte STM8266 / WEMOS D1 mini | ||
+ | #include "pitches.h" | ||
#include "FastLED.h" //bibliothèque pour controler le ruban led | #include "FastLED.h" //bibliothèque pour controler le ruban led | ||
+ | #include <Wire.h> //bibliothèque écran | ||
+ | #include <LiquidCrystal_I2C.h> //bibliothèque écran | ||
+ | #define REST 0 | ||
#define NUM_LEDS 86 | #define NUM_LEDS 86 | ||
#define NUM_OF_LEDS_BY_LEVEL 17 // nombre de leds par niveau | #define NUM_OF_LEDS_BY_LEVEL 17 // nombre de leds par niveau | ||
#define NUM_OF_LEVELS 5 // nombre de niveaux | #define NUM_OF_LEVELS 5 // nombre de niveaux | ||
− | #define PIN_BTN | + | #define PIN_BTN D3 // Entree du bouton |
− | #define PIN_LEDS | + | #define PIN_LEDS D4 // Sortie du ruban led |
+ | #define PIN_BUZZER D8 // Signal de sortie buzzer | ||
− | |||
− | CRGB leds[NUM_LEDS]; | + | // -------- INIT VARIABLES -------- |
+ | LiquidCrystal_I2C lcd(0x27, 16, 2); | ||
+ | CRGB leds[NUM_LEDS]; //Création d'une liste avec chaque led | ||
+ | CRGB randomcolor = CHSV(random(192), 255, 255); | ||
int level = 0; // niveau auquel le joueur est | int level = 0; // niveau auquel le joueur est | ||
int delay_level = 30; // délai qui permet de controler la vitesse de déplacement de la led | int delay_level = 30; // délai qui permet de controler la vitesse de déplacement de la led | ||
− | auto color = CRGB:: | + | auto color = CRGB::Blue; // couleur de la led qui se déplace |
− | int score = 0; // | + | int score = 0; // score du joueur |
− | const double coef[] = {1, 1. | + | const double coef[] = {1,1.5,2,2.5,3}; // coefficient multiplicateur de point par niveau |
− | int last_point | + | int last_point[NUM_OF_LEVELS]; // sauvegarde de la derniere led allumée pour la rallumer après flash() |
+ | bool game_in_progress = false; | ||
+ | int last_point_visu = 0; | ||
+ | |||
+ | |||
+ | // -------- INIT FONCTIONS -------- | ||
− | + | int move(); // déplacement de la led | |
− | int | ||
− | |||
− | |||
void level_up(); // passage de niveau | void level_up(); // passage de niveau | ||
+ | void waiting_start_game(); //affichage d'attente de début du jeu | ||
void flash(); // animation de victoire d'un niveau | void flash(); // animation de victoire d'un niveau | ||
− | + | // -------- PROGRAMME -------- | |
void setup() { | void setup() { | ||
− | FastLED.addLeds<NEOPIXEL, | + | FastLED.addLeds<NEOPIXEL, D4>(leds, NUM_LEDS); // setup du ruban de led sur la sortie PIN_LEDS => 2 |
pinMode(PIN_BTN, INPUT); // setup du bouton dur l'entrée PIN_BTN => 3 | pinMode(PIN_BTN, INPUT); // setup du bouton dur l'entrée PIN_BTN => 3 | ||
− | Serial.begin(9600); // setup moniteur série pour debug | + | FastLED.setBrightness(50); // setup de la luminosité |
+ | Serial.begin(9600); // setup moniteur série pour debug | ||
+ | int last_point[NUM_OF_LEVELS]; | ||
+ | pinMode(PIN_BUZZER, OUTPUT); | ||
+ | |||
+ | // -------- ECRAN -------- | ||
+ | lcd.init(); // Initialize I2C LCD module | ||
+ | lcd.backlight(); // Turn backlight ON | ||
} | } | ||
+ | |||
void loop() { | void loop() { | ||
− | + | waiting_start_game(); | |
− | + | lcd.setCursor(0,0); | |
− | if ( | + | lcd.print(" Cliquer "); |
− | + | lcd.setCursor(0,1); | |
− | + | lcd.print(" pour commencer"); | |
− | + | FastLED.clear(); | |
− | + | if (digitalRead(PIN_BTN)==LOW){ | |
− | + | musique(); | |
− | + | game_in_progress = true; | |
− | + | lcd.clear(); | |
− | + | lcd.setCursor(0,0); | |
+ | lcd.print("Partie en cours !"); | ||
+ | lcd.setCursor(0,1); | ||
+ | lcd.print("XoXoXoXoXoXoXoXo"); | ||
+ | FastLED.clear(); | ||
+ | delay(400); | ||
+ | while(game_in_progress){ | ||
+ | move(); | ||
+ | if (digitalRead(PIN_BTN)==LOW && game_in_progress==true){ | ||
+ | level_up(); | ||
+ | } | ||
+ | } | ||
} | } | ||
− | |||
− | |||
} | } | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | int | + | int move(){ |
− | + | // Permet de faire bouger la LED de gauche à droite | |
− | for (int i = NUM_OF_LEDS_BY_LEVEL * level; i <= (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1); i++) | + | for (int i = NUM_OF_LEDS_BY_LEVEL * level; i <= (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1); i++){ |
− | + | // -------- DEBUGGING -------- // | |
− | if (digitalRead(PIN_BTN)) // | + | /* |
− | { | + | Serial.print("val de la led: "); |
− | + | Serial.print(i); | |
− | { | + | Serial.print("\n"); |
− | + | */ | |
+ | if (digitalRead(PIN_BTN)==LOW){ //Stock des scores LEDs 1 -> 9 -> 1 | ||
+ | int center = abs(i - (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL / 2)); | ||
+ | if (center <= NUM_OF_LEDS_BY_LEVEL/2) { | ||
+ | last_point[level] = NUM_OF_LEDS_BY_LEVEL/2 - center + 1; // Les points augmentent jusqu'à 9 | ||
+ | } else { | ||
+ | last_point[level] = 0; // À partir de la position 9, les points diminuent | ||
+ | } | ||
+ | // if(i<(1/2*NUM_OF_LEDS_BY_LEVEL)){ | ||
+ | // last_point[level] = i; | ||
+ | // } | ||
+ | // else{ | ||
+ | // for(int degr = 1; degr<NUM_OF_LEDS_BY_LEVEL; degr++) | ||
+ | // last_point[level] = (i - degr); | ||
+ | |||
+ | // } | ||
+ | int last_point_visu = i-1; | ||
+ | return i-1; | ||
+ | // -------- DEBUGGING -------- // | ||
+ | /* | ||
+ | Serial.print("last_point_visu"); | ||
+ | Serial.print(last_point_visu); | ||
+ | |||
+ | for(int z=0; z<NUM_OF_LEVELS; z++){ | ||
+ | Serial.print(last_point[z]); | ||
+ | Serial.print("\n"); | ||
} | } | ||
− | + | */ | |
− | + | ||
+ | |||
} | } | ||
+ | //Eteins les LEDs derrière la LED mouvante | ||
leds[i - 1] = CRGB::Black; | leds[i - 1] = CRGB::Black; | ||
delay(3); | delay(3); | ||
− | + | leds[level * NUM_OF_LEDS_BY_LEVEL + NUM_OF_LEDS_BY_LEVEL / 2] = CRGB::Yellow; | |
− | leds[level * NUM_OF_LEDS_BY_LEVEL + NUM_OF_LEDS_BY_LEVEL / 2] = CRGB:: | ||
leds[i] = color; | leds[i] = color; | ||
− | |||
FastLED.show(); | FastLED.show(); | ||
delay(delay_level); | delay(delay_level); | ||
Ligne 124 : | Ligne 172 : | ||
FastLED.show(); | FastLED.show(); | ||
delay(delay_level); | delay(delay_level); | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
for (int i = NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1; i >= NUM_OF_LEDS_BY_LEVEL * level ; i--) | for (int i = NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1; i >= NUM_OF_LEDS_BY_LEVEL * level ; i--) | ||
{ | { | ||
− | if (digitalRead(PIN_BTN)) | + | // -------- DEBUGGING -------- // |
− | + | /* | |
− | + | Serial.print("val de la led: "); | |
− | { | + | Serial.print(i); |
− | + | Serial.print("\n"); | |
+ | */ | ||
+ | if (digitalRead(PIN_BTN)==LOW){ //Stock des scores LEDs 1 -> 9 -> 1 | ||
+ | int center = abs(i - (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL / 2)); | ||
+ | if (center <= NUM_OF_LEDS_BY_LEVEL/2) { | ||
+ | last_point[level] = NUM_OF_LEDS_BY_LEVEL/2 - center + 1; // Les points augmentent jusqu'à 9 | ||
+ | } else { | ||
+ | last_point[level] = 0; // À partir de la position 9, les points diminuent | ||
+ | } | ||
+ | // if(i<(1/2*NUM_OF_LEDS_BY_LEVEL)){ | ||
+ | // last_point[level] = i; | ||
+ | // } | ||
+ | // else{ | ||
+ | // for(int degr = 1; degr<NUM_OF_LEDS_BY_LEVEL; degr++) | ||
+ | // last_point[level] = (i - degr); | ||
+ | // } | ||
+ | |||
+ | int last_point_visu = i+1; | ||
+ | return i+1; | ||
+ | |||
+ | // -------- DEBUGGING -------- // | ||
+ | /* | ||
+ | Serial.print("last_point_visu"); | ||
+ | Serial.print(last_point_visu); | ||
+ | |||
+ | for(int z=0; z<NUM_OF_LEVELS; z++){ | ||
+ | Serial.print(last_point[z]); | ||
+ | Serial.print("\n"); | ||
} | } | ||
− | + | */ | |
− | + | ||
} | } | ||
+ | //Eteins les LEDs derrière la LED mouvante | ||
leds[i + 1] = CRGB::Black; | leds[i + 1] = CRGB::Black; | ||
delay(3); | delay(3); | ||
− | + | leds[level * NUM_OF_LEDS_BY_LEVEL + NUM_OF_LEDS_BY_LEVEL / 2] = CRGB::Yellow; | |
− | leds[level * NUM_OF_LEDS_BY_LEVEL + NUM_OF_LEDS_BY_LEVEL / 2] = CRGB:: | ||
leds[i] = color; | leds[i] = color; | ||
− | |||
FastLED.show(); | FastLED.show(); | ||
delay(delay_level); | delay(delay_level); | ||
} | } | ||
− | + | leds[NUM_OF_LEDS_BY_LEVEL] = CRGB::Black; | |
− | + | FastLED.show(); | |
− | + | delay(delay_level); | |
return 0; | return 0; | ||
+ | } | ||
− | |||
− | |||
void flash() // fonction de décoration qui fait clignoter les leds en blanc avant le passage de niveau | void flash() // fonction de décoration qui fait clignoter les leds en blanc avant le passage de niveau | ||
{ | { | ||
Ligne 164 : | Ligne 230 : | ||
for (int i = NUM_OF_LEDS_BY_LEVEL * level; i <= (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1); i++) // On met toute les leds du niveau en blanc | for (int i = NUM_OF_LEDS_BY_LEVEL * level; i <= (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1); i++) // On met toute les leds du niveau en blanc | ||
{ | { | ||
− | leds[i] = CRGB:: | + | leds[i] = CRGB::Green; |
} | } | ||
FastLED.show(); | FastLED.show(); | ||
− | |||
delay(100); | delay(100); | ||
for (int i = NUM_OF_LEDS_BY_LEVEL * level; i <= (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1); i++) // On éteint toutes les leds du niveau | for (int i = NUM_OF_LEDS_BY_LEVEL * level; i <= (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1); i++) // On éteint toutes les leds du niveau | ||
Ligne 176 : | Ligne 241 : | ||
delay(100); | delay(100); | ||
} | } | ||
− | leds[ | + | leds[last_point_visu] = CRGB::Purple; |
} | } | ||
− | void | + | void level_up() // changement de niveau |
{ | { | ||
− | + | flash(); // animation | |
+ | level++; // incrémentation de la variable niveau | ||
+ | delay_level -= 4; // le jeu devient de plus en plus rapide | ||
+ | |||
+ | if (level >= NUM_OF_LEVELS) // fin du jeu | ||
{ | { | ||
− | + | compute_score(); //Calcul le score | |
+ | show_score(); //Affiche le score sur un écran à crystaux liquides | ||
− | + | //Remise des valeurs pas défaut | |
− | + | level = 0; | |
+ | score = 0; | ||
+ | delay_level = 30; | ||
+ | game_in_progress = false; | ||
+ | for(int w=0; w<NUM_OF_LEVELS;w++){ | ||
+ | last_point[w] = 0; | ||
+ | } | ||
} | } | ||
} | } | ||
− | void | + | void waiting_start_game(){ |
− | + | // Allume toutes les LEDs en bleu avant de faire commencer la partie | |
− | for (int | + | for (int w = 0; w < NUM_LEDS; w++){ |
− | + | leds[w] = CRGB::Blue; | |
− | leds[ | ||
− | |||
} | } | ||
FastLED.show(); | FastLED.show(); | ||
} | } | ||
− | + | int compute_score(){ | |
− | + | // Récupere les élements du tableau last_point et les additionnes | |
− | + | for (int i = 0; i<NUM_OF_LEVELS; i++){ | |
− | { | + | if (i > 2) { |
− | + | // Pour les niveaux 4 et 5, le score est diviser par deux | |
− | + | score += last_point[i] / 2; | |
− | + | } else { | |
+ | score += last_point[i]; | ||
} | } | ||
− | + | } | |
+ | // -------- DEBUGGING -------- // | ||
+ | /* | ||
+ | Serial.print("Score : "); | ||
+ | Serial.println(score); | ||
+ | */ | ||
+ | return score; | ||
+ | } | ||
+ | |||
+ | int show_score(){ | ||
+ | lcd.clear(); | ||
+ | lcd.setCursor(0,0); | ||
+ | lcd.print(" Score : "); | ||
+ | lcd.print(score); | ||
+ | lcd.setCursor(0,1); | ||
+ | lcd.print(" Bien joue !!"); // Je ne sais pas comment mettre des caractères speciaux (hors ASCII 128) | ||
+ | delay(5000); | ||
+ | lcd.clear(); | ||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | // ----- MUSIQUE ----- // | ||
+ | |||
+ | int melody[] = { | ||
+ | |||
+ | //Based on the arrangement at https://www.flutetunes.com/tunes.php?id=169 | ||
+ | |||
+ | NOTE_AS4,-2, NOTE_F4,8, NOTE_F4,8, NOTE_AS4,8,//1 | ||
+ | NOTE_GS4,16, NOTE_FS4,16, NOTE_GS4,-2, | ||
+ | NOTE_AS4,-2, NOTE_FS4,8, NOTE_FS4,8, NOTE_AS4,8, | ||
+ | NOTE_A4,16, NOTE_G4,16, NOTE_A4,-2, | ||
+ | REST,1, | ||
+ | |||
+ | NOTE_AS4,4, NOTE_F4,-4, NOTE_AS4,8, NOTE_AS4,16, NOTE_C5,16, NOTE_D5,16, NOTE_DS5,16,//7 | ||
+ | NOTE_F5,2, NOTE_F5,8, NOTE_F5,8, NOTE_F5,8, NOTE_FS5,16, NOTE_GS5,16, | ||
+ | NOTE_AS5,-2, NOTE_AS5,8, NOTE_AS5,8, NOTE_GS5,8, NOTE_FS5,16, | ||
+ | NOTE_GS5,-8, NOTE_FS5,16, NOTE_F5,2, NOTE_F5,4, | ||
+ | |||
+ | NOTE_DS5,-8, NOTE_F5,16, NOTE_FS5,2, NOTE_F5,8, NOTE_DS5,8, //11 | ||
+ | NOTE_CS5,-8, NOTE_DS5,16, NOTE_F5,2, NOTE_DS5,8, NOTE_CS5,8, | ||
+ | NOTE_C5,-8, NOTE_D5,16, NOTE_E5,2, NOTE_G5,8, | ||
+ | NOTE_F5,16, NOTE_F4,16, NOTE_F4,16, NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,8, NOTE_F4,16,NOTE_F4,8, | ||
+ | |||
+ | NOTE_AS4,4, NOTE_F4,-4, NOTE_AS4,8, NOTE_AS4,16, NOTE_C5,16, NOTE_D5,16, NOTE_DS5,16,//15 | ||
+ | NOTE_F5,2, NOTE_F5,8, NOTE_F5,8, NOTE_F5,8, NOTE_FS5,16, NOTE_GS5,16, | ||
+ | NOTE_AS5,-2, NOTE_CS6,4, | ||
+ | NOTE_C6,4, NOTE_A5,2, NOTE_F5,4, | ||
+ | NOTE_FS5,-2, NOTE_AS5,4, | ||
+ | NOTE_A5,4, NOTE_F5,2, NOTE_F5,4, | ||
+ | |||
+ | NOTE_FS5,-2, NOTE_AS5,4, | ||
+ | NOTE_A5,4, NOTE_F5,2, NOTE_D5,4, | ||
+ | NOTE_DS5,-2, NOTE_FS5,4, | ||
+ | NOTE_F5,4, NOTE_CS5,2, NOTE_AS4,4, | ||
+ | NOTE_C5,-8, NOTE_D5,16, NOTE_E5,2, NOTE_G5,8, | ||
+ | NOTE_F5,16, NOTE_F4,16, NOTE_F4,16, NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,8, NOTE_F4,16,NOTE_F4,8 | ||
+ | |||
+ | }; | ||
+ | |||
+ | void musique(){ | ||
+ | int tempo = 60; | ||
+ | // sizeof gives the number of bytes, each int value is composed of two bytes (16 bits) | ||
+ | // there are two values per note (pitch and duration), so for each note there are four bytes | ||
+ | int notes = sizeof(melody) / sizeof(melody[0]) / 2; | ||
+ | |||
+ | // this calculates the duration of a whole note in ms | ||
+ | int wholenote = (60000 * 2) / tempo; | ||
− | + | int divider = 0, noteDuration = 0; | |
− | + | // iterate over the notes of the melody. | |
− | + | // Remember, the array is twice the number of notes (notes + durations) | |
− | + | for (int thisNote = 0; thisNote < notes * 2; thisNote = thisNote + 2) { | |
− | + | ||
− | + | // calculates the duration of each note | |
− | + | divider = melody[thisNote + 1]; | |
− | + | if (divider > 0) { | |
− | + | // regular note, just proceed | |
− | + | noteDuration = (wholenote) / divider; | |
− | + | } else if (divider < 0) { | |
− | + | // dotted notes are represented with negative durations!! | |
− | + | noteDuration = (wholenote) / abs(divider); | |
− | + | noteDuration *= 1.5; // increases the duration in half for dotted notes | |
− | |||
− | |||
} | } | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
+ | // we only play the note for 90% of the duration, leaving 10% as a pause | ||
+ | tone(PIN_BUZZER, melody[thisNote], noteDuration*0.9); | ||
+ | // Wait for the specief duration before playing the next note. | ||
+ | delay(noteDuration); | ||
+ | |||
+ | // stop the waveform generation before the next note. | ||
+ | noTone(PIN_BUZZER); | ||
} | } | ||
− | |||
− | |||
} | } | ||
− | |||
==étapes de fabrication== | ==étapes de fabrication== |
Version du 31 janvier 2024 à 11:36
Sommaire
description
Ce projet fonction grâce à une carte Arduino, des LEDs et un bouton.
Une lumière traverse le ruban de gauche à droite et lorsqu'elle est au milieu, il faut appuyer sur le bouton au bon moment pour gagner.
réalisé par :
-Arnaud Genty -Maxime Bintein -Tristan Le Coz
Introduction
éventuelle vidéo
Liste des composants
- Bouton poussoir style Arcade
- Arduino nano
- 2 rubans de LED adressable (85 LEDs pour être exacte)
- Carton
- Bois
- Câbles mini-USB
- Câbles
- écran LCD
- Breadboard
- 2 résistances de 500kΩ
Outils
- Cutter
- Marqueur noir
- Pistolet à colle
- Scotch
- Fer à souder
- Scie à bois
- Perceuse
- Bibliothèque Arduino FastLed
https://fastled.io/
fichiers à joindre
code, ficher d'impression 3D, de découpe laser ou vinyle, ...
Code :
//Programme fait sur carte STM8266 / WEMOS D1 mini
- include "pitches.h"
- include "FastLED.h" //bibliothèque pour controler le ruban led
- include <Wire.h> //bibliothèque écran
- include <LiquidCrystal_I2C.h> //bibliothèque écran
- define REST 0
- define NUM_LEDS 86
- define NUM_OF_LEDS_BY_LEVEL 17 // nombre de leds par niveau
- define NUM_OF_LEVELS 5 // nombre de niveaux
- define PIN_BTN D3 // Entree du bouton
- define PIN_LEDS D4 // Sortie du ruban led
- define PIN_BUZZER D8 // Signal de sortie buzzer
// -------- INIT VARIABLES --------
LiquidCrystal_I2C lcd(0x27, 16, 2);
CRGB leds[NUM_LEDS]; //Création d'une liste avec chaque led
CRGB randomcolor = CHSV(random(192), 255, 255);
int level = 0; // niveau auquel le joueur est
int delay_level = 30; // délai qui permet de controler la vitesse de déplacement de la led
auto color = CRGB::Blue; // couleur de la led qui se déplace
int score = 0; // score du joueur
const double coef[] = {1,1.5,2,2.5,3}; // coefficient multiplicateur de point par niveau
int last_point[NUM_OF_LEVELS]; // sauvegarde de la derniere led allumée pour la rallumer après flash()
bool game_in_progress = false;
int last_point_visu = 0;
// -------- INIT FONCTIONS --------
int move(); // déplacement de la led void level_up(); // passage de niveau void waiting_start_game(); //affichage d'attente de début du jeu void flash(); // animation de victoire d'un niveau
// -------- PROGRAMME -------- void setup() {
FastLED.addLeds<NEOPIXEL, D4>(leds, NUM_LEDS); // setup du ruban de led sur la sortie PIN_LEDS => 2 pinMode(PIN_BTN, INPUT); // setup du bouton dur l'entrée PIN_BTN => 3 FastLED.setBrightness(50); // setup de la luminosité Serial.begin(9600); // setup moniteur série pour debug int last_point[NUM_OF_LEVELS]; pinMode(PIN_BUZZER, OUTPUT);
// -------- ECRAN -------- lcd.init(); // Initialize I2C LCD module lcd.backlight(); // Turn backlight ON
}
void loop() {
waiting_start_game(); lcd.setCursor(0,0); lcd.print(" Cliquer "); lcd.setCursor(0,1); lcd.print(" pour commencer"); FastLED.clear(); if (digitalRead(PIN_BTN)==LOW){ musique(); game_in_progress = true; lcd.clear(); lcd.setCursor(0,0); lcd.print("Partie en cours !"); lcd.setCursor(0,1); lcd.print("XoXoXoXoXoXoXoXo"); FastLED.clear(); delay(400); while(game_in_progress){ move(); if (digitalRead(PIN_BTN)==LOW && game_in_progress==true){ level_up(); } } }
}
int move(){
// Permet de faire bouger la LED de gauche à droite for (int i = NUM_OF_LEDS_BY_LEVEL * level; i <= (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1); i++){ // -------- DEBUGGING -------- // /* Serial.print("val de la led: "); Serial.print(i); Serial.print("\n"); */ if (digitalRead(PIN_BTN)==LOW){ //Stock des scores LEDs 1 -> 9 -> 1 int center = abs(i - (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL / 2)); if (center <= NUM_OF_LEDS_BY_LEVEL/2) { last_point[level] = NUM_OF_LEDS_BY_LEVEL/2 - center + 1; // Les points augmentent jusqu'à 9 } else { last_point[level] = 0; // À partir de la position 9, les points diminuent } // if(i<(1/2*NUM_OF_LEDS_BY_LEVEL)){ // last_point[level] = i; // } // else{ // for(int degr = 1; degr<NUM_OF_LEDS_BY_LEVEL; degr++) // last_point[level] = (i - degr); // } int last_point_visu = i-1; return i-1; // -------- DEBUGGING -------- // /* Serial.print("last_point_visu"); Serial.print(last_point_visu); for(int z=0; z<NUM_OF_LEVELS; z++){ Serial.print(last_point[z]); Serial.print("\n"); } */ } //Eteins les LEDs derrière la LED mouvante leds[i - 1] = CRGB::Black; delay(3); leds[level * NUM_OF_LEDS_BY_LEVEL + NUM_OF_LEDS_BY_LEVEL / 2] = CRGB::Yellow; leds[i] = color; FastLED.show(); delay(delay_level); } leds[NUM_OF_LEDS_BY_LEVEL * level + 20] = CRGB::Black; FastLED.show(); delay(delay_level); for (int i = NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1; i >= NUM_OF_LEDS_BY_LEVEL * level ; i--) { // -------- DEBUGGING -------- // /* Serial.print("val de la led: "); Serial.print(i); Serial.print("\n"); */ if (digitalRead(PIN_BTN)==LOW){ //Stock des scores LEDs 1 -> 9 -> 1 int center = abs(i - (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL / 2)); if (center <= NUM_OF_LEDS_BY_LEVEL/2) { last_point[level] = NUM_OF_LEDS_BY_LEVEL/2 - center + 1; // Les points augmentent jusqu'à 9 } else { last_point[level] = 0; // À partir de la position 9, les points diminuent } // if(i<(1/2*NUM_OF_LEDS_BY_LEVEL)){ // last_point[level] = i; // } // else{ // for(int degr = 1; degr<NUM_OF_LEDS_BY_LEVEL; degr++) // last_point[level] = (i - degr); // } int last_point_visu = i+1; return i+1; // -------- DEBUGGING -------- // /* Serial.print("last_point_visu"); Serial.print(last_point_visu); for(int z=0; z<NUM_OF_LEVELS; z++){ Serial.print(last_point[z]); Serial.print("\n"); } */ } //Eteins les LEDs derrière la LED mouvante leds[i + 1] = CRGB::Black; delay(3); leds[level * NUM_OF_LEDS_BY_LEVEL + NUM_OF_LEDS_BY_LEVEL / 2] = CRGB::Yellow; leds[i] = color; FastLED.show(); delay(delay_level); } leds[NUM_OF_LEDS_BY_LEVEL] = CRGB::Black; FastLED.show(); delay(delay_level); return 0;
}
void flash() // fonction de décoration qui fait clignoter les leds en blanc avant le passage de niveau {
for (int cpt = 0; cpt < 4; cpt++) { for (int i = NUM_OF_LEDS_BY_LEVEL * level; i <= (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1); i++) // On met toute les leds du niveau en blanc { leds[i] = CRGB::Green; } FastLED.show(); delay(100); for (int i = NUM_OF_LEDS_BY_LEVEL * level; i <= (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1); i++) // On éteint toutes les leds du niveau { leds[i] = CRGB::Black; } FastLED.show(); delay(100); } leds[last_point_visu] = CRGB::Purple;
}
void level_up() // changement de niveau {
flash(); // animation level++; // incrémentation de la variable niveau delay_level -= 4; // le jeu devient de plus en plus rapide
if (level >= NUM_OF_LEVELS) // fin du jeu { compute_score(); //Calcul le score show_score(); //Affiche le score sur un écran à crystaux liquides
//Remise des valeurs pas défaut level = 0; score = 0; delay_level = 30; game_in_progress = false; for(int w=0; w<NUM_OF_LEVELS;w++){ last_point[w] = 0; } }
}
void waiting_start_game(){
// Allume toutes les LEDs en bleu avant de faire commencer la partie for (int w = 0; w < NUM_LEDS; w++){ leds[w] = CRGB::Blue; } FastLED.show();
}
int compute_score(){
// Récupere les élements du tableau last_point et les additionnes for (int i = 0; i<NUM_OF_LEVELS; i++){ if (i > 2) { // Pour les niveaux 4 et 5, le score est diviser par deux score += last_point[i] / 2; } else { score += last_point[i]; } } // -------- DEBUGGING -------- // /* Serial.print("Score : "); Serial.println(score); */ return score;
}
int show_score(){
lcd.clear(); lcd.setCursor(0,0); lcd.print(" Score : "); lcd.print(score); lcd.setCursor(0,1); lcd.print(" Bien joue !!"); // Je ne sais pas comment mettre des caractères speciaux (hors ASCII 128) delay(5000); lcd.clear(); return 0;
}
// ----- MUSIQUE ----- //
int melody[] = {
//Based on the arrangement at https://www.flutetunes.com/tunes.php?id=169 NOTE_AS4,-2, NOTE_F4,8, NOTE_F4,8, NOTE_AS4,8,//1 NOTE_GS4,16, NOTE_FS4,16, NOTE_GS4,-2, NOTE_AS4,-2, NOTE_FS4,8, NOTE_FS4,8, NOTE_AS4,8, NOTE_A4,16, NOTE_G4,16, NOTE_A4,-2, REST,1,
NOTE_AS4,4, NOTE_F4,-4, NOTE_AS4,8, NOTE_AS4,16, NOTE_C5,16, NOTE_D5,16, NOTE_DS5,16,//7 NOTE_F5,2, NOTE_F5,8, NOTE_F5,8, NOTE_F5,8, NOTE_FS5,16, NOTE_GS5,16, NOTE_AS5,-2, NOTE_AS5,8, NOTE_AS5,8, NOTE_GS5,8, NOTE_FS5,16, NOTE_GS5,-8, NOTE_FS5,16, NOTE_F5,2, NOTE_F5,4,
NOTE_DS5,-8, NOTE_F5,16, NOTE_FS5,2, NOTE_F5,8, NOTE_DS5,8, //11 NOTE_CS5,-8, NOTE_DS5,16, NOTE_F5,2, NOTE_DS5,8, NOTE_CS5,8, NOTE_C5,-8, NOTE_D5,16, NOTE_E5,2, NOTE_G5,8, NOTE_F5,16, NOTE_F4,16, NOTE_F4,16, NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,8, NOTE_F4,16,NOTE_F4,8,
NOTE_AS4,4, NOTE_F4,-4, NOTE_AS4,8, NOTE_AS4,16, NOTE_C5,16, NOTE_D5,16, NOTE_DS5,16,//15 NOTE_F5,2, NOTE_F5,8, NOTE_F5,8, NOTE_F5,8, NOTE_FS5,16, NOTE_GS5,16, NOTE_AS5,-2, NOTE_CS6,4, NOTE_C6,4, NOTE_A5,2, NOTE_F5,4, NOTE_FS5,-2, NOTE_AS5,4, NOTE_A5,4, NOTE_F5,2, NOTE_F5,4,
NOTE_FS5,-2, NOTE_AS5,4, NOTE_A5,4, NOTE_F5,2, NOTE_D5,4, NOTE_DS5,-2, NOTE_FS5,4, NOTE_F5,4, NOTE_CS5,2, NOTE_AS4,4, NOTE_C5,-8, NOTE_D5,16, NOTE_E5,2, NOTE_G5,8, NOTE_F5,16, NOTE_F4,16, NOTE_F4,16, NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,8, NOTE_F4,16,NOTE_F4,8
};
void musique(){
int tempo = 60; // sizeof gives the number of bytes, each int value is composed of two bytes (16 bits) // there are two values per note (pitch and duration), so for each note there are four bytes int notes = sizeof(melody) / sizeof(melody[0]) / 2; // this calculates the duration of a whole note in ms int wholenote = (60000 * 2) / tempo; int divider = 0, noteDuration = 0; // iterate over the notes of the melody. // Remember, the array is twice the number of notes (notes + durations) for (int thisNote = 0; thisNote < notes * 2; thisNote = thisNote + 2) {
// calculates the duration of each note divider = melody[thisNote + 1]; if (divider > 0) { // regular note, just proceed noteDuration = (wholenote) / divider; } else if (divider < 0) { // dotted notes are represented with negative durations!! noteDuration = (wholenote) / abs(divider); noteDuration *= 1.5; // increases the duration in half for dotted notes }
// we only play the note for 90% of the duration, leaving 10% as a pause tone(PIN_BUZZER, melody[thisNote], noteDuration*0.9);
// Wait for the specief duration before playing the next note. delay(noteDuration); // stop the waveform generation before the next note. noTone(PIN_BUZZER); }
}
étapes de fabrication
étape 1: câbler et souder
câbler les fils entre les leds, la carte arduino et le bouton puis souder les fils si nécessaire et enfin téléverser le programme dans la carte si nécessaire.
étape 2: le support
réaliser le support en coupant et collant les cartons
étape ...
troubleshouting
quelles sont difficultés, les problèmes, quelles sont les solutions, les trucs et astuces pour que ça marche ?
1er problème : le programme ne marchait pas car la LED était montée à l'envers
2ème problème : adapter la taille du support qui était d'abord trop grand