#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <SPI.h>
// Pin definitions for the ILI9341 screen
#define TFT_CS 10
#define TFT_RST 9
#define TFT_DC 8
// Initialize the display
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
// Game variables
int paddleWidth = 10;
int paddleHeight = 40;
int ballSize = 5;
int paddle1Y = 120, paddle2Y = 120;
int ballX = 160, ballY = 120;
int ballSpeedX = 2, ballSpeedY = 2;
int previousBallX = ballX, previousBallY = ballY; // For clearing previous ball position
int score1 = 0, score2 = 0;
// Paddle movement sensitivity
int paddleSpeed = 10; // Increased from 5 to 10 for more responsiveness
// Pin for player controls (buttons or sensors)
const int player1UpPin = 2;
const int player1DownPin = 3;
const int player2UpPin = 4;
const int player2DownPin = 5;
void setup() {
Serial.begin(9600); // Start serial communication for debugging
tft.begin();
tft.setRotation(3); // Adjust rotation as needed
tft.fillScreen(ILI9341_BLACK);
// Set input pins for paddle control
pinMode(player1UpPin, INPUT_PULLUP);
pinMode(player1DownPin, INPUT_PULLUP);
pinMode(player2UpPin, INPUT_PULLUP);
pinMode(player2DownPin, INPUT_PULLUP);
drawInitialGame();
}
void loop() {
// Debug messages to check if buttons are working
if (digitalRead(player1UpPin) == LOW) {
Serial.println("Player 1 UP button pressed");
}
if (digitalRead(player1DownPin) == LOW) {
Serial.println("Player 1 DOWN button pressed");
}
if (digitalRead(player2UpPin) == LOW) {
Serial.println("Player 2 UP button pressed");
}
if (digitalRead(player2DownPin) == LOW) {
Serial.println("Player 2 DOWN button pressed");
}
// Control paddles with increased sensitivity
if (digitalRead(player1UpPin) == LOW && paddle1Y > 0) {
paddle1Y -= paddleSpeed;
}
if (digitalRead(player1DownPin) == LOW && paddle1Y < tft.height() - paddleHeight) {
paddle1Y += paddleSpeed;
}
if (digitalRead(player2UpPin) == LOW && paddle2Y > 0) {
paddle2Y -= paddleSpeed;
}
if (digitalRead(player2DownPin) == LOW && paddle2Y < tft.height() - paddleHeight) {
paddle2Y += paddleSpeed;
}
// Move ball
ballX += ballSpeedX;
ballY += ballSpeedY;
// Bounce ball off top and bottom
if (ballY <= 0 || ballY >= tft.height() - ballSize) {
ballSpeedY = -ballSpeedY;
}
// Paddle collisions
if (ballX <= paddleWidth && ballY > paddle1Y && ballY < paddle1Y + paddleHeight) {
ballSpeedX = -ballSpeedX;
}
if (ballX >= tft.width() - paddleWidth - ballSize && ballY > paddle2Y && ballY < paddle2Y + paddleHeight) {
ballSpeedX = -ballSpeedX;
}
// Scoring
if (ballX <= 0) {
score2++;
resetBall();
}
if (ballX >= tft.width() - ballSize) {
score1++;
resetBall();
}
// Redraw everything
drawGame();
delay(30); // Control game speed
}
void drawInitialGame() {
// Initial screen setup
tft.fillScreen(ILI9341_BLACK);
drawPaddles();
drawBall();
drawScore();
}
void drawPaddles() {
// Clear previous paddles
tft.fillRect(0, 0, paddleWidth, tft.height(), ILI9341_BLACK); // Player 1 paddle
tft.fillRect(tft.width() - paddleWidth, 0, paddleWidth, tft.height(), ILI9341_BLACK); // Player 2 paddle
// Draw new paddles
tft.fillRect(0, paddle1Y, paddleWidth, paddleHeight, ILI9341_WHITE); // Player 1
tft.fillRect(tft.width() - paddleWidth, paddle2Y, paddleWidth, paddleHeight, ILI9341_WHITE); // Player 2
}
void drawBall() {
// Clear the previous ball position completely
tft.fillRect(previousBallX, previousBallY, ballSize, ballSize, ILI9341_BLACK);
// Draw the new ball position
tft.fillRect(ballX, ballY, ballSize, ballSize, ILI9341_WHITE);
// Update previous position to current position for the next frame
previousBallX = ballX;
previousBallY = ballY;
}
void drawScore() {
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.setCursor(50, 10);
tft.print(score1);
tft.setCursor(tft.width() - 60, 10);
tft.print(score2);
}
void drawGame() {
drawPaddles();
drawBall();
drawScore();
}
void resetBall() {
// Reset ball to the center
ballX = tft.width() / 2;
ballY = tft.height() / 2;
previousBallX = ballX;
previousBallY = ballY;
ballSpeedX = -ballSpeedX;
delay(500); // Pause after a score
}