#include "SPI.h" // Kommunikation mit dem Display
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#include <vector> // Verwendung von Vektoren
#define TFT_DC 27 // Daten/Command für das Display
#define TFT_CS 12 // Chip-Select´´
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC); // Initialisierung des Displays
#define SpielfeldX 200 // Breite des Spielfelds
#define SpielfeldY 200 // Höhe des Spielfelds
#define Feldgroesse 10 // Größe eines Spielfeld-Feldes
#define VERT_PIN 34 // Pin-Definition für die Vertikalachse des Joysticks
#define HORZ_PIN 35 // Pin-Definition für die Horizontalachse des Joysticks
#define SEL_PIN 0 // Pin-Definition für die Auswahltaste des Joysticks
int SchlangeX = 8; // Startposition der Schlange (X-Koordinate)
int SchlangeY = 16; // Startposition der Schlange (Y-Koordinate)
// Definition einer Struktur für die Koordinaten einer Schlange
struct SchlangenKoord {
int x; // X-Koordinate
int y; // Y-Koordinate
};
// Definition einer Struktur für die Koordinaten einer Frucht
struct FruchtKoord {
int x; // X-Koordinate
int y; // Y-Koordinate
} frucht;
SchlangenKoord Richtung = {1, 0}; // Initialisierung der Bewegungsrichtung der Schlange (rechts)
// Deklaration eines Vektors, der Punkte enthält, um die Segmente der Schlange zu speichern
std::vector<SchlangenKoord> snake;
void SchlangenBewegung() {
// Neue Kopfposition berechnen
SchlangenKoord Kopfposition = {snake[0].x + Richtung.x, snake[0].y + Richtung.y};
// Prüfen, ob die neue Kopfposition innerhalb des Spielfelds liegt und nicht mit der Schlange kollidiert
if (Kopfposition.x >= 0 && Kopfposition.x < 22 && //Border
Kopfposition.y >= 0 && Kopfposition.y < SpielfeldY - Feldgroesse) {
// Kollision mit der Schlange überprüfen
for (auto &segment : snake) {
if (Kopfposition.x == segment.x && Kopfposition.y == segment.y) {
return; // Kollision gefunden, Bewegung stoppen
}
}
// Schlange am neuen Kopf zeichnen
tft.fillRect(Kopfposition.x * Feldgroesse, Kopfposition.y * Feldgroesse, Feldgroesse, Feldgroesse, ILI9341_WHITE);
// Schlange bewegen
snake.insert(snake.begin(), Kopfposition); // Neuen Kopf hinzufügen
if (Kopfposition.x == frucht.x && Kopfposition.y == frucht.y) {
// Wenn der Kopf auf eine Frucht trifft, Frucht neu platzieren (noch nicht)
Frucht();
} else {
// Letztes Segment entfernen und löschen
auto &lastSegment = snake.back();
tft.fillRect(lastSegment.x * Feldgroesse, lastSegment.y * Feldgroesse, Feldgroesse, Feldgroesse, ILI9341_BLACK);
snake.pop_back();
}
}
}
void setup() {
tft.begin(); // Initialisierung des Displays
tft.drawRect(20, 60, SpielfeldX, SpielfeldY, ILI9341_WHITE); // Zeichnen des Spielfeldrahmens
// Displaynachricht
tft.setCursor(1, 3);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1);
tft.println("Druecke eine beliebige Taste um das Spiel zu starten");
// Startposition der Schlange
snake.push_back({8, 16});
snake.push_back({7, 16});
snake.push_back({6, 16});
pinMode(VERT_PIN, INPUT);
pinMode(HORZ_PIN, INPUT);
pinMode(SEL_PIN, INPUT_PULLUP);
// Erste Frucht platzieren
Frucht();
}
// Funktion zum Zeichnen der Schlange
void SchlangeBild() {
for (SchlangenKoord &Teil : snake) {
tft.fillRect(Teil.x * Feldgroesse, Teil.y * Feldgroesse, Feldgroesse, Feldgroesse, ILI9341_WHITE);
}
}
// Funktion zum Platzieren einer neuen Frucht
void Frucht() {
frucht.x = random(24, 216);
frucht.y = random(64, 256);
// Frucht auf dem Display zeichnen
tft.fillCircle(frucht.x, frucht.y, 3, ILI9341_RED);
}
// Funktion zur Steuerung der Schlange mit dem Joystick
void Joystick() {
int vert = analogRead(VERT_PIN);
int horz = analogRead(HORZ_PIN);
if (vert > 2048) {
Richtung = {0, -1}; // Nach oben
} else if (vert < 2048) {
Richtung = {0, 1}; // Nach unten
} else if (horz < 2048) {
Richtung = {1, 0}; // Nach rechts
} else if (horz > 2048) {
Richtung = {-1, 0}; // Nach links
}
}
// Hauptprogrammschleife
void loop() {
SchlangeBild();
SchlangenBewegung();
Joystick();
delay(100);
}