#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//--------------- OLED ----------------------------------------
// Initialise the display
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//Define Pins
#define OLED_RESET 4
#define BEEPER 3
//Define Visuals
#define FONT_SIZE 2
#define SCREEN_WIDTH 127 //real size minus 1, because coordinate system starts with 0
#define SCREEN_HEIGHT 63 //real size minus 1, because coordinate system starts with 0
#define BALL_SIZE 3
#define SCORE_PADDING 10
float ballX = SCREEN_WIDTH/2;
float ballY = SCREEN_HEIGHT/2;
float ballSpeedX = 1;
float ballSpeedY = 1;
int scoreA = 0;
int scoreB = 0;
//--------------- SETUP Y LOOP ----------------------------------------
void setup()
{
display.begin(SSD1306_SWITCHCAPVCC, 0x3D); // initialize with the I2C addr 0x3D (for the 128x64)
// initialise the display
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x64
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, loop forever
}
display.setTextWrap(false);
display.setTextColor(WHITE);
display.setTextSize(FONT_SIZE);
display.clearDisplay();
}
void loop()
{
calculateMovement();
draw();
}
//-------------------------------------------------------
void calculateMovement()
{
ballX += ballSpeedX;
ballY += ballSpeedY;
//bounce from top, bottom, left and right
if (ballY >= SCREEN_HEIGHT - BALL_SIZE || ballY <= 0 || ballX >= SCREEN_WIDTH - BALL_SIZE || ballX <= 0) {
if (ballY >= SCREEN_HEIGHT - BALL_SIZE || ballY <= 0) {
ballSpeedY *= -1;
}
if (ballX >= SCREEN_WIDTH - BALL_SIZE || ballX <= 0) {
ballSpeedX *= -1;
}
soundBounce();
}
//score points if ball hits wall behind paddle
if (ballX >= SCREEN_WIDTH - BALL_SIZE || ballX <= 0) {
if (ballSpeedX > 0) {
scoreA++;
soundBounce();
}
//
if (ballSpeedX < 0) {
scoreB++;
soundBounce();
}
soundPoint();
}
}
void draw()
{
display.clearDisplay();
//draw center line
for (int i=0; i<SCREEN_HEIGHT; i+=4) {
display.drawFastVLine(SCREEN_WIDTH/2, i, 2, WHITE);
}
//draw ball
display.fillRect(ballX,ballY,BALL_SIZE,BALL_SIZE,WHITE);
//print scores
//backwards indent score A. This is dirty, but it works ... ;)
int scoreAWidth = 5 * FONT_SIZE;
if (scoreA > 9) scoreAWidth += 6 * FONT_SIZE;
if (scoreA > 99) scoreAWidth += 6 * FONT_SIZE;
if (scoreA > 999) scoreAWidth += 6 * FONT_SIZE;
if (scoreA > 9999) scoreAWidth += 6 * FONT_SIZE;
display.setCursor(SCREEN_WIDTH/2 - SCORE_PADDING - scoreAWidth,0);
display.print(scoreA);
display.setCursor(SCREEN_WIDTH/2 + SCORE_PADDING+1,0); //+1 because of dotted line.
display.print(scoreB);
display.display();
}
void soundStart()
{
tone(BEEPER, 250);
delay(100);
tone(BEEPER, 500);
delay(100);
tone(BEEPER, 1000);
delay(100);
noTone(BEEPER);
}
void soundBounce()
{
tone(BEEPER, 500, 50);
}
void soundPoint()
{
tone(BEEPER, 150, 150);
}