#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#define TFT_CS 10
#define TFT_DC 9
#define TFT_RST -1
#define JOY_VERT A0
#define JOY_HORIZ A1
#define JOY_SELECT 2
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
const int screenWidth = 240;
const int screenHeight = 320;
const int playerWidth = 20;
const int playerHeight = 20;
const int bulletWidth = 2;
const int bulletHeight = 10;
const int enemyWidth = 20;
const int enemyHeight = 20;
const int maxEnemies = 10;
int playerX = screenWidth / 2 - playerWidth / 2;
int playerY = screenHeight - playerHeight - 10;
int oldPlayerX = playerX;
int bulletX = -1, bulletY = -1;
int oldBulletX = -1, oldBulletY = -1;
int enemyX[maxEnemies], enemyY[maxEnemies];
bool enemyAlive[maxEnemies];
int enemyDirection = 1;
int enemySpeed = 2;
int bulletSpeed = 7;
int playerSpeed = 6;
bool gameRunning = true;
unsigned long lastPlayerMoveTime = 0;
unsigned long lastBulletMoveTime = 0;
unsigned long lastEnemyMoveTime = 0;
const unsigned long playerMoveInterval = 20;
const unsigned long bulletMoveInterval = 15;
const unsigned long enemyMoveInterval = 200;
int oscillationCounter = 0; // Contatore per la discesa dei nemici
void setup() {
tft.begin();
tft.setRotation(0);
tft.fillScreen(ILI9341_BLACK);
pinMode(JOY_SELECT, INPUT_PULLUP);
// Impostazione iniziale dei nemici
for (int i = 0; i < maxEnemies; i++) {
enemyX[i] = i * (enemyWidth + 10) + 10;
enemyY[i] = 30;
enemyAlive[i] = true;
}
}
void loop() {
if (!gameRunning) {
if (digitalRead(JOY_SELECT) == LOW) {
resetGame();
}
return;
}
handleInput();
updateBullet();
updateEnemies();
checkCollisions();
}
void handleInput() {
int xValue = analogRead(JOY_HORIZ);
if (millis() - lastPlayerMoveTime >= playerMoveInterval) {
lastPlayerMoveTime = millis();
// Cancella la vecchia posizione del giocatore
tft.fillRect(oldPlayerX, playerY, playerWidth, playerHeight, ILI9341_BLACK);
oldPlayerX = playerX;
if (xValue > 600 && playerX > 0) {
playerX -= playerSpeed;
} else if (xValue < 400 && playerX < screenWidth - playerWidth) {
playerX += playerSpeed;
}
tft.fillRect(playerX, playerY, playerWidth, playerHeight, ILI9341_GREEN);
}
// Sparo, solo se il proiettile non è attivo
if (digitalRead(JOY_SELECT) == LOW && bulletY < 0) {
bulletX = playerX + playerWidth / 2 - bulletWidth / 2;
bulletY = playerY;
}
}
void updateBullet() {
if (millis() - lastBulletMoveTime >= bulletMoveInterval) {
lastBulletMoveTime = millis();
if (oldBulletY >= 0) {
tft.fillRect(oldBulletX, oldBulletY, bulletWidth, bulletHeight, ILI9341_BLACK);
}
if (bulletY >= 0) {
oldBulletX = bulletX;
oldBulletY = bulletY;
bulletY -= bulletSpeed;
if (bulletY >= 0) {
tft.fillRect(bulletX, bulletY, bulletWidth, bulletHeight, ILI9341_WHITE);
} else {
bulletX = -1;
}
}
}
}
void updateEnemies() {
unsigned long currentMillis = millis();
if (currentMillis - lastEnemyMoveTime >= enemyMoveInterval) {
lastEnemyMoveTime = currentMillis;
bool hitEdge = false;
// Cancella tutti i nemici dalla posizione precedente
for (int i = 0; i < maxEnemies; i++) {
if (enemyAlive[i]) {
tft.fillRect(enemyX[i], enemyY[i], enemyWidth, enemyHeight, ILI9341_BLACK);
}
}
// Oscilla i nemici a destra o sinistra e verifica se raggiungono i bordi
for (int i = 0; i < maxEnemies; i++) {
if (enemyAlive[i]) {
enemyX[i] += enemyDirection * enemySpeed;
if (enemyX[i] <= 0 || enemyX[i] >= screenWidth - enemyWidth) {
hitEdge = true;
}
}
}
// Cambia direzione e incrementa il contatore delle oscillazioni
if (hitEdge) {
enemyDirection = -enemyDirection;
oscillationCounter++;
}
// Ogni 4 oscillazioni, fai scendere i nemici di un gradino
if (oscillationCounter >= 4) {
oscillationCounter = 0;
for (int i = 0; i < maxEnemies; i++) {
if (enemyAlive[i]) {
enemyY[i] += 10;
}
}
}
// Ridisegna tutti i nemici nella nuova posizione
for (int i = 0; i < maxEnemies; i++) {
if (enemyAlive[i]) {
tft.fillRect(enemyX[i], enemyY[i], enemyWidth, enemyHeight, ILI9341_RED);
}
}
}
}
void checkCollisions() {
for (int i = 0; i < maxEnemies; i++) {
if (enemyAlive[i] && bulletY >= enemyY[i] && bulletY <= enemyY[i] + enemyHeight) {
if (bulletX >= enemyX[i] && bulletX <= enemyX[i] + enemyWidth) {
tft.fillRect(enemyX[i], enemyY[i], enemyWidth, enemyHeight, ILI9341_BLACK);
enemyAlive[i] = false;
bulletY = -1;
break;
}
}
}
for (int i = 0; i < maxEnemies; i++) {
if (enemyAlive[i] && enemyY[i] + enemyHeight >= playerY) {
gameRunning = false;
clearEnemies(); // Cancella i nemici quando raggiungono il fondo
}
}
}
void clearEnemies() {
for (int i = 0; i < maxEnemies; i++) {
tft.fillRect(enemyX[i], enemyY[i], enemyWidth, enemyHeight, ILI9341_BLACK);
}
}
void resetGame() {
playerX = screenWidth / 2 - playerWidth / 2;
playerY = screenHeight - playerHeight - 10;
bulletX = -1;
bulletY = -1;
gameRunning = true;
oscillationCounter = 0;
for (int i = 0; i < maxEnemies; i++) {
enemyX[i] = i * (enemyWidth + 10) + 10;
enemyY[i] = 30;
enemyAlive[i] = true;
}
}