Files
arduino_pong/arduino_pong.ino

122 lines
3.0 KiB
Arduino
Raw Normal View History

#include "Arduino_LED_Matrix.h"
2026-03-15 21:14:04 +01:00
#include "src/config.h"
2026-03-18 19:46:52 +01:00
#include "src/renderer.h"
#include "src/engine.h"
2026-03-17 23:25:30 +01:00
#include "src/paddle.h"
#include "src/ball.h"
2026-03-15 20:29:56 +01:00
// initial pong frame matrix
2026-03-15 17:07:03 +01:00
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 },
2026-03-15 20:29:56 +01:00
{ 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 }
};
2026-03-18 19:46:52 +01:00
ArduinoLEDMatrix matrix;
bool need_refresh= true;
2026-03-18 18:12:38 +01:00
uint8_t hits= 0;
long exec_t2= millis();
enum game_statuses : uint8_t {
TIMER,
RUN,
SCORE,
GAMEOVER,
WAIT,
};
game_statuses game_status= TIMER;
2026-03-17 23:25:30 +01:00
Ball ball(4, 6);
// HumanPaddle p1(1, P1_BTN_UP, P1_BTN_BOTTOM);
// HumanPaddle p2(4, P2_BTN_UP, P2_BTN_BOTTOM);
BotPaddle p1(1, 0, 1);
BotPaddle p2(4, MATRIX_WIDTH-1, 1);
Engine engine(p1, p2, ball, INITIAL_BALL_DELAY);
2026-03-18 19:46:52 +01:00
Renderer renderer(p1, p2, ball, frame, matrix);
2026-03-15 20:29:56 +01:00
void setup() {
Serial.begin(9600);
2026-03-15 20:29:56 +01:00
// 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);
2026-03-15 20:29:56 +01:00
randomSeed(millis());
}
void loop() {
long exec_t1= millis();
switch (game_status) {
2026-03-17 23:25:30 +01:00
case TIMER:
for (int i = START_TIMER; i >= 0; i--) {
2026-03-18 19:46:52 +01:00
renderer.render_timer(i);
2026-03-18 18:24:52 +01:00
delay(1000);
}
game_status= RUN;
// delay the first ball movement
exec_t2= millis() + FIRST_START_BALL_DELAY;
break;
case RUN:
// need_refresh= check_paddle_movements(p1, p2);
need_refresh= engine.control_players();
2026-03-18 19:00:50 +01:00
if (exec_t1 - exec_t2 > engine.ball_movement_delay()) {
2026-03-18 18:12:38 +01:00
engine.run();
if (engine.get_event() == P1SCORE || engine.get_event() == P2SCORE)
game_status= SCORE;
2026-03-18 19:00:50 +01:00
exec_t2= exec_t1;
2026-03-18 18:12:38 +01:00
need_refresh= true;
}
// rerender matrix only if something is changed
if (need_refresh) {
2026-03-18 19:46:52 +01:00
renderer.render_matrix();
2026-03-17 23:25:30 +01:00
need_refresh= false;
}
break;
case SCORE:
delay(300);
2026-03-18 19:46:52 +01:00
renderer.render_score();
engine.restart_ball();
2026-03-18 19:00:50 +01:00
delay(1000);
if (p1.get_score() >= MAX_POINTS || p2.get_score() >= MAX_POINTS)
game_status= GAMEOVER;
2026-03-18 19:00:50 +01:00
else {
game_status= RUN;
// before move again the ball wait a second
2026-03-18 19:46:52 +01:00
renderer.render_matrix();
exec_t2= millis() + FIRST_START_BALL_DELAY;
2026-03-18 19:00:50 +01:00
}
break;
case GAMEOVER:
2026-03-18 19:46:52 +01:00
renderer.render_winner();
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;
2026-03-17 23:25:30 +01:00
engine.reset();
}
break;
}
2026-03-18 18:24:52 +01:00
delay(50);
2026-03-14 21:35:19 +01:00
}