Skip to content

Instantly share code, notes, and snippets.

@ItsMichal
Created September 25, 2021 05:12
Show Gist options
  • Save ItsMichal/73bbc6190475ab6cd8c3e219c2e4cb9f to your computer and use it in GitHub Desktop.
Save ItsMichal/73bbc6190475ab6cd8c3e219c2e4cb9f to your computer and use it in GitHub Desktop.
LED Pong

LED Pong

The code above runs a basic LED pong game on two WS8212 strips of 5 LEDs each.

Schematic

LED Pong Schematic

// LED Pong
// Michal Bodzianowski (c) 2021
#include <Adafruit_NeoPixel.h>
// Fix for dropping inputs. Every tick, inputRatio
// number of inputs will be listend for. In this case,
// max delay is at 30ms. If you can click the button
// and release it faster than that... god bless you.
const int inputRatio = 10;
int counter = 0;
// Pins for LED strips and controls
const int buttonPin =11;
const int switchPin = 9;
const int neoPinOne = 4;
const int neoPinTwo = 3;
//Led params
const int ledWidth = 5; //Fully implemented
const int ledHeight = 2; //Only works as two for now.
//Initialize LED strips
Adafruit_NeoPixel neoOne(ledWidth, neoPinOne, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel neoTwo(ledWidth, neoPinTwo, NEO_GRB + NEO_KHZ800);
//Game parameters
int pongBallX = 1; //X pos of the pongball
int pongBallY = 0; //Y pos of the pongball
int pongDir = -1; //Direciton
int comY = 0; // Position of the computer
int playerY = 0; //Position of the player
bool startedPong = false; // Whether the game has started (unused for now)
int delayGame = 300; // Delay to start the game at. Eventually gets lower and lower.
bool buttonPress = false; // Whether the button is being pressed. Prevents state from switching too often
// Setup
void setup()
{
//Start pins and strips
pinMode(buttonPin, INPUT);
pinMode(switchPin, INPUT);
neoOne.begin();
neoTwo.begin();
}
// Resets the game parameters
void resetGame(){
playerY = 0;
pongBallX = 1;
pongBallY = 0;
pongDir = -1;
comY = 0;
playerY = 0;
startedPong = false;
delayGame = 300;
}
// Main Loop
void loop()
{
//On button press- switch Player pos
if(digitalRead(buttonPin) == HIGH && buttonPress == false){
buttonPress = true;
playerY++;
if(playerY > (ledHeight-1)){
playerY =0;
}
}else if (digitalRead(buttonPin) == LOW){ //Prevents double input until button released
buttonPress= false;
}
// If game loop is set to go
// This allows player input to happen every 30ms
// without speeding up the game that much
if(inputRatio==counter){
counter = 0; // Resets the counter
//Throw pong
pongBallX = pongBallX+pongDir;
//Player side
if(pongBallX == 0){
//Hit player
if(pongBallY == playerY){
// Randomly move ball up or down
if(random(0,2) == 1){
pongBallY +=1;
}
pongDir = 1; // Switch dir
pongBallX = pongBallX+pongDir; // Move pongball
delayGame -= 10; // Speed up game
}else{
// Miss player and lose game
for(int i = 0; i < ledWidth; i++){
neoOne.setPixelColor(i, neoOne.Color(100,0,0));
neoTwo.setPixelColor(i, neoOne.Color(100,0,0));
}
neoOne.show();
neoTwo.show();
delay(3000);
resetGame();
}
}
//COM side
if(pongBallX == ledWidth-1){
//Return ball with random dir
//and speed up game
if(random(0,2) == 1){
pongBallY +=1;
}
pongDir = -1;
pongBallX = pongBallX+pongDir;
delayGame -= 10;
}
//Enforce bounds. This code line
//prevents multiple lines unfortunately.
if(pongBallY > 1){
pongBallY = 0;
}
//Set computer to pongball
//so it never "loses"
comY = pongBallY;
}
//Clear screen
for(int i = 0; i < ledWidth; i++){
neoOne.setPixelColor(i, neoOne.Color(0,0,0));
neoTwo.setPixelColor(i, neoOne.Color(0,0,0));
}
//Display player
float div = (float) counter/ (float) inputRatio;
int brightness = 50;
//Set color of player
int color = neoOne.Color(100,100,100);
//Cheat code
//If switch is up, change player color
//to green and set player pos to ball pos
//so player never loses.
if(digitalRead(switchPin) == HIGH){
color = neoOne.Color(0,100,0);
playerY = pongBallY;
}
//Set player LED on right strip
// This code also limits height
// as well as the next few blocks
if(playerY == 0){
neoOne.setPixelColor(0, color);
}else{
neoTwo.setPixelColor(0, color);
}
//Show computer LED
if(comY == 0){
neoOne.setPixelColor(ledWidth-1, neoOne.Color(100,100,100));
}else{
neoTwo.setPixelColor(ledWidth-1, neoOne.Color(100,100,100));
}
//Show pong ball LED
if(pongBallY == 0){
neoOne.setPixelColor(pongBallX, neoOne.Color(0,0,brightness));
//Set trailing LED
if(pongBallX-pongDir > 0 && pongBallX-pongDir < ledWidth-1){
neoOne.setPixelColor(pongBallX-pongDir, neoOne.Color(0,0,brightness/2));
}
}else{
neoTwo.setPixelColor(pongBallX, neoTwo.Color(0,0,brightness));
//Set trailing LED
if(pongBallX-pongDir > 0 && pongBallX-pongDir < ledWidth-1){
neoTwo.setPixelColor(pongBallX-pongDir, neoTwo.Color(0,0,brightness/5));
}
}
//Win condition
//If pongBall reaches 50ms delay then player has won.
if(delayGame < 50){
//Light up green for 3s
for(int i = 0; i < ledWidth; i++){
neoOne.setPixelColor(i, neoOne.Color(0,100,0));
neoTwo.setPixelColor(i, neoOne.Color(0,100,0));
}
neoOne.show();
neoTwo.show();
delay(3000);
// Reset the game
resetGame();
}
//Show all LEDs
neoTwo.show();
neoOne.show();
//Set global delay-
//This is divided by inputRatio
//to allow for higher player input
//polling. Counter keeps track of
//when game logic should run.
//Default is every 10 input polls and 300ms.
delay(delayGame/inputRatio);
counter++;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment