144 lines
3.6 KiB
C++
144 lines
3.6 KiB
C++
#include "Arduino_LED_Matrix.h"
|
|
|
|
#include "src/config.h"
|
|
#include "src/pong_render.h"
|
|
|
|
#include "src/paddle.h"
|
|
#include "src/ball.h"
|
|
#include "src/engine.h"
|
|
|
|
// create LED matrix object
|
|
ArduinoLEDMatrix matrix;
|
|
|
|
// initial pong frame matrix
|
|
byte frame[MATRIX_HEIGHT][MATRIX_WIDTH] = {
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
|
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
|
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
|
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
|
{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
|
|
};
|
|
|
|
int need_refresh= true;
|
|
uint8_t hits= 0;
|
|
uint8_t ball_delay= INITIAL_BALL_DELAY;
|
|
long exec_t2= millis();
|
|
|
|
enum game_statuses : uint8_t {
|
|
TIMER,
|
|
RUN,
|
|
SCORE,
|
|
GAMEOVER,
|
|
WAIT,
|
|
};
|
|
game_statuses game_status= TIMER;
|
|
|
|
Ball ball(4, 6);
|
|
Paddle p1(1);
|
|
Paddle p2(4);
|
|
Engine engine(p1, p2, ball);
|
|
|
|
void setup() {
|
|
Serial.begin(9600);
|
|
// start LED matrix
|
|
matrix.begin();
|
|
|
|
pinMode(P1_BTN_UP, INPUT_PULLUP);
|
|
pinMode(P1_BTN_BOTTOM, INPUT_PULLUP);
|
|
pinMode(P2_BTN_UP, INPUT_PULLUP);
|
|
pinMode(P2_BTN_BOTTOM, INPUT_PULLUP);
|
|
|
|
randomSeed(millis());
|
|
}
|
|
|
|
void loop() {
|
|
long exec_t1= millis();
|
|
|
|
switch (game_status) {
|
|
|
|
case TIMER:
|
|
for (int i = START_TIMER; i >= 0; i--) {
|
|
render_timer(frame, i);
|
|
matrix.renderBitmap(frame, MATRIX_HEIGHT, MATRIX_WIDTH);
|
|
delay(1000);
|
|
}
|
|
game_status= RUN;
|
|
// delay the first ball movement
|
|
exec_t2= millis() + FIRST_START_BALL_DELAY;
|
|
break;
|
|
|
|
case RUN:
|
|
if (digitalRead(P1_BTN_UP) == LOW) {
|
|
p1.move_pad_up();
|
|
need_refresh= true;
|
|
}
|
|
else if (digitalRead(P1_BTN_BOTTOM) == LOW) {
|
|
p1.move_pad_down();
|
|
need_refresh= true;
|
|
}
|
|
if (digitalRead(P2_BTN_UP) == LOW) {
|
|
p2.move_pad_up();
|
|
need_refresh= true;
|
|
}
|
|
else if (digitalRead(P2_BTN_BOTTOM) == LOW) {
|
|
p2.move_pad_down();
|
|
need_refresh= true;
|
|
}
|
|
if (exec_t1 - exec_t2 > ball_delay) {
|
|
engine.run();
|
|
if (engine.get_event() == P1SCORE || engine.get_event() == P2SCORE) {
|
|
game_status= SCORE;
|
|
// delay the ball movement after score
|
|
exec_t2= millis() + FIRST_START_BALL_DELAY + 1000;
|
|
}
|
|
else if (engine.get_event() == P1_COLLISION || engine.get_event() == P2_COLLISION) {
|
|
hits++;
|
|
if (hits >= 6 && ball_delay >= 80) {
|
|
hits= 0;
|
|
ball_delay-= 20;
|
|
exec_t2= exec_t1;
|
|
}
|
|
}
|
|
else exec_t2= exec_t1;
|
|
need_refresh= true;
|
|
}
|
|
// rerender matrix only if something is changed
|
|
if (need_refresh) {
|
|
render_matrix(frame, p1, p2, ball);
|
|
matrix.renderBitmap(frame, MATRIX_HEIGHT, MATRIX_WIDTH);
|
|
need_refresh= false;
|
|
}
|
|
break;
|
|
|
|
case SCORE:
|
|
render_score(frame, p1, p2);
|
|
matrix.renderBitmap(frame, MATRIX_HEIGHT, MATRIX_WIDTH);
|
|
ball.reset_position();
|
|
ball_delay= INITIAL_BALL_DELAY;
|
|
delay(1000);
|
|
if (p1.get_score() >= MAX_POINTS || p2.get_score() >= MAX_POINTS) {
|
|
game_status= GAMEOVER;
|
|
}
|
|
else game_status= RUN;
|
|
break;
|
|
|
|
case GAMEOVER:
|
|
render_winner(frame, matrix, p1, p2);
|
|
game_status= WAIT;
|
|
break;
|
|
|
|
case WAIT:
|
|
// keep showing the winner waiting for a restart
|
|
// restart game once one button is pressed
|
|
if (digitalRead(P1_BTN_UP) == LOW || digitalRead(P1_BTN_BOTTOM) == LOW || digitalRead(P2_BTN_UP) == LOW || digitalRead(P2_BTN_BOTTOM) == LOW) {
|
|
game_status= TIMER;
|
|
engine.reset();
|
|
}
|
|
break;
|
|
}
|
|
delay(50);
|
|
}
|