#include #include TFT_eSPI tft = TFT_eSPI(); LIS3DHTR lis; //Constantes : //couleurs : #define TFT_BLACK 0x0000 /* 0, 0, 0 */ #define TFT_NAVY 0x000F /* 0, 0, 128 */ #define TFT_DARKGREEN 0x03E0 /* 0, 128, 0 */ #define TFT_DARKCYAN 0x03EF /* 0, 128, 128 */ #define TFT_MAROON 0x7800 /* 128, 0, 0 */ #define TFT_PURPLE 0x780F /* 128, 0, 128 */ #define TFT_OLIVE 0x7BE0 /* 128, 128, 0 */ #define TFT_LIGHTGREY 0xC618 /* 192, 192, 192 */ #define TFT_DARKGREY 0x7BEF /* 128, 128, 128 */ #define TFT_BLUE 0x001F /* 0, 0, 255 */ #define TFT_GREEN 0x07E0 /* 0, 255, 0 */ #define TFT_CYAN 0x07FF /* 0, 255, 255 */ #define TFT_RED 0xF800 /* 255, 0, 0 */ #define TFT_MAGENTA 0xF81F /* 255, 0, 255 */ #define TFT_YELLOW 0xFFE0 /* 255, 255, 0 */ #define TFT_WHITE 0xFFFF /* 255, 255, 255 */ #define TFT_ORANGE 0xFDA0 /* 255, 180, 0 */ #define TFT_GREENYELLOW 0xB7E0 /* 180, 255, 0 */ #define PIECE_RADIUS 5 #define PIECE_COUNT 5 #define SPEEDGAME 5 // Paramètres du jeu : bool isGameRunning = false; unsigned long lastButtonPressTime = 0; unsigned long lastTimeDecrement = 0; // Stocke le moment où la dernière seconde a été décrémentée unsigned long timeInterval = 1000; // Interval de temps en millisecondes (1000 ms = 1 seconde) int score = 0; // Initialisation du score int timeLeft = 30; // Initialisation du timer String oldLevel = ""; // Niveau précédent int oldScore = -1; // Score précédent int oldTimeLeft = -1; // Temps précédent String level = "Novice"; // Initialisation du niveau (changeable après) int ballRadius = 7; // rayon de la boule rouge int ballX = 160; // coordonné x du centre de la boule int ballY = 120; // coordonné y du centre de la boule int oldBallX = ballX; // stocker les anciennes coordonnées de la balle int oldBallY = ballY; // stocker les anciennes coordonnées de la balle int currentLevelIndex = 0; String levels[3] = {"Novice", "Confirmé", "Expert"}; // Assurez-vous que les niveaux sont dans le bon ordre struct Piece { int x; int y; bool isCollected; bool isBlack; }; // Niveau Novice Piece novicePieces[5] = { {50, 60, false, false}, {70, 100, false, false}, {90, 140, false, false}, {110, 180, false, false}, {130, 220, false, false}, }; // Niveau confirmé Piece confirmedPieces[5] = { {50, 60, false, false}, {320 - 70, 240 - 100, false, false}, {90, 240 - 140, false, false}, {320 - 110, 100, false, false}, {160, 120, false, false}, }; // Niveau Expert Piece expertPieces[10] = { {50, 60, false, false}, {320 - 70, 240 - 100, false, false}, {90, 240 - 140, false, false}, {320 - 110, 100, false, false}, {160, 120, false, false}, // Pièces noires {80, 80, false, true}, {320 - 80, 240 - 80, false, true}, {80, 240 - 80, false, true}, {320 - 80, 80, false, true}, {160, 60, false, true}, }; Piece* currentPieces = novicePieces; int currentPieceCount = 5; // variable pour stocker les données de l'accèléromètre float accX, accY; float distance(int x1, int y1, int x2, int y2) { return sqrt(sq(x2 - x1) + sq(y2 - y1)); } void setupButtonAndScreen() { pinMode(WIO_KEY_A, INPUT_PULLUP); pinMode(WIO_KEY_B, INPUT_PULLUP); pinMode(WIO_KEY_C, INPUT_PULLUP); tft.begin(); tft.setRotation(3); // dessine la bannière bleu tft.fillRoundRect(0, 0, 320, 40, 0, TFT_BLUE); tft.fillRoundRect(0, 40, 320, 200, 0, TFT_DARKGREY); //set la couleur du text tft.setTextColor(TFT_WHITE, TFT_BLUE); tft.setTextSize(2); // Affichage du niveau, score et timer tft.drawString(level, 10, 10); tft.drawString(String(score)+" pts", 160, 10); tft.drawString(String(timeLeft), 290, 10); //dessine la boule rouge : tft.fillCircle(ballX, ballY, ballRadius, TFT_RED); } void setupAccelerometer() { lis.begin(Wire1); if (!lis) { while (1); } lis.setOutputDataRate(LIS3DHTR_DATARATE_25HZ); lis.setFullScaleRange(LIS3DHTR_RANGE_2G); } void checkButtonState() { int buttonState = digitalRead(WIO_KEY_B); Serial.println(buttonState); if(buttonState == LOW){ isGameRunning = true; lastTimeDecrement = millis(); } } void drawPieces() { for (int i = 0; i < currentPieceCount; i++) { if (!currentPieces[i].isCollected) { tft.fillCircle(currentPieces[i].x, currentPieces[i].y, PIECE_RADIUS, currentPieces[i].isBlack ? TFT_BLACK : TFT_YELLOW); } } } void updateBallPosition() { delay(10); // Lire les données de l'accéléromètre accX = -lis.getAccelerationY(); accY = lis.getAccelerationX(); // Nettoyer l'ancienne position de la balle tft.fillCircle(oldBallX, oldBallY, ballRadius, TFT_DARKGREY); // Déplacer la balle en fonction des données de l'accéléromètre ballX += accX * SPEEDGAME; ballY += accY * SPEEDGAME; // Limiter les positions de la balle à l'intérieur de la zone de jeu if (ballX < 0 + ballRadius) ballX = ballRadius; if (ballX > 320 - ballRadius) ballX = 320 - ballRadius; if (ballY < 40 + ballRadius) ballY = 40 + ballRadius; if (ballY > 240 - ballRadius) ballY = 240 - ballRadius; // Dessiner la nouvelle position de la balle tft.fillCircle(ballX, ballY, ballRadius, TFT_RED); // Mettre à jour les anciennes coordonnées de la balle oldBallX = ballX; oldBallY = ballY; } void checkTime() { // Gestion du chronomètre if (millis() - lastTimeDecrement >= timeInterval) { // Une seconde s'est écoulée, décrémentez le timer et mettez à jour le moment du dernier décrément timeLeft--; lastTimeDecrement = millis(); } // Si le temps est écoulé, arrêtez le jeu if (timeLeft <= 0) { isGameRunning = false; } } void updateBanner() { // Vérifier si les valeurs ont changé if (level != oldLevel || score != oldScore || timeLeft != oldTimeLeft) { // Actualiser le bandeau tft.fillRoundRect(0, 0, 320, 40, 0, TFT_BLUE); tft.drawString(level, 10, 10); tft.drawString(String(score) + " pts", 160, 10); tft.drawString(String(timeLeft), 290, 10); // Mettre à jour les valeurs précédentes oldLevel = level; oldScore = score; oldTimeLeft = timeLeft; } } void displayPieces() { uint16_t oldTextColor = TFT_WHITE; uint8_t oldTextSize = 2; // Effacer toutes les pièces précédentes tft.fillRoundRect(0, 40, 320, 200, 0, TFT_DARKGREY); // Afficher les nouvelles pièces for (int i = 0; i < currentPieceCount; i++) { if (!currentPieces[i].isCollected) { // Choisissez la couleur de la pièce int pieceColor = currentPieces[i].isBlack ? TFT_BLACK : TFT_YELLOW; tft.fillCircle(currentPieces[i].x, currentPieces[i].y, PIECE_RADIUS, pieceColor); // Si la pièce est jaune, ajoutez le symbole '$' if (!currentPieces[i].isBlack) { tft.setTextColor(TFT_BLACK, pieceColor); tft.setTextSize(1); tft.setCursor(currentPieces[i].x - 3, currentPieces[i].y - 3); tft.print("$"); } } } tft.setTextColor(oldTextColor); tft.setTextSize(oldTextSize); } void changeLevel() { if (isGameRunning) { // Si le jeu est en cours, ne faites rien et sortez de la fonction return; } int buttonState = digitalRead(WIO_KEY_C); if(buttonState == LOW && millis() - lastButtonPressTime > 500){ lastButtonPressTime = millis(); // Mise à jour du temps du dernier appui sur le bouton currentLevelIndex++; if(currentLevelIndex >= 3) currentLevelIndex = 0; //retourne à 0 si le niveau dépasse le maximum level = levels[currentLevelIndex]; if(level == "Novice") { currentPieces = novicePieces; currentPieceCount = sizeof(novicePieces) / sizeof(novicePieces[0]); } else if(level == "Confirmé") { currentPieces = confirmedPieces; currentPieceCount = sizeof(confirmedPieces) / sizeof(confirmedPieces[0]); } else if(level == "Expert") { currentPieces = expertPieces; currentPieceCount = sizeof(expertPieces) / sizeof(expertPieces[0]); } // Reset le score score = 0; // Réinitialise l'état des pièces for (int i = 0; i < currentPieceCount; i++) { currentPieces[i].isCollected = false; } displayPieces(); // Afficher les pièces après avoir changé de niveau updateBanner(); // Mettre à jour le bandeau après avoir changé le niveau } } /* void displayLevel() { // Vider la zone de jeu tft.fillRoundRect(0, 40, 320, 200, 0, TFT_DARKGREY); Piece* currentPieces; // pointeur vers le tableau des pièces du niveau en cours if (level == "Novice") { currentPieces = piecesNovice; } else if (level == "Confirmé") { currentPieces = piecesConfirme; } else if (level == "Expert") { currentPieces = piecesExpert; } for (int i = 0; i < PIECE_COUNT; i++) { if (!currentPieces[i].isCollected) { tft.fillCircle(currentPieces[i].x, currentPieces[i].y, PIECE_RADIUS, currentPieces[i].color); if (currentPieces[i].color == TFT_YELLOW) { // seulement dessiner le symbole du dollar pour les pièces jaunes tft.setTextColor(TFT_BLACK, currentPieces[i].color); tft.setTextSize(1); tft.setCursor(currentPieces[i].x - 3, currentPieces[i].y - 3); // Ajuster ces valeurs pour centrer le symbole du dollar tft.print("$"); } } } }*/ void setup() { Serial.begin(115200); setupButtonAndScreen(); setupAccelerometer(); pinMode(WIO_KEY_C, INPUT_PULLUP); displayPieces(); // Afficher les pièces dès le démarrage } void loop() { checkButtonState(); changeLevel(); if(isGameRunning){ updateBallPosition(); checkTime(); } updateBanner(); // Mettre à jour le bandeau dans chaque boucle, que le jeu soit en cours ou non for (int i = 0; i < currentPieceCount; i++) { if (!currentPieces[i].isCollected && distance(ballX, ballY, currentPieces[i].x, currentPieces[i].y) < ballRadius + PIECE_RADIUS) { currentPieces[i].isCollected = true; score++; // Augmenter le score } } }