#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#define TFT_CS 15
#define TFT_DC 4
#define TFT_RST 2
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
#define JOY_X_PIN 34
#define JOY_Y_PIN 35
#define JOY_BTN_PIN 32
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
int snakeX[100], snakeY[100];
int snakeLength = 3;
int foodX, foodY;
int direction = 1;
bool gameOver = false;
void setup() {
Serial.begin(115200);
tft.begin();
tft.setRotation(1);
tft.fillScreen(ILI9341_BLACK);
pinMode(JOY_BTN_PIN, INPUT_PULLUP);
for (int i = 0; i < snakeLength; i++) {
snakeX[i] = SCREEN_WIDTH / 2 - i * 10;
snakeY[i] = SCREEN_HEIGHT / 2;
}
spawnFood();
}
void spawnFood() {
int margin = 30;
foodX = random(margin, SCREEN_WIDTH - margin) / 10 * 10;
foodY = random(margin, SCREEN_HEIGHT - margin) / 10 * 10;
}
void drawSnake() {
for (int i = 0; i < snakeLength; i++) {
tft.fillRect(snakeX[i], snakeY[i], 10, 10, ILI9341_GREEN);
}
}
void drawFood() {
tft.fillRect(foodX, foodY, 10, 10, ILI9341_RED);
}
void updateSnake() {
// Hapus ekor (bagian belakang ular)
tft.fillRect(snakeX[snakeLength - 1], snakeY[snakeLength - 1], 10, 10, ILI9341_BLACK);
for (int i = snakeLength - 1; i > 0; i--) {
snakeX[i] = snakeX[i - 1];
snakeY[i] = snakeY[i - 1];
}
if (direction == 0) snakeX[0] -= 10;
if (direction == 1) snakeX[0] += 10;
if (direction == 2) snakeY[0] -= 10;
if (direction == 3) snakeY[0] += 10;
}
void checkCollision() {
if (snakeX[0] < 0 || snakeX[0] >= SCREEN_WIDTH || snakeY[0] < 0 || snakeY[0] >= SCREEN_HEIGHT) {
gameOver = true;
}
for (int i = 1; i < snakeLength; i++) {
if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) {
gameOver = true;
}
}
if (snakeX[0] == foodX && snakeY[0] == foodY) {
snakeLength++;
spawnFood();
}
}
void handleJoystick() {
int xVal = analogRead(JOY_X_PIN);
int yVal = analogRead(JOY_Y_PIN);
// Menampilkan nilai joystick pada serial monitor
Serial.print("X: ");
Serial.print(xVal);
Serial.print(" | Y: ");
Serial.println(yVal);
if (abs(xVal - 2048) > 500 || abs(yVal - 2048) > 500) {
if (xVal < 1000 && direction != 1) {
direction = 0; // Kiri
Serial.println("Tombol: Kiri");
}
else if (xVal > 3000 && direction != 0) {
direction = 1; // Kanan
Serial.println("Tombol: Kanan");
}
if (yVal < 1000 && direction != 2) {
direction = 3; // Atas
Serial.println("Tombol: Atas");
}
else if (yVal > 3000 && direction != 3) {
direction = 2; // Bawah
Serial.println("Tombol: Bawah");
}
}
}
void loop() {
if (!gameOver) {
drawSnake();
drawFood();
checkCollision();
handleJoystick();
updateSnake();
delay(400); // Kurangi delay agar lebih cepat
} else {
tft.setCursor(50, 120);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(3);
tft.println("Game Over!");
delay(1000);
gameOver = false;
snakeLength = 3;
setup();
}
delay(10);
}