#include "DFRobot_GDL.h"
#define TFT_DC 10
#define TFT_RST A0
#define TFT_CS 9
#define PLAYER_ONE A1
#define PLAYER_TWO A2
int buttonPin = 7;
DFRobot_ST7789_240x320_HW_SPI screen(/*dc=*/TFT_DC, /*cs=*/TFT_CS, /*rst=*/TFT_RST);
// PLAYER CO-ORDS
int paddlesStartPosition = 80;
int paddleStartRange = 80;
int prevPaddleOne;
int prevPaddleTwo;
int paddleOne;
int paddleTwo;
// PLAYER ATTRIBUTES
int paddleOneX = 25;
int paddleTwoX = 280;
int paddlesHeight = 40;
int paddlesWidth = 10;
// GLOBAL GAME STATE
bool isGameStart = false;
int targetScore = 10;
int playerOneScore;
int playerTwoScore;
bool playerOneReady = false;
bool playerTwoReady = false;
// BALL ATTRIBUTES
int ballSize = 10;
int ballSpeed = 3;
int speedX[] = { -2, -1, 1, 2 };
// BALL CO-ORDS
int ball_x = 160;
int ball_y = 120;
int prevBallX;
int prevBallY;
// BALL DIRECTIONS
int ball_x_move = 0;
int ball_y_move = 0;
int hitCount = 0;
void setup() {
Serial.begin(9600);
screen.begin();
screen.setRotation(3);
analogRead(10);
pinMode(buttonPin, INPUT);
screen.fillScreen(COLOR_RGB565_WHITE);
reset();
}
void loop() {
if (isGameStart) {
move();
draw();
state();
} else {
movePaddle();
drawPaddle();
startCondition();
}
}
void startCondition() {
if ((paddleOne >= paddlesStartPosition) && (paddleOne + paddlesHeight <= paddlesStartPosition + paddleStartRange)) {
playerOneReady = true;
screen.fillRect(0, paddlesStartPosition, paddlesWidth, paddleStartRange, COLOR_RGB565_GREEN);
} else {
playerOneReady = false;
screen.fillRect(0, paddlesStartPosition, paddlesWidth, paddleStartRange, COLOR_RGB565_LGRAY);
}
if ((paddleTwo >= paddlesStartPosition) && (paddleTwo + paddlesHeight <= paddlesStartPosition + paddleStartRange)) {
screen.fillRect(310, paddlesStartPosition, paddlesWidth, paddleStartRange, COLOR_RGB565_GREEN);
playerTwoReady = true;
} else {
screen.fillRect(310, paddlesStartPosition, paddlesWidth, paddleStartRange, COLOR_RGB565_LGRAY);
playerTwoReady = false;
}
if ((playerOneReady) && (playerTwoReady)) {
isGameStart = true;
screen.fillScreen(COLOR_RGB565_WHITE);
}
}
void state() {
if (playerOneScore == targetScore) {
screen.fillScreen(COLOR_RGB565_WHITE);
screen.setTextColor(COLOR_RGB565_BLACK);
screen.setCursor(65, 110);
screen.println("PLAYER 1 WON!!");
delay(2000);
reset();
}
if (playerTwoScore == targetScore) {
screen.fillScreen(COLOR_RGB565_WHITE);
screen.setTextColor(COLOR_RGB565_BLACK);
screen.setCursor(65, 110);
screen.println("PLAYER 2 WON!!");
delay(2000);
reset();
}
}
void reset() {
isGameStart = false;
playerOneScore = 0;
playerTwoScore = 0;
ball_x = 160;
ball_y = 120;
ball_x_move = 0;
ball_y_move = 0;
ballSpeed = 3;
getRandomX();
getRandomY();
screen.flush();
screen.fillScreen(COLOR_RGB565_WHITE);
screen.setTextSize(4);
screen.setTextColor(COLOR_RGB565_BLACK);
screen.setCursor(55, 100);
screen.println("PING PONG");
screen.setTextSize(2);
screen.setCursor(70, 150);
screen.println("ALIGN TO START");
screen.fillRect(0, paddlesStartPosition, paddlesWidth, paddleStartRange, COLOR_RGB565_LGRAY);
screen.fillRect(310, paddlesStartPosition, paddlesWidth, paddleStartRange, COLOR_RGB565_LGRAY);
}
void restart() {
delay(1000);
ball_x = 160;
ball_y = 120;
ball_x_move = 0;
ball_y_move = 0;
ballSpeed = 3;
getRandomX();
getRandomY();
}
void movePaddle() {
paddleOne = map(analogRead(PLAYER_ONE), 4, 840, 6, 191);
paddleTwo = map(analogRead(PLAYER_TWO), 4, 840, 6, 191);
}
void move() {
movePaddle();
moveBall();
}
void moveBall() {
if (hitCount >= 5) {
ballSpeed++;
if (ball_x_move < 0) {
ball_x_move = -ballSpeed;
} else {
ball_x_move = ballSpeed;
}
hitCount = 0;
}
// TOP AND BOTTOM COLLISIONS
if (ball_y <= 6 || ball_y + ballSize >= 230) {
ball_y_move *= -1;
}
// LEFT WALL
if (ball_x <= 10) {
playerTwoScore++;
restart();
}
// RIGHT WALL
if (ball_x >= 306) {
playerOneScore++;
restart();
}
// LEFT PADDLE COLLISION
if (ballCollision(true) || ballCollision(false)) {
ball_x_move *= -1;
ball_y_move = 0;
hitCount++;
getRandomY();
}
ball_x += ball_x_move;
ball_y += ball_y_move;
}
bool ballCollision(bool left) {
// CHECK LEFT SIDE OF BALL
if (left) {
if ((ball_y >= paddleOne || ball_y + ballSize >= paddleOne) && (ball_y <= paddleOne + paddlesHeight)) {
if (ball_x <= paddleOneX + paddlesWidth && ball_x >= paddleOneX) {
return true;
}
}
} else {
if (ball_y <= paddleTwo + paddlesHeight && (ball_y >= paddleTwo || ball_y + ballSize >= paddleTwo)) {
if (ball_x + ballSize >= paddleTwoX && ball_x + ballSize <= paddleTwoX + paddlesWidth) {
return true;
}
}
}
return false;
}
void draw() {
drawCourt();
drawScores();
drawPaddle();
drawBall();
}
void drawScores() {
screen.setTextColor(COLOR_RGB565_BLACK, COLOR_RGB565_WHITE);
screen.setTextSize(2);
screen.setCursor(110, 20);
screen.println(playerOneScore);
screen.setCursor(200, 20);
screen.println(playerTwoScore);
}
void drawCourt() {
// HORIZONTAL
screen.fillRect(10, 6, 300, 4, COLOR_RGB565_BLACK);
screen.fillRect(10, 230, 300, 4, COLOR_RGB565_BLACK);
// VERTICAL
screen.fillRect(10, 6, 4, 226, COLOR_RGB565_BLACK);
screen.fillRect(306, 6, 4, 226, COLOR_RGB565_BLACK);
// Middle court line
screen.fillRect(158, 6, 4, 226, COLOR_RGB565_BLACK);
}
void drawBall() {
// Erase Ball from previous position
eraseBall();
// Draw ball at new position
screen.fillRect(ball_x, ball_y, ballSize, ballSize, COLOR_RGB565_BLACK);
// Store new position for erasing
prevBallX = ball_x;
prevBallY = ball_y;
}
void drawPaddle() {
// Erasing Paddle from previous positions
erasePaddles();
// Draw paddle to new Position
screen.fillRect(paddleOneX, paddleOne, paddlesWidth, paddlesHeight, COLOR_RGB565_BLACK);
screen.fillRect(paddleTwoX, paddleTwo, paddlesWidth, paddlesHeight, COLOR_RGB565_BLACK);
// Store new position for erasing
prevPaddleOne = paddleOne;
prevPaddleTwo = paddleTwo;
}
void getRandomX() {
do {
ball_x_move = (random(0, 2) == 0) ? -ballSpeed : ballSpeed;
} while (ball_x_move == 0);
}
void getRandomY() {
do {
ball_y_move = speedX[random(0, 4)];
Serial.println(ball_y_move);
} while (ball_y_move == 0);
}
void eraseBall() {
// Ball moved left
if (ball_x - prevBallX > 0) {
screen.fillRect(prevBallX, prevBallY, ball_x - prevBallX, ballSize, COLOR_RGB565_WHITE);
}
// Ball moved right
else {
screen.fillRect(ball_x + ballSize, prevBallY, prevBallX - ball_x, ballSize, COLOR_RGB565_WHITE);
}
// Ball moved down
if (ball_y - prevBallY > 0) {
screen.fillRect(ball_x, prevBallY, ballSize, ball_y - prevBallY, COLOR_RGB565_WHITE);
}
// Ball moved up
else {
screen.fillRect(ball_x, ball_y + ballSize, ballSize, prevBallY - ball_y, COLOR_RGB565_WHITE);
}
}
void erasePaddles() {
// Paddle moved down
if (paddleOne - prevPaddleOne > 0) {
screen.fillRect(paddleOneX, prevPaddleOne, paddlesWidth, paddleOne - prevPaddleOne, COLOR_RGB565_WHITE);
}
// Paddle moved up
else {
screen.fillRect(paddleOneX, paddleOne + paddlesHeight, paddlesWidth, prevPaddleOne - paddleOne, COLOR_RGB565_WHITE);
}
// Paddle moved down
if (paddleTwo - prevPaddleTwo > 0) {
screen.fillRect(paddleTwoX, prevPaddleTwo, paddlesWidth, paddleTwo - prevPaddleTwo, COLOR_RGB565_WHITE);
}
// Paddle moved up
else {
screen.fillRect(paddleTwoX, paddleTwo + paddlesHeight, paddlesWidth, prevPaddleTwo - paddleTwo, COLOR_RGB565_WHITE);
}
}