#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#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
#define ILI9341_YELLOW 0xFFE0
#define JOYSTICK_X A0
#define JOYSTICK_Y A1
#define FIRE_BUTTON 2
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
const int rows = 5;
const int cols = 6;
const int enemySpeed = 2;
int enemyDirection = 1;
unsigned long lastEnemyMove = 0;
struct Enemy {
int x, y;
bool active;
};
Enemy enemies[rows][cols];
const int invaderSize = 2;
const int invaderWidth = invaderSize * 8;
const int invaderHeight = invaderSize * 8;
int posX = 120;
int posY = 270;
bool playerAlive = true;
// Variables pour les missiles du joueur
const int maxMissiles = 5;
int missileX[maxMissiles];
int missileY[maxMissiles];
bool missileActive[maxMissiles];
const int missileWidth = 2;
const int missileHeight = 8;
// Variables pour les missiles ennemis
const int maxEnemyMissiles = 10;
int enemyMissileX[maxEnemyMissiles];
int enemyMissileY[maxEnemyMissiles];
bool enemyMissileActive[maxEnemyMissiles];
byte invader[8] = {
0b01000010, 0b00100100, 0b00111100, 0b11100111,
0b10111101, 0b10011001, 0b00100100, 0b01100110
};
byte poulpodis500[8] //monstroDanseur
{
0b00010010,
0b00111010,
0b00111010,
0b10010010,
0b11111111,
0b00010010,
0b01111100,
0b01000100
};
void setup() {
tft.begin();
tft.fillScreen(ILI9341_BLACK);
pinMode(JOYSTICK_X, INPUT);
pinMode(JOYSTICK_Y, INPUT);
pinMode(FIRE_BUTTON, INPUT_PULLUP);
Serial.begin(9600);
for (int i = 0; i < maxMissiles; i++) missileActive[i] = false;
for (int i = 0; i < maxEnemyMissiles; i++) enemyMissileActive[i] = false;
// Initialiser les ennemis
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
enemies[r][c].x = 10 + c * (invaderWidth + 10);
enemies[r][c].y = 10 + r * (invaderHeight + 10);
enemies[r][c].active = true;
drawEnemy(enemies[r][c].x, enemies[r][c].y);
}
}
}
void loop() {
if (playerAlive) {
int xValue = analogRead(JOYSTICK_X) - 512;
int yValue = analogRead(JOYSTICK_Y) - 512;
int oldPosX = posX;
int oldPosY = posY;
// Déplacer le joueur
if (xValue > 100) posX -= 2;
if (xValue < -100) posX += 2;
if (yValue > 100) posY -= 2;
if (yValue < -100) posY += 2;
posX = constrain(posX, 0, tft.width() - invaderWidth);
posY = constrain(posY, 0, tft.height() - invaderHeight);
tft.fillRect(oldPosX, oldPosY, invaderWidth, invaderHeight, ILI9341_BLACK);
drawInvader(posX, posY);
if (digitalRead(FIRE_BUTTON) == LOW) {
fireMissile();
}
}
if (millis() - lastEnemyMove >= 200) {
lastEnemyMove = millis();
moveEnemies();
}
updateMissiles();
updateEnemyMissiles();
delay(10);
}
void moveEnemies() {
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (enemies[r][c].active) {
tft.fillRect(enemies[r][c].x, enemies[r][c].y, invaderWidth, invaderHeight, ILI9341_BLACK);
enemies[r][c].x += enemyDirection * enemySpeed;
}
}
}
if (enemies[0][0].x <= 0 || enemies[0][cols - 1].x >= tft.width() - invaderWidth) {
enemyDirection *= -1;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
enemies[r][c].y += invaderHeight;
}
}
}
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (enemies[r][c].active) {
drawEnemy(enemies[r][c].x, enemies[r][c].y);
if (random(100) < 2) fireEnemyMissile(enemies[r][c].x + invaderWidth / 2, enemies[r][c].y + invaderHeight);
}
}
}
}
void fireMissile() {
for (int i = 0; i < maxMissiles; i++) {
if (!missileActive[i]) {
missileX[i] = posX + invaderWidth / 2 - missileWidth / 2;
missileY[i] = posY;
missileActive[i] = true;
break;
}
}
}
void updateMissiles() {
for (int i = 0; i < maxMissiles; i++) {
if (missileActive[i]) {
tft.fillRect(missileX[i], missileY[i], missileWidth, missileHeight, ILI9341_BLACK);
missileY[i] -= 5;
if (missileY[i] < 0) missileActive[i] = false;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (enemies[r][c].active && checkCollision(missileX[i], missileY[i], missileWidth, missileHeight, enemies[r][c].x, enemies[r][c].y, invaderWidth, invaderHeight)) {
enemies[r][c].active = false;
missileActive[i] = false;
tft.fillRect(enemies[r][c].x, enemies[r][c].y, invaderWidth, invaderHeight, ILI9341_BLACK);
break;
}
}
}
if (missileActive[i]) {
tft.fillRect(missileX[i], missileY[i], missileWidth, missileHeight, ILI9341_YELLOW);
}
}
}
}
void fireEnemyMissile(int x, int y) {
for (int i = 0; i < maxEnemyMissiles; i++) {
if (!enemyMissileActive[i]) {
enemyMissileX[i] = x;
enemyMissileY[i] = y;
enemyMissileActive[i] = true;
break;
}
}
}
void updateEnemyMissiles() {
for (int i = 0; i < maxEnemyMissiles; i++) {
if (enemyMissileActive[i]) {
tft.fillRect(enemyMissileX[i], enemyMissileY[i], missileWidth, missileHeight, ILI9341_BLACK);
enemyMissileY[i] += 3;
if (enemyMissileY[i] > tft.height()) enemyMissileActive[i] = false;
if (playerAlive && checkCollision(enemyMissileX[i], enemyMissileY[i], missileWidth, missileHeight, posX, posY, invaderWidth, invaderHeight)) {
playerAlive = false;
Serial.println("Le héros est touché !");
tft.fillRect(posX, posY, invaderWidth, invaderHeight, ILI9341_BLACK);
enemyMissileActive[i] = false;
}
if (enemyMissileActive[i]) {
tft.fillRect(enemyMissileX[i], enemyMissileY[i], missileWidth, missileHeight, ILI9341_YELLOW);
}
}
}
}
bool checkCollision(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) {
return !(x1 > x2 + w2 || x1 + w1 < x2 || y1 > y2 + h2 || y1 + h1 < y2);
}
void drawEnemy(int x, int y) {
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
if (poulpodis500[row] & (1 << (7 - col))) {
tft.fillRect(x + col * invaderSize, y + row * invaderSize, invaderSize, invaderSize, ILI9341_YELLOW);
}
}
}
}
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))) {
tft.fillRect(x + col * invaderSize, y + row * invaderSize, invaderSize, invaderSize, ILI9341_YELLOW);
}
}
}
}