//Button Pins and Speaker Pin
#define UP 17 //A3
#define DOWN 16 //A2
#define TONE_PIN A1
//OLED Pins: CLK=13 and MOSI=11
#define dc 4
#define cs 7
#define rst 10
//Color definitions
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1351.h>
#include <SPI.h>
#include "Timer.h"
#include "pitches.h"
#define PADDLE_HEIGHT 12
#define PADDLE_WIDTH 3
#define BALL_DELAY 40 //How quickly the ball's position updates, smaller number = more difficult to play
#define PADDLE_DELAY 5
Adafruit_SSD1351 tft = Adafruit_SSD1351(cs, dc, rst);
Timer t;
bool game_running = false;
int score=0;
int ballDIR[2] = {1,1};
int ballCoords[2] = {58,58};
int oldBallCoords[2];
int currentY = (128-PADDLE_HEIGHT) / 2;
int oldY;
#define NOTE_NUMBER 11
int melody[]={
NOTE_CS5, NOTE_GS4, NOTE_AS4, NOTE_C5, NOTE_AS4, NOTE_GS4, NOTE_CS5, NOTE_GS4, NOTE_AS4, NOTE_GS4, NOTE_CS5
};
int noteDurations[]={
4, 8, 8,8,16,16,16,8,8,8,8
};
void startGame();
void setup() {
Serial.begin(9600);
// put your setup code here, to run once:
initPins();
tft.begin();
initScreen();
}
void loop() {
// put your main code here, to run repeatedly:
if(game_running){
t.update();
}
}
void initPins(){
pinMode(TONE_PIN,OUTPUT);
pinMode(UP, INPUT_PULLUP);
pinMode(DOWN, INPUT_PULLUP);
}
void playTheme(){
for(int thisNote=0;thisNote<NOTE_NUMBER;thisNote++){
if(digitalRead(UP)==0){
game_running=true;
}
if(game_running){
break;
}
int noteDuration = 1000 / (noteDurations[thisNote]/2);
tone(TONE_PIN, melody[thisNote], noteDuration);
int pauseBetweenNotes = noteDuration * 1.3;
delay(pauseBetweenNotes);
noTone(TONE_PIN);
}
}
void updatePaddle();
void updateBall();
void initScreen(){
tft.fillScreen(BLACK);
tft.setCursor(0,0);
tft.setTextSize(3);
tft.print(" PONG");
tft.fillCircle(59,59,20,WHITE);
tft.setTextSize(1);
tft.setCursor(0, 100);
tft.print("Start game by pressing the upper button");
while(!game_running){
playTheme();
}
noTone(TONE_PIN);
detachInterrupt(UP);
tft.fillScreen(BLACK);
t.every(BALL_DELAY, updateBall);
t.every(PADDLE_DELAY, updatePaddle);
}
void startGame(){
Serial.println("Pressed");
game_running = true;
}
void updateBall(){
oldBallCoords[0] = ballCoords[0];
oldBallCoords[1] = ballCoords[1];
if(ballCoords[0]>=127){
ballDIR[0] = -ballDIR[0];
tone(TONE_PIN, NOTE_C4, 50);
delay(50*1.3);
noTone(TONE_PIN);
}
else if(ballCoords[0]<=0){ //You lose
score ++;
tft.setCursor(20, 50);
tft.setTextSize(3);
tft.print(score);
delay(3000);
tft.fillScreen(BLACK);
ballCoords[0] = 58;
ballCoords[1] = 58;
}
if(ballCoords[1]>= 127||ballCoords[1]<=0){
ballDIR[1] = -ballDIR[1];
tone(TONE_PIN, NOTE_C4, 50);
delay(50*1.3);
noTone(TONE_PIN);
}
if(ballCoords[0]>=1&&ballCoords[0]<=PADDLE_WIDTH+1){
if(ballCoords[0]>=currentY&&ballCoords[0]<=currentY+(PADDLE_HEIGHT/2)){
ballDIR[0] = -ballDIR[0];
tone(TONE_PIN, NOTE_C4, 50);
delay(50*1.3);
noTone(TONE_PIN);
}
else if(ballCoords[0]>=currentY+6&&ballCoords[0]<=currentY+PADDLE_HEIGHT){
ballDIR[0] = -ballDIR[0];
ballDIR[1] = -ballDIR[1];
tone(TONE_PIN, NOTE_C4, 50);
delay(50*1.3);
noTone(TONE_PIN);
}
}
ballCoords[0]+=ballDIR[0];
ballCoords[1] += ballDIR[1];
tft.fillRect(oldBallCoords[0],oldBallCoords[1],3,3,BLACK);
tft.fillRect(ballCoords[0],ballCoords[1],3,3,WHITE);
}
void updatePaddle(){
oldY = currentY;
if(digitalRead(UP)==0){
if(currentY > 0){
currentY-=1;
}
}
else if(digitalRead(DOWN)==0){
if(currentY<127-PADDLE_HEIGHT){
currentY +=1;
}
}
tft.fillRect(1, oldY, PADDLE_WIDTH, PADDLE_HEIGHT, BLACK);
tft.fillRect(1, currentY, PADDLE_WIDTH, PADDLE_HEIGHT, WHITE);
}