#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
// Définition des broches pour l'écran TFT
#define TFT_CLK 13
#define TFT_MISO 12
#define TFT_MOSI 11
#define TFT_DC 5
#define TFT_CS 4
#define TFT_RST 8
#define ILI9341_BLACK 0x0000 ///< Couleur noir
#define ILI9341_YELLOW 0xFFE0 ///< Couleur jaune
// Définition des broches pour le joystick
#define JOYSTICK_X A0
#define JOYSTICK_Y A1
// Création de l'objet pour l'écran ILI9341
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
// Position initiale du graphisme (invader)
int posX = 120;
int posY = 160;
const int invaderSize = 2; // Taille d'un pixel du Space Invader
// Position et direction du méchant
int poulpodisPosX = 10;
int poulpodisPosY = 10;
int poulpodisDirection = 1; // 1 pour droite, -1 pour gauche
const int poulpodisSpeed = 2; // Vitesse de déplacement du méchant
// Taille des entités (le héros et le méchant)
const int invaderWidth = invaderSize * 8;
const int invaderHeight = invaderSize * 8;
// Nombre maximum de missiles que le joueur peut avoir à l'écran en même temps
const int maxMissiles = 5;
int missileX[maxMissiles];
int missileY[maxMissiles];
bool missileActive[maxMissiles]; // Indique si le missile est actif (tiré)
const int missileWidth = 2;
const int missileHeight = 8;
// Définir une broche pour le bouton de tir
#define FIRE_BUTTON 2 // Exemple de broche pour le bouton
// Seuils pour éviter que le mouvement ne soit trop sensible
const int threshold = 100;
// Modèle Space Invader en binaire (8x8)
byte invader[8] = {
0b01000010,
0b00100100,
0b00111100,
0b11100111,
0b10111101,
0b10011001,
0b00100100,
0b01100110
};
byte poulpodis1000[8] = {
0b00000000,
0b01111100,
0b01010100,
0b01111100,
0b01111100,
0b00111000,
0b01010100,
0b00000000
};
byte poulpodis500[8] //monstroDanseur
{
0b00010010,
0b00111010,
0b00111010,
0b10010010,
0b11111111,
0b00010010,
0b01111100,
0b01000100
};
// Fonction d'initialisation
void setup() {
// Initialisation de la communication avec l'écran
tft.begin();
tft.fillScreen(ILI9341_BLACK);
// Initialisation des entrées pour le joystick
pinMode(JOYSTICK_X, INPUT);
pinMode(JOYSTICK_Y, INPUT);
pinMode(FIRE_BUTTON, INPUT_PULLUP);
// Initialiser tous les missiles comme inactifs
for (int i = 0; i < maxMissiles; i++) {
missileActive[i] = false;
}
// Dessin initial du graphisme
drawInvader(posX, posY);
// Initialiser le moniteur série
Serial.begin(9600);
}
// Fonction de la boucle principale
void loop() { // Lecture des positions du joystick pour le joueur
int xValue = analogRead(JOYSTICK_X) - 512; // Centrer les valeurs à 0
int yValue = analogRead(JOYSTICK_Y) - 512;
// Sauvegarder l'ancienne position pour effacer le joueur plus tard
int oldPosX = posX;
int oldPosY = posY;
// Tirer un missile si le bouton est pressé
if (digitalRead(FIRE_BUTTON) == LOW) {
fireMissile(); // Tirer un missile
}
// Gérer les missiles
for (int i = 0; i < maxMissiles; i++) {
if (missileActive[i]) {
// Effacer l'ancienne position du missile
tft.fillRect(missileX[i], missileY[i], missileWidth, missileHeight, ILI9341_BLACK);
missileY[i] -= 5; // Déplacer le missile vers le haut
// Vérifier si le missile est hors de l'écran
if (missileY[i] < 0) {
missileActive[i] = false; // Désactiver le missile
}
// Vérifier si le missile touche le méchant
if (checkCollision(missileX[i], missileY[i], missileWidth, missileHeight, poulpodisPosX, poulpodisPosY, invaderWidth, invaderHeight)) {
// Collision détectée : détruire le méchant et désactiver le missile
Serial.println("Le méchant est touché !");
// Effacer l'ancien méchant
tft.fillRect(poulpodisPosX, poulpodisPosY, invaderWidth, invaderHeight, ILI9341_BLACK);
missileActive[i] = false;
// Vous pouvez aussi réinitialiser la position du méchant ou créer un nouvel ennemi ici
poulpodisPosX = 10; // Réinitialiser le méchant (par exemple)
poulpodisPosY = 10; // Réinitialiser sa position
}
// Redessiner le missile s'il est encore actif
if (missileActive[i]) {
tft.fillRect(missileX[i], missileY[i], missileWidth, missileHeight, ILI9341_YELLOW);
}
}
}
// Détection du mouvement sur l'axe X pour le joueur
if (xValue > threshold) {
posX -= 2; // Déplace vers la droite
} else if (xValue < -threshold) {
posX += 2; // Déplace vers la gauche
}
// Détection du mouvement sur l'axe Y pour le joueur
if (yValue > threshold) {
posY -= 2; // Déplace vers le bas
} else if (yValue < -threshold) {
posY += 2; // Déplace vers le haut
}
// Limiter les déplacements du joueur aux bords de l'écran
if (posX < 0) posX = 0;
if (posX > tft.width() - invaderWidth) posX = tft.width() - invaderWidth;
if (posY < 0) posY = 0;
if (posY > tft.height() - invaderHeight) posY = tft.height() - invaderHeight;
// Effacer seulement l'ancienne position du joueur
tft.fillRect(oldPosX, oldPosY, invaderWidth, invaderHeight, ILI9341_BLACK);
// Redessiner le joueur à la nouvelle position
drawInvader(posX, posY);
// Effacer l'ancienne position du méchant "poulpodis"
tft.fillRect(poulpodisPosX, poulpodisPosY, invaderWidth, invaderHeight, ILI9341_BLACK);
// Déplacement du méchant "poulpodis"
poulpodisPosX += poulpodisDirection * poulpodisSpeed;
// Si le méchant atteint le bord de l'écran, il change de direction et descend d'une ligne
if (poulpodisPosX <= 0 || poulpodisPosX >= tft.width() - invaderWidth) {
poulpodisDirection *= -1; // Inverse la direction
poulpodisPosY += invaderHeight; // Descend d'une ligne
}
// Redessiner le méchant à sa nouvelle position
drawPoulpodis(poulpodisPosX, poulpodisPosY);
// Détection de collision entre le héros et le méchant
if (checkCollision(posX, posY, invaderWidth, invaderHeight, poulpodisPosX, poulpodisPosY, invaderWidth, invaderHeight)) {
Serial.println("Collision détectée !");
}
// Petit délai pour rendre le mouvement fluide
delay(50);
}
// Fonction pour vérifier la collision en boîte englobante
bool checkCollision(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) {
return !(x1 > x2 + w2 || // trop à droite
x1 + w1 < x2 || // trop à gauche
y1 > y2 + h2 || // trop en bas
y1 + h1 < y2); // trop en haut
}
// Fonction pour dessiner un mechant
void drawPoulpodis(int x, int y) {
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
if (poulpodis500[row] & (1 << (7 - col))) {
// Dessiner un pixel du Space Invader
tft.fillRect(x + col * invaderSize, y + row * invaderSize, invaderSize, invaderSize, ILI9341_YELLOW);
}
}
}
}
// Fonction pour dessiner un Space Invader
void drawInvader(int x, int y) {
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
if (invader[row] & (1 << (7 - col))) {
// Dessiner un pixel du Space Invader
tft.fillRect(x + col * invaderSize, y + row * invaderSize, invaderSize, invaderSize, ILI9341_YELLOW);
}
}
}
}
void fireMissile() {
for (int i = 0; i < maxMissiles; i++) {
if (!missileActive[i]) {
// Si un missile est disponible, tire un nouveau missile
missileX[i] = posX + invaderWidth / 2 - missileWidth / 2; // Positionner au centre du personnage
missileY[i] = posY; // Le missile part de la position du joueur
missileActive[i] = true;
break; // On ne tire qu'un missile à la fois
}
}
}