In: Electrical Engineering
This is a code for a bouncing ball on an 8X8 LED. How can i change the code to make it a ping pong game against AI by adding 1 potentionmeter to control it?
#include <TimerOne.h>//this is a library that uses timer 1 of the arduino to trigger interrupts in certain time intervals
//This defines a matrix defining a smiley face for the 8x8 LED
matrix display
#define BALL { \
{1, 0, 0, 0, 0, 0, 0, 0}, \
{0, 0, 0, 0, 0, 0, 0, 0}, \
{0, 0, 0, 0, 0, 0, 0, 0}, \
{0, 0, 0, 0, 0, 0, 0, 0}, \
{0, 0, 0, 0, 0, 0, 0, 0}, \
{0, 0, 0, 0, 0, 0, 0, 0}, \
{0, 0, 0, 0, 0, 0, 0, 0}, \
{0, 0, 0, 0, 0, 0, 0, 0} \
}
/*Arduino pin --> Display pin----->8x8 matrix row and column
coordinates (1;1) origin
D2-------------->9---------------------->row 1
D3-------------->10-------------------->col 4
D4-------------->11-------------------->col 6
D5-------------->12--------------------->row 4
D6-------------->13-------------------->col 1
D7-------------->14--------------------->row 2
D8-------------->15-------------------->col 7
D9-------------->16-------------------->col 8
D10------------->4--------------------->col 3
D11------------->3--------------------->col 2
D12------------->2---------------------->row 7
D13------------->1---------------------->row 5
A0 (D14)-------->5---------------------->row 8
A1 (D15)-------->6--------------------->col 5
A2 (D16)-------->7---------------------->row 6
A3 (D17)-------->8---------------------->row 3
*/
//rows:
const int col[8] = {
2,7,17,5,13,16,12,14 };//these are the Arduino pins that connect to
the anodes (1-8) of the LEDs
//columns:
const int row[8] = {
6,11,10,3,15,4,8,9 };//these are the Arduino pins that connect to
the cathodes (1-8) of the LEDs
int x = 0;
int y = 0;
int dx = 1;
int dy = 1;
volatile byte c,r,flag,counter;//interrupt routine variables, they need to be specified as 'volatile'
// 2-dimensional array that contains the currently 'ON' LEDs in
the matrix ('1'='ON'); this is used in the refreshScreen() ISR
below:
byte pattern[8][8] = BALL;
unsigned long previousMillis = 0; //last time we switched
patterns [ms]
unsigned long interval = 1000; //time between switching [ms]
int currentPattern = 0; //0 for "Ball", 1 for "Ball2", 2 for
"Ball3", 3 for "Ball4"
void setup() {
// initialize the row and column pins as outputs
// iterate through the pins:
for (int pin = 0; pin < 8; pin++) {
// initialize the output pins:
pinMode(col[pin], OUTPUT);
digitalWrite(col[pin], HIGH);
pinMode(row[pin], OUTPUT);
digitalWrite(row[pin], LOW);
// take the col pins (i.e. the cathodes) high and the row pins
(anodes) low to ensure that
// the LEDS are off:
}
Timer1.initialize(100); // initialize timer1, and set a 100 us
second period for the interrupt interval (i.e. the ISR will be
called
//every 100 us - this seems to be a good frequency to achieve a
flicker-free LED display.
//experiment with this parameter. If it gets too small the ISR
starts 'eating up' all the processor time, and the main loop
becomes very slow
Timer1.attachInterrupt(refreshScreen); // attaches the
refreshScreen() function as 'Interrupt Service Routine' (ISR) to
the interrupt
//this means that every time 100 us have passed, the
refreshScreen() routine will be called.
}
//main loop...here we can simply busy ourselves with changing
the pattern[][] array; nothing deals with the LED display.
//this is all handled via the ISR
void loop() {
if (x>=7)
{ dx = -1;
dy = random(-1,1);
}
if(x<=0)
{
dx = 1;
dy = random(-1,1);
}
if (y>=7)
{dy = -1;
dx = random(-1,1);
}
if (y<=0)
{ dy = 1;
dx = random(-1,1);
}
pattern[x][y] = 0;
pattern[x+dx][y+dy]=1;
x=x+dx;
y=y+dy;
delay(50);
#include "LedControl.h" #include "Timer.h" #define POTPIN A5 // Potentiometer #define PADSIZE 3 #define BALL_DELAY 200 #define GAME_DELAY 10 #define BOUNCE_VERTICAL 1 #define BOUNCE_HORIZONTAL -1 #define NEW_GAME_ANIMATION_SPEED 50 #define HIT_NONE 0 #define HIT_CENTER 1 #define HIT_LEFT 2 #define HIT_RIGHT 3 //#define DEBUG 1 byte sad[] = { B00000000, B01000100, B00010000, B00010000, B00000000, B00111000, B01000100, B00000000 }; byte smile[] = { B00000000, B01000100, B00010000, B00010000, B00010000, B01000100, B00111000, B00000000 }; Timer timer; LedControl lc = LedControl(12,11,10,1); byte direction; // Wind rose, 0 is north int xball; int yball; int yball_prev; byte xpad; int ball_timer; void setSprite(byte *sprite){ for(int r = 0; r < 8; r++){ lc.setRow(0, r, sprite[r]); } } void newGame() { lc.clearDisplay(0); // initial position xball = random(1, 7); yball = 1; direction = random(3, 6); // Go south for(int r = 0; r < 8; r++){ for(int c = 0; c < 8; c++){ lc.setLed(0, r, c, HIGH); delay(NEW_GAME_ANIMATION_SPEED); } } setSprite(smile); delay(1500); lc.clearDisplay(0); } void setPad() { xpad = map(analogRead(POTPIN), 0, 1020, 8 - PADSIZE, 0); } void debug(const char* desc){ #ifdef DEBUG Serial.print(desc); Serial.print(" XY: "); Serial.print(xball); Serial.print(", "); Serial.print(yball); Serial.print(" XPAD: "); Serial.print(xpad); Serial.print(" DIR: "); Serial.println(direction); #endif } int checkBounce() { if(!xball || !yball || xball == 7 || yball == 6){ int bounce = (yball == 0 || yball == 6) ? BOUNCE_HORIZONTAL : BOUNCE_VERTICAL; #ifdef DEBUG debug(bounce == BOUNCE_HORIZONTAL ? "HORIZONTAL" : "VERTICAL"); #endif return bounce; } return 0; } int getHit() { if(yball != 6 || xball < xpad || xball > xpad + PADSIZE){ return HIT_NONE; } if(xball == xpad + PADSIZE / 2){ return HIT_CENTER; } return xball < xpad + PADSIZE / 2 ? HIT_LEFT : HIT_RIGHT; } bool checkLoose() { return yball == 6 && getHit() == HIT_NONE; } void moveBall() { debug("MOVE"); int bounce = checkBounce(); if(bounce) { switch(direction){ case 0: direction = 4; break; case 1: direction = (bounce == BOUNCE_VERTICAL) ? 7 : 3; break; case 2: direction = 6; break; case 6: direction = 2; break; case 7: direction = (bounce == BOUNCE_VERTICAL) ? 1 : 5; break; case 5: direction = (bounce == BOUNCE_VERTICAL) ? 3 : 7; break; case 3: direction = (bounce == BOUNCE_VERTICAL) ? 5 : 1; break; case 4: direction = 0; break; } debug("->"); } // Check hit: modify direction is left or right switch(getHit()){ case HIT_LEFT: if(direction == 0){ direction = 7; } else if (direction == 1){ direction = 0; } break; case HIT_RIGHT: if(direction == 0){ direction = 1; } else if(direction == 7){ direction = 0; } break; } // Check orthogonal directions and borders ... if((direction == 0 && xball == 0) || (direction == 4 && xball == 7)){ direction++; } if(direction == 0 && xball == 7){ direction = 7; } if(direction == 4 && xball == 0){ direction = 3; } if(direction == 2 && yball == 0){ direction = 3; } if(direction == 2 && yball == 6){ direction = 1; } if(direction == 6 && yball == 0){ direction = 5; } if(direction == 6 && yball == 6){ direction = 7; } // "Corner" case if(xball == 0 && yball == 0){ direction = 3; } if(xball == 0 && yball == 6){ direction = 1; } if(xball == 7 && yball == 6){ direction = 7; } if(xball == 7 && yball == 0){ direction = 5; } yball_prev = yball; if(2 < direction && direction < 6) { yball++; } else if(direction != 6 && direction != 2) { yball--; } if(0 < direction && direction < 4) { xball++; } else if(direction != 0 && direction != 4) { xball--; } xball = max(0, min(7, xball)); yball = max(0, min(6, yball)); debug("AFTER MOVE"); } void gameOver() { setSprite(sad); delay(1500); lc.clearDisplay(0); } void drawGame() { if(yball_prev != yball){ lc.setRow(0, yball_prev, 0); } lc.setRow(0, yball, byte(1 << (xball))); byte padmap = byte(0xFF >> (8 - PADSIZE) << xpad) ; #ifdef DEBUG //Serial.println(padmap, BIN); #endif lc.setRow(0, 7, padmap); } void setup() { // The MAX72XX is in power-saving mode on startup, // we have to do a wakeup call pinMode(POTPIN, INPUT); lc.shutdown(0,false); // Set the brightness to a medium values lc.setIntensity(0, 8); // and clear the display lc.clearDisplay(0); randomSeed(analogRead(0)); #ifdef DEBUG Serial.begin(9600); Serial.println("Pong"); #endif newGame(); ball_timer = timer.every(BALL_DELAY, moveBall); } void loop() { timer.update(); // Move pad setPad(); #ifdef DEBUG Serial.println(xpad); #endif // Update screen drawGame(); if(checkLoose()) { debug("LOOSE"); gameOver(); newGame(); } delay(GAME_DELAY); }