Arduino Pong Game
This version uses I2C instead of SPI and uses the SH1106 OLED firmware, not SSD1306
// Pong game for SH1106 OLED 128x64 display
// 2018 - Gord Payne
// based on work of Ben Wohrl
//https://medium.com/@ruction/arduino-pong-i2c-oled-128x64-bd4185970b50
// Converted to run on SH1106 display using u8g2 OLED library
// added sounds
#include <Wire.h> // This library allows you to communicate with I2C
#include <U8g2lib.h> // OLED Universal Graphics library for SH1106 display chip
// Define the PINS you're goint to use on your Arduino Nano
int controller1 = A2; // ANALOG 2
int controller2 = A3; // ANALOG 3
int ledPin = 13; // DIGITAL 13
int btnPin = 5; // DIGITAL 5
int piezo = 9; // buzzer
// Define variables
int buttonState = 0; // HIGH = Pressed
int gameState = 0; // 0 = Home, 1 = Game, 2 = End
int winSound = 0;
int controllerValue1 = 0; // variable to store the value coming from the potentiometer
int controllerValue2 = 0; // variable to store the value coming from the potentiometer
int paddlePositionPlayer1 = 0;
int paddlePositionPlayer2 = 0;
int scorePlayer1 = 0; //0
int scorePlayer2 = 0; //0
int ballX = 128 / 2;
int ballY = 64 / 2;
int ballSpeedX = 2;// was 2
int ballSpeedY = 1; // was 1
int maxScore = 8;
U8G2_SH1106_128X64_NONAME_F_HW_I2C oled(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); // constructor for the particular OLED
#define OLED_ADDRESS 0x3C
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(btnPin, INPUT_PULLUP);
pinMode(piezo, OUTPUT);
oled.begin();
oled.clear();
}
void loop() {
oled.clearBuffer();
// Read controller value and calculate paddle position
controllerValue1 = analogRead(controller1);
controllerValue2 = analogRead(controller2);
paddlePositionPlayer1 = controllerValue1 * (46.0 / 1023.0);
paddlePositionPlayer2 = controllerValue2 * (46.0 / 1023.0);
// Set button state
buttonState = digitalRead(btnPin);
Serial.println(buttonState);
if (buttonState == LOW && gameState == 0) {
gameState = 1;
delay(150);
} else if (buttonState == LOW && (gameState == 1 || gameState == 2)) {
gameState = 0; // reset for new game
scorePlayer1 = 0;
scorePlayer2 = 0;
ballX = 128 / 2;
ballY = 64 / 2;
winSound = 0;
delay(150);
}
if (gameState == 0) {// display opening screen
oled.setFont(u8g2_font_6x10_tf);
oled.setDrawColor(1);
oled.setCursor(40, 18);
oled.println("PONG");
oled.setCursor(32, 38);
oled.println("press start");
}
if (gameState == 1) { // game playing
drawField(scorePlayer1, scorePlayer2); // update screen
collisionControl(); // check for collision
drawBall();
}
if (gameState == 2) {
drawField(scorePlayer1, scorePlayer2);
if (scorePlayer1 == maxScore) {
oled.setCursor(15, 30);
} else if (scorePlayer2 == maxScore) {
oled.setCursor(77, 30);
}
oled.println("winner!");
if (winSound == 0) { // play g major chord
winSnd();
winSound++;
}
}
oled.sendBuffer();
}
void drawField(int score1, int score2) {
oled.drawBox(0, round(paddlePositionPlayer1), 2, 18);
oled.drawBox(126, round(paddlePositionPlayer2), 2, 18);
oled.setFont(u8g2_font_6x10_tf);
oled.setDrawColor(1);
oled.setCursor(55, 10);
oled.print(score1);
oled.print(":");
oled.print(score2);
oled.drawBox(63, 12, 1, 5);
oled.drawBox(63, 22, 1, 5);
oled.drawBox(63, 32, 1, 5);
oled.drawBox(63, 42, 1, 5);
oled.drawBox(63, 52, 1, 5);
oled.drawBox(63, 62, 1, 5);
}
void collisionControl() {
//bounce from top and bottom
if (ballY >= 64 - 2 || ballY <= 0) {
ballSpeedY *= -1;
playSound(400,100,20);
}
//score points if ball hits wall behind player
if (ballX >= 128 - 2 || ballX <= 0) {
if (ballSpeedX > 0) {
scorePlayer1++;
playSound(200,300,200);
ballX = 128 / 4;
}
if (ballSpeedX < 0) {
scorePlayer2++;
playSound(200,300,200);
ballX = 128 / 4 * 3;
}
if (scorePlayer1 == maxScore || scorePlayer2 == maxScore) {
gameState = 2;
}
}
//bounce from player1
if (ballX >= 0 && ballX <= 2 && ballSpeedX < 0) {
if (ballY > round(paddlePositionPlayer1) - 2 && ballY < round(paddlePositionPlayer1) + 18) {
ballSpeedX *= -1;
playSound(700,100,20);
}
}
//bounce from player2
if (ballX >= 128 - 2 - 2 && ballX <= 128 - 2 && ballSpeedX > 0) {
if (ballY > round(paddlePositionPlayer2) - 2 && ballY < round(paddlePositionPlayer2) + 18) {
ballSpeedX *= -1;
playSound(600,100,20);
}
}
}
void drawBall() {
oled.drawBox(ballX, ballY, 2, 2);
ballX += ballSpeedX;
ballY += ballSpeedY;
}
void playSound(int freq,int dur,int pause){
tone(piezo, freq, dur);// play a sound
delay(pause);
noTone(piezo);
}
void winSnd(){
tone(piezo, 784, 250);
delay(200);
noTone(piezo);
tone(piezo, 987, 250);
delay(200);
noTone(piezo);
tone(piezo, 1174, 700);
delay(500);
noTone(piezo);
}
// 2018 - Gord Payne
// based on work of Ben Wohrl
//https://medium.com/@ruction/arduino-pong-i2c-oled-128x64-bd4185970b50
// Converted to run on SH1106 display using u8g2 OLED library
// added sounds
#include <Wire.h> // This library allows you to communicate with I2C
#include <U8g2lib.h> // OLED Universal Graphics library for SH1106 display chip
// Define the PINS you're goint to use on your Arduino Nano
int controller1 = A2; // ANALOG 2
int controller2 = A3; // ANALOG 3
int ledPin = 13; // DIGITAL 13
int btnPin = 5; // DIGITAL 5
int piezo = 9; // buzzer
// Define variables
int buttonState = 0; // HIGH = Pressed
int gameState = 0; // 0 = Home, 1 = Game, 2 = End
int winSound = 0;
int controllerValue1 = 0; // variable to store the value coming from the potentiometer
int controllerValue2 = 0; // variable to store the value coming from the potentiometer
int paddlePositionPlayer1 = 0;
int paddlePositionPlayer2 = 0;
int scorePlayer1 = 0; //0
int scorePlayer2 = 0; //0
int ballX = 128 / 2;
int ballY = 64 / 2;
int ballSpeedX = 2;// was 2
int ballSpeedY = 1; // was 1
int maxScore = 8;
U8G2_SH1106_128X64_NONAME_F_HW_I2C oled(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); // constructor for the particular OLED
#define OLED_ADDRESS 0x3C
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(btnPin, INPUT_PULLUP);
pinMode(piezo, OUTPUT);
oled.begin();
oled.clear();
}
void loop() {
oled.clearBuffer();
// Read controller value and calculate paddle position
controllerValue1 = analogRead(controller1);
controllerValue2 = analogRead(controller2);
paddlePositionPlayer1 = controllerValue1 * (46.0 / 1023.0);
paddlePositionPlayer2 = controllerValue2 * (46.0 / 1023.0);
// Set button state
buttonState = digitalRead(btnPin);
Serial.println(buttonState);
if (buttonState == LOW && gameState == 0) {
gameState = 1;
delay(150);
} else if (buttonState == LOW && (gameState == 1 || gameState == 2)) {
gameState = 0; // reset for new game
scorePlayer1 = 0;
scorePlayer2 = 0;
ballX = 128 / 2;
ballY = 64 / 2;
winSound = 0;
delay(150);
}
if (gameState == 0) {// display opening screen
oled.setFont(u8g2_font_6x10_tf);
oled.setDrawColor(1);
oled.setCursor(40, 18);
oled.println("PONG");
oled.setCursor(32, 38);
oled.println("press start");
}
if (gameState == 1) { // game playing
drawField(scorePlayer1, scorePlayer2); // update screen
collisionControl(); // check for collision
drawBall();
}
if (gameState == 2) {
drawField(scorePlayer1, scorePlayer2);
if (scorePlayer1 == maxScore) {
oled.setCursor(15, 30);
} else if (scorePlayer2 == maxScore) {
oled.setCursor(77, 30);
}
oled.println("winner!");
if (winSound == 0) { // play g major chord
winSnd();
winSound++;
}
}
oled.sendBuffer();
}
void drawField(int score1, int score2) {
oled.drawBox(0, round(paddlePositionPlayer1), 2, 18);
oled.drawBox(126, round(paddlePositionPlayer2), 2, 18);
oled.setFont(u8g2_font_6x10_tf);
oled.setDrawColor(1);
oled.setCursor(55, 10);
oled.print(score1);
oled.print(":");
oled.print(score2);
oled.drawBox(63, 12, 1, 5);
oled.drawBox(63, 22, 1, 5);
oled.drawBox(63, 32, 1, 5);
oled.drawBox(63, 42, 1, 5);
oled.drawBox(63, 52, 1, 5);
oled.drawBox(63, 62, 1, 5);
}
void collisionControl() {
//bounce from top and bottom
if (ballY >= 64 - 2 || ballY <= 0) {
ballSpeedY *= -1;
playSound(400,100,20);
}
//score points if ball hits wall behind player
if (ballX >= 128 - 2 || ballX <= 0) {
if (ballSpeedX > 0) {
scorePlayer1++;
playSound(200,300,200);
ballX = 128 / 4;
}
if (ballSpeedX < 0) {
scorePlayer2++;
playSound(200,300,200);
ballX = 128 / 4 * 3;
}
if (scorePlayer1 == maxScore || scorePlayer2 == maxScore) {
gameState = 2;
}
}
//bounce from player1
if (ballX >= 0 && ballX <= 2 && ballSpeedX < 0) {
if (ballY > round(paddlePositionPlayer1) - 2 && ballY < round(paddlePositionPlayer1) + 18) {
ballSpeedX *= -1;
playSound(700,100,20);
}
}
//bounce from player2
if (ballX >= 128 - 2 - 2 && ballX <= 128 - 2 && ballSpeedX > 0) {
if (ballY > round(paddlePositionPlayer2) - 2 && ballY < round(paddlePositionPlayer2) + 18) {
ballSpeedX *= -1;
playSound(600,100,20);
}
}
}
void drawBall() {
oled.drawBox(ballX, ballY, 2, 2);
ballX += ballSpeedX;
ballY += ballSpeedY;
}
void playSound(int freq,int dur,int pause){
tone(piezo, freq, dur);// play a sound
delay(pause);
noTone(piezo);
}
void winSnd(){
tone(piezo, 784, 250);
delay(200);
noTone(piezo);
tone(piezo, 987, 250);
delay(200);
noTone(piezo);
tone(piezo, 1174, 700);
delay(500);
noTone(piezo);
}
pongcircuit.png | |
File Size: | 96 kb |
File Type: | png |