Last active
March 23, 2017 23:14
-
-
Save giljr/41ba8a69efb26a74d06234f3ae07d517 to your computer and use it in GitHub Desktop.
Ping_Pong Game - Final & Complete Version - Visit Jungletronics: https://goo.gl/ON9NIr
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define AUTOPLAY true | |
byte imageMem[8] = { // display buffer | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | |
}; | |
float speed_x = 1; // ball variables: speed & positions(pos_x/pos_y) | |
float speed_y = 0.5; // transversal speed (y axis) | |
float pos_x = 0; // ball position in axis | |
float pos_y = 4; // Range for the complete paddle bat design from 1 up to 6 | |
float paddle_l, paddle_r; // paddle positions | |
int n; // display row counter | |
void setup() { | |
for (int z = 2; z < 14; z++) { | |
pinMode(z, OUTPUT); // all pins output for driving the LED matrix | |
} | |
TCCR2A = 0; // no ocr or pwm; intitialize interrupt timer 2 | |
TCCR2B = 4; // 1<<CS22 | 0<<CS21 | 0<<CS20 -- for clock div 64 | |
TIMSK2 = 1 << TOIE2; // enable timer 1 interrupt | |
TCNT2 = 0x06; // 1 kHz - see datasheet (https://goo.gl/k7tXKa) | |
} | |
void loop() { | |
float paddle = analogRead(0)/116; // use one paddle variable; see variable definition above | |
if (AUTOPLAY){ | |
if (speed_x==-1) paddle_l = pos_y; //** autoplay mode never misses!!! | |
else paddle_r = pos_y; //** The paddle bat always chases the ball along the y axis... | |
} | |
else { | |
if (speed_x==-1) paddle_l = paddle; //** (swap who's controlling the paddle) | |
else paddle_r = paddle; //** Or the paddle bat passes to the user's command | |
} | |
if ((pos_x > 6) && (speed_x == 1) && (pos_y < (paddle_r + 1)) && (pos_y > (paddle_r - 1))) { | |
speed_x = -1; // reverse direction when hitting the right bat | |
} | |
if ((pos_x < 1) && (speed_x == -1) && (pos_y < (paddle_l + 1)) && (pos_y > (paddle_l - 1))) { | |
speed_x = 1; // reverse direction when hitting the left bat | |
} | |
pos_x += speed_x; //** We add velocity on the x-axis to make the ball touch the walls | |
// and not just follow in a straight line; | |
// From now on the ball makes angles with the walls. | |
// For the ball does not escape let's make two ifs to hold it inside | |
pos_y += speed_y; // We add the y position so that the racket follows the ball | |
// in two dimensions: x and y axis | |
if(pos_y >6) { //** ceiling | |
speed_y = speed_y * -1; | |
} | |
if(pos_y <1) { //** bottom | |
speed_y = speed_y * -1; | |
} | |
if(pos_x<0){ // ball is out left: right can serve | |
pos_x=6; // works only out of autoplay mode .. | |
pos_y=paddle_r; | |
speed_x=-1; | |
speed_y = (float)random(0,10)/10; | |
} | |
if(pos_x>7) { // ball is out right: left can serve | |
pos_x=1; // works only out of autoplay mode .. | |
pos_y=paddle_l; | |
speed_x=1; | |
speed_y = (float)random(0,10)/10; | |
} | |
clearScreen(); | |
drawBall((int)pos_x, (int)pos_y); | |
drawBats((int)paddle_l, (int)paddle_r); | |
//delay(50); // how fast are the ball...You can change | |
delay(200); //to fifty and see full speed ball... | |
} | |
void drawBats(int l, int r) { // draw bats by number 3d = 0000 0011 - draw right paddle bat. | |
imageMem[7] = (3 << l) >> 1; // shift 0011 left by 'int l'[0..7] and then shift result by 1 | |
// see: suppose l = 7 -> (0000 0011 << 7) >> 1 results 0110 0000 | |
imageMem[0] = (3 << r) >> 1; // same as above, except by r [0..7] value - draw right paddle bat. | |
// draw bats in imageMem like this [][][][][1][1][][] see diagram | |
} | |
void drawBall(int x, int y) { // Draw a bit of the ball in any of the positions that appear | |
// asterisk in the imageMem [][*][*][*][*][*][*][] | |
imageMem[7 - x] = 1 << y; // draw the ball is very easy, just get its positions inside imageMem | |
// And dumps the six bytes at each delay ms from loop() | |
} | |
void clearScreen() { | |
for (int z = 0; z < 8; z++) { // clear all bytes in imageMem, this routine is called to | |
// each loop, thus zeroing 8 bytes to new scene stage. see simulation images | |
imageMem[z] = 0x00; | |
} | |
} | |
ISR(TIMER2_OVF_vect) { // see complete anotation on code I | |
TCNT2 = 0x06; // reload timer at 1kHz | |
PORTD &= 0xE3; // clear PIN 2,3,4 | |
PORTD |= (n << 2) & 0x1C; // set collumn trough the mux | |
PORTD &= 0x1F; // clear PIN 5,6,7 | |
PORTD |= (imageMem[n] << 5) & 0xE0; // set row data on 5,6,7 | |
PORTB &= 0xE0; // clear PIN 8,9,10,11,12 | |
PORTB |= (imageMem[n] >> 3) & 0x1F; // set row data on 8-12 | |
n++; // increase collumn counter | |
if (n > 7) { | |
n = 0; // next image. Refreshrate = 1000/8 images/sec | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment