#include "SPI.h" #include #include #include "Adafruit_WS2801.h" #include "Adafruit_LEDBackpack.h" #include "Adafruit_GFX.h" Adafruit_7segment matrix = Adafruit_7segment(); // Define pin numbers for each device // a is left side, b right side #define abutton 2 #define bbutton 8 #define switch1 3 // fast rainbow #define switch2 12 // slow rainbow #define switch3 5 // fast moving rainbow #define switch4 6 // slow moving rainbow #define switch5 9 // harder game switch #define mute 4 // mute switch #define pot 0 //analog pin uint8_t SPEAKER = 7; //for reference in hooking up, not used as they are hardware spi pins //int dataPin = 11; //int clockPin = 13; // TWI (I2C) pins // datapin = A4 // clockpin = A5 //color list for random color generation #define numColors 128 int randColors[numColors][3] = { {127,0,0},//red {127,127,0},//yellow {0,127,0},//green {0,127,127},//cyan {0,0,127},//blue {127,0,127},//violet {100,100,10},//light blue {165,42,42}, {178,34,34}, {220,20,60}, {255,99,71}, {255,127,80}, {205,92,92}, {240,128,128}, {233,150,122}, {250,128,114}, {255,160,122}, {255,69,0}, {255,140,0}, {255,165,0}, {255,215,0}, {184,134,11}, {218,165,32}, {238,232,170}, {189,183,107}, {240,230,140}, {128,128,0}, {255,255,0}, {154,205,50}, {85,107,47}, {107,142,35}, {124,252,0}, {127,255,0}, {173,255,47}, {34,139,34}, {50,205,50}, {144,238,144}, {152,251,152}, {143,188,143}, {0,250,154}, {0,255,127}, {46,139,87}, {102,205,170}, {60,179,113}, {32,178,170}, {47,79,79}, {0,128,128}, {0,139,139}, {0,255,255}, {0,255,255}, {224,255,255}, {0,206,209}, {64,224,208}, {72,209,204}, {175,238,238}, {127,255,212}, {176,224,230}, {95,158,160}, {70,130,180}, {100,149,237}, {0,191,255}, {30,144,255}, {173,216,230}, {135,206,235}, {135,206,250}, {25,25,112}, {65,105,225}, {138,43,226}, {75,0,130}, {72,61,139}, {106,90,205}, {123,104,238}, {147,112,219}, {139,0,139}, {148,0,211}, {153,50,204}, {186,85,211}, {128,0,128}, {216,191,216}, {221,160,221}, {238,130,238}, {255,0,255}, {218,112,214}, {199,21,133}, {219,112,147}, {255,20,147}, {255,105,180}, {255,182,193}, {255,192,203}, {250,235,215}, {245,245,220}, {255,228,196}, {255,235,205}, {245,222,179}, {255,248,220}, {255,250,205}, {250,250,210}, {255,255,224}, {139,69,19}, {160,82,45}, {210,105,30}, {205,133,63}, {244,164,96}, {222,184,135}, {210,180,140}, {188,143,143}, {255,228,181}, {255,222,173}, {255,218,185}, {255,228,225}, {255,240,245}, {250,240,230}, {253,245,230}, {255,239,213}, {255,245,238}, {245,255,250}, {112,128,144}, {119,136,153}, {176,196,222}, {230,230,250}, {255,250,240}, {240,248,255}, {248,248,255}, {240,255,240}, {255,255,240}, {240,255,255}, {255,250,250}, {128,128,128}, }; // Define notes for win music // start at A below middle C // Musical notes are defined differently in tone.h, that's why I had to included these here #define NOTE_Ab 207.652 #define NOTE_A 220.000 #define NOTE_As 233.082 #define NOTE_Bb NOTE_As #define NOTE_B 246.942 #define NOTE_C 261.626 #define NOTE_Cs 277.183 #define NOTE_Db NOTE_Cs #define NOTE_D 293.665 #define NOTE_Ds 311.127 #define NOTE_Eb NOTE_Ds #define NOTE_E 329.628 #define NOTE_F 349.228 #define NOTE_Fs 369.994 #define NOTE_Gb NOTE_Fs #define NOTE_G 391.995 #define NOTE_Gs 415.305 #define NOTE_REST 0.0 #define NOTE_SUSTAIN -1.0 // Part of Bach 2-part invention #4 in D minor // http://www.8notes.com/scores/2791.asp int tempo = 150; float composition[] = { NOTE_D, NOTE_E, NOTE_F, NOTE_G, NOTE_A*2, NOTE_As*2, NOTE_Db, NOTE_As*2, NOTE_A*2, NOTE_G, NOTE_F, NOTE_E, NOTE_F, NOTE_REST, NOTE_A*2, NOTE_REST, NOTE_D*2, NOTE_REST, NOTE_G, NOTE_REST, NOTE_Cs*2, NOTE_REST, NOTE_E*2, NOTE_REST, NOTE_D*2, NOTE_E*2, NOTE_F*2, NOTE_G*2, NOTE_A*4, NOTE_As*4, NOTE_Db*2, NOTE_As*4, NOTE_A*4, NOTE_G*2, NOTE_F*2, NOTE_E*2, }; // uses a non standard tone library // http://code.google.com/p/rogue-code/wiki/ToneLibraryDocumentation Tone tone1; // flags // N: new game, i.e first time plugged in // S: same game, each round is still same game // R: right // L: left char flag = 'N'; char turn = 'A'; char cheat = 'N'; int winningscore = 12; int nLEDs = 32; int maxdelay = 60;//35 int mindelay = 18; int i = 0; int j = 0; byte abuttonPoints = 0; byte bbuttonPoints = 0; // ball speed variables byte ballSpeed = 0; byte ballSpeedIncrease = 0; int ballInitialSpeed = 0; // how far away you can hit the button without missing is one less than this // e.g. if bz=5 then you have to hit within five pixels of the edge int normalbounce = 5; int reducedbounce = 3; int bouncezone = normalbounce; // define strip, mine uses ws2801 chips, require ws2801 library // https://github.com/adafruit/Adafruit-WS2801-Library Adafruit_WS2801 strip = Adafruit_WS2801(nLEDs); /* Helper functions for RGB strip colors */ // Create a 24 bit color ballInitialSpeedue from R,G,B uint32_t Color(byte r, byte g, byte b) { uint32_t c; c = r; c <<= 8; c |= g; c <<= 8; c |= b; return c; } //Input a value 0 to 255 to get a color value. //The colors are a transition r - g -b - back to r uint32_t Wheel(byte WheelPos) { if (WheelPos < 85) { return Color(WheelPos * 3, 255 - WheelPos * 3, 0); } else if (WheelPos < 170) { WheelPos -= 85; return Color(255 - WheelPos * 3, 0, WheelPos * 3); } else { WheelPos -= 170; return Color(0, WheelPos * 3, 255 - WheelPos * 3); } } void setup() { //assign buttons pinMode(abutton, INPUT); pinMode(bbutton, INPUT); pinMode(switch1, INPUT); pinMode(mute, INPUT); pinMode(SPEAKER, OUTPUT); //initialize speaker tone1.begin(SPEAKER); //initialize LED strip strip.begin(); // Update LED contents, to start they are all 'off' strip.show(); //initalize 7 segment LED matrix.begin(0x70); randomSeed(analogRead(1)); } void loop() { // points display code if (abuttonPoints <= 9) { matrix.writeDigitNum(1, abuttonPoints); matrix.writeDigitNum(0, 0); } else { int temp = abuttonPoints-10; if (temp==0) { matrix.writeDigitNum(1, 0); } else { matrix.writeDigitNum(1, abuttonPoints-10); } matrix.writeDigitNum(0, 1); } matrix.drawColon(true); if (bbuttonPoints <= 9) { matrix.writeDigitNum(4, bbuttonPoints); matrix.writeDigitNum(3, 0); } else { int temp = bbuttonPoints-10; if (temp==0) { matrix.writeDigitNum(4, 0); } else { matrix.writeDigitNum(4, bbuttonPoints-10); } matrix.writeDigitNum(3, 1); } matrix.writeDisplay(); // switch for light show - all color rainbow fast if (digitalRead(switch1) == HIGH) { rainbow(5); // set strip off for new game for(i=0; i < nLEDs; i++) strip.setPixelColor(i, 0); strip.show(); } // switch for light show - all color rainbow slow if (digitalRead(switch2) == HIGH) { rainbow(25); // set strip off for new game for(i=0; i < nLEDs; i++) strip.setPixelColor(i, 0); strip.show(); } // switch for light show - moving rainbow - fast if (digitalRead(switch3) == HIGH) { rainbowCycleabutton(0); } // switch for light show - moving rainbow - slow if (digitalRead(switch4) == HIGH) { rainbowCyclebbutton(5); } // switch for harder game - reduce bounce zone if (digitalRead(switch5) == HIGH) { bouncezone = reducedbounce; } if (digitalRead(switch5) == LOW) { bouncezone = normalbounce; } // a wins if(abuttonPoints > winningscore) { // reset speed increase conuter ballSpeedIncrease = 0; // light show abuttonCelebrate(); } // b wins if(bbuttonPoints > winningscore) { // reset speed increase conuter ballSpeedIncrease = 0; // light show bbuttonCelebrate(); } // flag starts as N // set pixel light for player who's turn it is // this runs once, the first time the game is plugged in if(flag == 'N' && turn == 'A') { strip.setPixelColor(0, Color(100, 100, 10)); strip.show(); } if(flag == 'N' && turn == 'B') { strip.setPixelColor(nLEDs-1, Color(100, 100, 10)); strip.show(); } // pot is being read anytime the ball is not moving if(flag != 'R' && flag != 'L') { ballInitialSpeed = analogRead(pot); ballInitialSpeed = map(ballInitialSpeed, 0, 1023, mindelay, maxdelay); ballSpeed = ballInitialSpeed - ballSpeedIncrease; } // flag == right if(flag == 'R') { // increase ball speed by reducing delay ballSpeedIncrease += 1; ballSpeed = ballInitialSpeed - ballSpeedIncrease; if(ballSpeed < 0) ballSpeed = 0; if(ballSpeed > maxdelay) ballSpeed = maxdelay; // play tick sound if(digitalRead(mute) == LOW) { tone1.play(NOTE_F5, 50); } delay(50); int rand = random(0,numColors+1); // random color ball goes to the right chaseRight(Color(randColors[rand][1], randColors[rand][2], randColors[rand][3]), ballSpeed); } // flag = left if(flag == 'L') { // increase ball speed by reducing delay ballSpeedIncrease += 1; ballSpeed = ballInitialSpeed - ballSpeedIncrease; if(ballSpeed < 0) ballSpeed = 0; if(ballSpeed > maxdelay) ballSpeed = maxdelay; if(digitalRead(mute) == LOW) { tone1.play(NOTE_F5, 50); } delay(50); int rand = random(0,numColors+1); // random color ball goes to the left chaseLeft(Color(randColors[rand][1], randColors[rand][2], randColors[rand][3]), ballSpeed); } int AbuttonState = digitalRead(abutton); if(AbuttonState == HIGH && turn == 'A' && flag != 'R' && flag != 'L') { ballSpeed = ballInitialSpeed; ballSpeedIncrease = 0; i = 0; int rand = random(0,numColors+1); // random color ball goes to the right chaseRight(Color(randColors[rand][1], randColors[rand][2], randColors[rand][3]), ballSpeed); } int BbuttonState = digitalRead(bbutton); if(BbuttonState == HIGH && turn == 'B' && flag != 'R' && flag != 'L') { ballSpeed = ballInitialSpeed; ballSpeedIncrease = 0; i = nLEDs; int rand = random(0,numColors+1); // random color ball goes to the left chaseLeft(Color(randColors[rand][1], randColors[rand][2], randColors[rand][3]), ballSpeed); } } void win_music() { unsigned long note = composition[i]; for (i=1; i<37 ; i++) { unsigned long note = composition[i]; if (note == NOTE_REST) tone1.stop(); else if (note == NOTE_SUSTAIN) ; // Don't do anything, just let the current tone continue else tone1.play(note); delay(tempo); } } void chaseRight(uint32_t c, uint8_t wait) { for(i; i < nLEDs; i++) { if(digitalRead(bbutton) == HIGH) { cheat = 'Y'; if(digitalRead(mute) == LOW) { tone1.play(NOTE_F3,150); } } strip.setPixelColor(i, c); // Set new pixel 'on' strip.show(); // Refresh LED states strip.setPixelColor(i, 0); // Erase pixel, but don't refresh! delay(wait); if(i > nLEDs-bouncezone-1 && cheat != 'Y') { int BbuttonState = digitalRead(bbutton); if(BbuttonState == HIGH) { turn = 'B'; flag = 'L'; return; } } } abuttonPoints++; if(abuttonPoints <= winningscore) strip.show(); if(digitalRead(mute) == LOW) { tone1.play(NOTE_B3, 500); } delay(500); flag = 'S'; cheat = 'N'; // set light at player a side strip.setPixelColor(0, Color(100, 100, 10)); strip.show(); } void chaseLeft(uint32_t c, uint8_t wait) { for(i; i >= 0; i--) { if(digitalRead(abutton) == HIGH) { cheat = 'Y'; if(digitalRead(mute) == LOW) { tone1.play(NOTE_F3,150); } } strip.setPixelColor(i, c); // Set new pixel 'on' strip.show(); // Refresh LED states strip.setPixelColor(i, 0); // Erase pixel, but don't refresh! delay(wait); if(i < bouncezone && cheat != 'Y') { int AbuttonState = digitalRead(abutton); if(AbuttonState == HIGH) { //i = 0; turn = 'A'; flag = 'R'; return; } } } bbuttonPoints++; strip.show(); if(bbuttonPoints <= winningscore) // play lose point sound if(digitalRead(mute) == LOW) { tone1.play(NOTE_B3, 500); } delay(500); flag = 'S'; cheat = 'N'; // set light at player b side strip.setPixelColor(nLEDs-1, Color(100, 100, 10)); strip.show(); } void abuttonCelebrate() { abuttonPoints = 0; bbuttonPoints = 0; if(digitalRead(mute) == LOW) { win_music(); } colorWipeLeft(Color(255, 0, 0), 20); colorWipeLeft(Color(0, 255, 0), 20); colorWipeLeft(Color(0, 0, 255), 20); rainbowCycleabutton(0); flag = 'N'; turn = 'B'; } void bbuttonCelebrate() { abuttonPoints = 0; bbuttonPoints = 0; if(digitalRead(mute) == LOW) { win_music(); } colorWipeRight(Color(255, 0, 0), 20); colorWipeRight(Color(0, 255, 0), 20); colorWipeRight(Color(0, 0, 255), 20); rainbowCyclebbutton(0); flag = 'N'; turn = 'A'; } void rainbowCycleabutton(uint8_t wait) { int m = nLEDs; uint16_t k, j; for (j=0; j < 384 * 3; j++) { // 5 cycles of all 384 colors in the Wheel for (k=0; k < strip.numPixels(); k++) { // tricky math! we use each pixel as a fraction of the full 384-color Wheel // (thats the i / strip.numPixels() part) // Then add in j which makes the colors go around per pixel // the % 384 is to make the Wheel cycle around strip.setPixelColor(k, Wheel( ((k * 384 / strip.numPixels()) + j) % 384) ); } strip.show(); // write all the pixels out delay(wait); } for(m; m >= 0; m--) { strip.setPixelColor(m, 0); strip.show(); } } void rainbowCyclebbutton(uint8_t wait) { int m = 0; uint16_t k, j; for (j=384 * 3; j > 0; j--) { // 5 cycles of all 384 colors in the Wheel for (k=0; k < strip.numPixels(); k++) { // tricky math! we use each pixel as a fraction of the full 384-color Wheel // (thats the i / strip.numPixels() part) // Then add in j which makes the colors go around per pixel // the % 384 is to make the Wheel cycle around strip.setPixelColor(k, Wheel( ((k * 384 / strip.numPixels()) + j) % 384) ); } strip.show(); // write all the pixels out delay(wait); } for(m; m < nLEDs; m++) { strip.setPixelColor(m, 0); strip.show(); } } void rainbow(uint8_t wait) { int i, j; for (j=0; j < 256; j++) { // 3 cycles of all 256 colors in the Wheel for (i=0; i < strip.numPixels(); i++) { strip.setPixelColor(i, Wheel( (i + j) % 255)); } strip.show(); // write all the pixels out delay(wait); } } // fill the dots one after the other with said color // good for testing purposes // goes to the right void colorWipeRight(uint32_t c, uint8_t wait) { for (int i=0; i < strip.numPixels(); i++) { strip.setPixelColor(i, c); strip.show(); delay(wait); } } void colorWipeLeft(uint32_t c, uint8_t wait) { for (i=nLEDs; i > 0; i--) { strip.setPixelColor(i, c); strip.show(); delay(wait); } }