24 Commits

Author SHA1 Message Date
andrea 33e070c442 added renderer.cpp/h files 2026-03-18 20:38:31 +01:00
andrea 1f6e65c5ec renderer class 2026-03-18 19:46:52 +01:00
andrea 7afa70c9d8 fix ball bouncing on pad behavior
now the ball bounces on pad when hit the pad, not when it reaches the edge of the "screen"
2026-03-18 19:12:09 +01:00
andrea 792c0f835c clean main sketch file 2026-03-18 19:00:50 +01:00
andrea 5afa726015 minors 2026-03-18 18:24:52 +01:00
andrea 48fef4be86 move some logics to loop() 2026-03-18 18:12:38 +01:00
andrea 48c2610561 TODO 2026-03-17 23:43:37 +01:00
andrea 3d8881ab3d total reframe with classes 2026-03-17 23:25:30 +01:00
andrea d8efabd6da start refactoring pong entities to use classes 2026-03-17 20:11:21 +01:00
andrea c774e11923 Improve arduino_pong.ino using enum to handle game statuses and switch case for better readibility and little memory improvements
Arduino Pong CI / build (macos-latest) (push) Has been cancelled
Arduino Pong CI / build (ubuntu-latest) (push) Has been cancelled
Arduino Pong CI / build (windows-latest) (push) Has been cancelled
Arduino Pong CD / release (push) Has been cancelled
2026-03-17 18:42:48 +01:00
andrea b3f6aeb3fe Show scores on the matrix, show winner message once someone reches 9, add start ball movement delay on start and restart after score, and fix uncentered ball on restart
Arduino Pong CI / build (macos-latest) (push) Has been cancelled
Arduino Pong CI / build (ubuntu-latest) (push) Has been cancelled
Arduino Pong CI / build (windows-latest) (push) Has been cancelled
2026-03-16 22:37:53 +01:00
andrea 6e5fc8ea10 change digital pins to avoid collisions with pin13 for L Led on the board
Arduino Pong CI / build (macos-latest) (push) Has been cancelled
Arduino Pong CI / build (ubuntu-latest) (push) Has been cancelled
Arduino Pong CI / build (windows-latest) (push) Has been cancelled
Arduino Pong CD / release (push) Has been cancelled
2026-03-15 22:43:00 +01:00
andrea 28f029ce03 update ci.yml with new libs structure
Arduino Pong CI / build (ubuntu-latest) (push) Has been cancelled
Arduino Pong CI / build (macos-latest) (push) Has been cancelled
Arduino Pong CI / build (windows-latest) (push) Has been cancelled
2026-03-15 21:15:49 +01:00
andrea cb42a45aa7 move all libs into src
Arduino Pong CI / build (macos-latest) (push) Has been cancelled
Arduino Pong CI / build (ubuntu-latest) (push) Has been cancelled
Arduino Pong CI / build (windows-latest) (push) Has been cancelled
2026-03-15 21:14:04 +01:00
andrea c47291e258 minors
Arduino Pong CI / build (ubuntu-latest) (push) Has been cancelled
Arduino Pong CI / build (windows-latest) (push) Has been cancelled
Arduino Pong CI / build (macos-latest) (push) Has been cancelled
Arduino Pong CD / release (push) Has been cancelled
2026-03-15 20:29:56 +01:00
andrea fec4db0c5d improve rerender logics
Arduino Pong CI / build (macos-latest) (push) Has been cancelled
Arduino Pong CI / build (ubuntu-latest) (push) Has been cancelled
Arduino Pong CI / build (windows-latest) (push) Has been cancelled
2026-03-15 20:23:52 +01:00
andrea 7c065d8799 updated ci.yml
Arduino Pong CI / build (macos-latest) (push) Has been cancelled
Arduino Pong CI / build (ubuntu-latest) (push) Has been cancelled
Arduino Pong CI / build (windows-latest) (push) Has been cancelled
2026-03-15 20:09:21 +01:00
andrea 31891bbc0e minors
Arduino Pong CD / release (push) Has been cancelled
2026-03-15 20:02:27 +01:00
andrea 5eeb735364 split main .ino fine into multiple sub files
Arduino Pong CI / build (macos-latest) (push) Has been cancelled
Arduino Pong CI / build (ubuntu-latest) (push) Has been cancelled
Arduino Pong CI / build (windows-latest) (push) Has been cancelled
2026-03-15 19:56:20 +01:00
andrea a938adff31 generate build files for cd
Arduino Pong CI / build (macos-latest) (push) Has been cancelled
Arduino Pong CI / build (ubuntu-latest) (push) Has been cancelled
Arduino Pong CI / build (windows-latest) (push) Has been cancelled
Arduino Pong CD / release (push) Has been cancelled
2026-03-15 18:19:48 +01:00
andrea 1f143520a8 add cd status on README 2026-03-15 18:13:58 +01:00
andrea cbdfcce354 cd permissions
Arduino Pong CD / release (push) Has been cancelled
2026-03-15 18:11:53 +01:00
andrea 66957b5e19 remove unecessary lib from cd
Arduino Pong CD / release (push) Has been cancelled
2026-03-15 18:09:13 +01:00
andrea f12af76845 minor
Arduino Pong CD / release (push) Has been cancelled
2026-03-15 18:07:15 +01:00
17 changed files with 678 additions and 182 deletions
+5 -3
View File
@@ -5,6 +5,9 @@ on:
tags: tags:
- 'v*' - 'v*'
permissions:
contents: write
jobs: jobs:
release: release:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -15,13 +18,12 @@ jobs:
- name: Install Arduino CLI - name: Install Arduino CLI
run: | run: |
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh
echo "$HOME/bin" >> $GITHUB_PATH echo "./bin" >> $GITHUB_PATH
- name: Install Board Core and Libs - name: Install Board Core and Libs
run: | run: |
arduino-cli core update-index arduino-cli core update-index
arduino-cli core install arduino:renesas_uno arduino-cli core install arduino:renesas_uno
arduino-cli lib install "Arduino_LED_Matrix"
- name: Build Binary - name: Build Binary
run: make compile run: make compile
@@ -30,6 +32,6 @@ jobs:
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
with: with:
files: | files: |
build/arduino.renesas_uno.unor4wifi/arduino_pong.ino.bin build/*.bin
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+2
View File
@@ -7,6 +7,8 @@ on:
- 'arduino_pong.ino' - 'arduino_pong.ino'
- 'Makefile' - 'Makefile'
- '.github/workflows/ci.yml' - '.github/workflows/ci.yml'
- 'src/*.cpp'
- 'src/*.h'
jobs: jobs:
build: build:
+1
View File
@@ -1,3 +1,4 @@
.secrets .secrets
.arduino_cache/ .arduino_cache/
bin/ bin/
build/
+6 -1
View File
@@ -30,8 +30,13 @@ prepare:
fi fi
compile: compile:
@mkdir -p build
@echo -e "$(GREEN)🛠️ Compiling $(SKETCH)...$(CLEAR)" @echo -e "$(GREEN)🛠️ Compiling $(SKETCH)...$(CLEAR)"
@$(CLI) compile -b $(BOARD) $(SKETCH) @$(CLI) compile -b $(BOARD) --output-dir build $(SKETCH)
clean:
@echo -e "$(GREEN)🛠️ Removing build files...$(CLEAR)"
@rm -rf build/
prepare_and_compile: prepare_and_compile:
make prepare --no-print-directory make prepare --no-print-directory
+2 -1
View File
@@ -3,11 +3,12 @@
A classic implementation of the Pong game developed specifically for the Arduino UNO R4 WiFi, utilizing its built-in 12×8 LED matrix as the game screen. A classic implementation of the Pong game developed specifically for the Arduino UNO R4 WiFi, utilizing its built-in 12×8 LED matrix as the game screen.
[![Arduino Pong CI](https://github.com/Dea1993/arduino_pong/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/Dea1993/arduino_pong/actions/workflows/ci.yml) [![Arduino Pong CI](https://github.com/Dea1993/arduino_pong/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/Dea1993/arduino_pong/actions/workflows/ci.yml)
[![Arduino Pong CD](https://github.com/Dea1993/arduino_pong/actions/workflows/cd.yml/badge.svg)](https://github.com/Dea1993/arduino_pong/actions/workflows/cd.yml)
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](LICENSE) [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](LICENSE)
# 📹 Preview # 📹 Preview
![Pong](preview.png) ![Pong](assets/preview.png)
Youtube: https://youtu.be/ouLBTDjpKqc Youtube: https://youtu.be/ouLBTDjpKqc
+98 -177
View File
@@ -1,208 +1,129 @@
#include "Arduino_LED_Matrix.h" #include "Arduino_LED_Matrix.h"
#define P1_BTN_UP 13 #include "src/config.h"
#define P1_BTN_BOTTOM 12 #include "src/renderer.h"
#define P2_BTN_UP 11 #include "src/engine.h"
#define P2_BTN_BOTTOM 10 #include "src/paddle.h"
#define MATRIX_WIDTH 12 #include "src/ball.h"
#define MATRIX_HEIGHT 8
// create LED matrix object
ArduinoLEDMatrix matrix;
// initial pong frame // initial pong frame matrix
byte frame[MATRIX_HEIGHT][MATRIX_WIDTH] = { byte frame[MATRIX_HEIGHT][MATRIX_WIDTH] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 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 }, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 }, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, { 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, 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, 0, 0, 0, 0, 0, 0, 0 }
}; };
// players coordinates ArduinoLEDMatrix matrix;
int p1_start= 1;
int p1_end= 3;
int p2_start= 4;
int p2_end= 6;
// initials balls coordinates
int ball_reset_x= MATRIX_WIDTH / 2;
int ball_reset_y= MATRIX_HEIGHT / 2;
int ball_x= ball_reset_x;
int ball_y= ball_reset_y;
// initially ball has no movements
// once game/round starts, balls gets random x and y movements
int ball_move_x= 0;
int ball_move_y= 0;
int bar_length= 3;
int p1_score= 0;
int p2_score= 0;
int need_refresh= 1;
int initial_loop_delay= 200;
int loop_delay= initial_loop_delay;
// used to increase speed when game is too easy
int hits= 0;
int need_refresh= true;
uint8_t hits= 0;
uint8_t ball_delay= INITIAL_BALL_DELAY;
long exec_t2= millis(); 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);
Renderer renderer(p1, p2, ball, frame, matrix);
void setup() { void setup() {
//Serial.begin(115200);
Serial.begin(9600); Serial.begin(9600);
// stard LED matrix // start LED matrix
matrix.begin(); matrix.begin();
pinMode(P1_BTN_UP, INPUT_PULLUP); pinMode(P1_BTN_UP, INPUT_PULLUP);
pinMode(P1_BTN_BOTTOM, INPUT_PULLUP); pinMode(P1_BTN_BOTTOM, INPUT_PULLUP);
pinMode(P2_BTN_UP, INPUT_PULLUP); pinMode(P2_BTN_UP, INPUT_PULLUP);
pinMode(P2_BTN_BOTTOM, INPUT_PULLUP); pinMode(P2_BTN_BOTTOM, INPUT_PULLUP);
randomSeed(analogRead(0)); randomSeed(millis());
}
void render_matrix() {
if (!need_refresh) return;
need_refresh= 0;
// clear
for (int x=0; x < MATRIX_WIDTH; x++) {
for (int y=0; y < MATRIX_HEIGHT; y++) {
frame[y][x]= 0;
}
}
// players coords
for (int i= p1_start; i < p1_start+bar_length; i++) {
frame[i][0]= 1;
}
for (int i= p2_start; i < p2_start+bar_length; i++) {
frame[i][MATRIX_WIDTH-1]= 1;
}
// ball coords
frame[ball_y][ball_x]= 1;
matrix.renderBitmap(frame, MATRIX_HEIGHT, MATRIX_WIDTH);
}
void pong_move_p1() {
if (digitalRead(P1_BTN_UP) == LOW && p1_start > 0) {
p1_start -= 1;
need_refresh= 1;
}
else if (digitalRead(P1_BTN_BOTTOM) == LOW && p1_start < 5) {
p1_start += 1;
need_refresh= 1;
}
}
void pong_move_p2() {
if (digitalRead(P2_BTN_UP) == LOW && p2_start > 0) {
p2_start -= 1;
need_refresh= 1;
}
else if (digitalRead(P2_BTN_BOTTOM) == LOW && p2_start < 5) {
p2_start += 1;
need_refresh= 1;
}
}
int ball_player_collision(int player) {
for (int p= player; p < player + bar_length; p++) {
if (ball_y == p) {
return 1;
}
}
return 0;
}
void point_scored() {
ball_x= ball_reset_x;
ball_y= ball_reset_y;
Serial.print("P1: ");
Serial.print(p1_score);
Serial.print(" - ");
Serial.print("P2: ");
Serial.print(p2_score);
Serial.println();
hits= 0;
loop_delay= initial_loop_delay;
}
void move_ball() {
need_refresh= 1;
if (ball_x < 0 || ball_x > MATRIX_WIDTH-1 || ball_y < 0 || ball_y > MATRIX_HEIGHT-1) {
// ball out of matrix limits
ball_x= ball_reset_x;
ball_y= ball_reset_y;
return;
}
// if ball is not moving, get random direction
// this is the initial position
if (ball_move_x == 0 || ball_move_y == 0) {
// extract random number between 0 or 1 to select the directions
if (random(2) == 0) ball_move_x= 1;
else ball_move_x= -1;
if (random(2) == 0) ball_move_y= 1;
else ball_move_y= -1;
}
else if (ball_x == 0) {
// if p1 collision: reverse x, go left
if (!ball_player_collision(p1_start)) {
// else p2 score, reset board
p2_score += 1;
Serial.println("Player 2 Scores");
point_scored();
}
else {
hits += 1;
ball_move_x= ball_move_x * -1;
}
}
else if (ball_x == MATRIX_WIDTH-1) {
if (!ball_player_collision(p2_start)) {
// else p1 score, reset board
p1_score += 1;
Serial.println("Player 1 Scores");
point_scored();
}
else {
hits += 1;
ball_move_x= ball_move_x * -1;
}
}
if (ball_y == 0 || ball_y == MATRIX_HEIGHT-1) {
// reverse y, go down
ball_move_y= ball_move_y * -1;
}
if (hits >= 6 && loop_delay >= 80) {
// increase ball speed
hits = 0;
loop_delay -= 20;
}
ball_x+= ball_move_x;
ball_y+= ball_move_y;
} }
void loop() { void loop() {
long exec_t1= millis(); long exec_t1= millis();
pong_move_p1();
pong_move_p2(); switch (game_status) {
render_matrix();
if (exec_t1 - exec_t2 > loop_delay) { case TIMER:
move_ball(); for (int i = START_TIMER; i >= 0; i--) {
exec_t2= exec_t1; renderer.render_timer(i);
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);
if (exec_t1 - exec_t2 > ball_delay) {
engine.run();
if (engine.get_event() == P1SCORE || engine.get_event() == P2SCORE) {
game_status= SCORE;
}
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;
need_refresh= true;
}
// rerender matrix only if something is changed
if (need_refresh) {
renderer.render_matrix();
need_refresh= false;
}
break;
case SCORE:
delay(300); // small delay to let see the last ball position
renderer.render_score();
delay(1000);
ball.reset_position();
ball_delay= INITIAL_BALL_DELAY;
if (p1.get_score() >= MAX_POINTS || p2.get_score() >= MAX_POINTS) {
game_status= GAMEOVER;
}
else {
game_status= RUN;
// before move again the ball wait a second
renderer.render_matrix();
delay(1000);
}
break;
case GAMEOVER:
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;
engine.reset();
}
break;
} }
delay(50); delay(50);
} }
View File

Before

Width:  |  Height:  |  Size: 847 KiB

After

Width:  |  Height:  |  Size: 847 KiB

+46
View File
@@ -0,0 +1,46 @@
#include <Arduino.h>
#include <stdint.h>
#include "config.h"
#include "ball.h"
void Ball::_init_directions(int8_t &_direction) {
if (random(2) == 0) _direction= 1;
else _direction= -1;
}
void Ball::move() {
if (!_direction_x) this -> _init_directions(_direction_x);
if (!_direction_y) this -> _init_directions(_direction_y);
// if (_x < 0 || _x > MATRIX_WIDTH-1 || _y < 0 || _y > MATRIX_HEIGHT-1) {
// this -> reset_position();
// }
if (_x + _direction_x >= 0 && _x + _direction_x < MATRIX_WIDTH)
_x+= _direction_x;
if (_y + _direction_y >= 0 && _y + _direction_y < MATRIX_HEIGHT)
_y+= _direction_y;
}
void Ball::bounce_on_pad() {
_direction_x *= -1;
}
void Ball::bounce_on_sides() {
_direction_y *= -1;
}
void Ball::reset_position () {
_x= BALL_RESET_X;
_y= BALL_RESET_Y;
this -> _init_directions(_direction_x);
this -> _init_directions(_direction_y);
}
uint8_t Ball::get_x() {
return _x;
}
uint8_t Ball::get_y() {
return _y;
}
+25
View File
@@ -0,0 +1,25 @@
#ifndef BALL_H
#define BALL_H
#include <stdint.h>
#include "config.h"
class Ball {
private:
uint8_t _x, _y;
int8_t _direction_x, _direction_y;
void _init_directions(int8_t &_direction);
public:
Ball (uint8_t _x, uint8_t _y) : _x(_x), _y(_y) {}
void move();
void bounce_on_pad();
void bounce_on_sides();
void reset_position ();
uint8_t get_x();
uint8_t get_y();
};
#endif
+15
View File
@@ -0,0 +1,15 @@
#define P1_BTN_UP 12
#define P1_BTN_BOTTOM 11
#define P2_BTN_UP 10
#define P2_BTN_BOTTOM 9
#define MATRIX_WIDTH 12
#define MATRIX_HEIGHT 8
#define BALL_RESET_X (MATRIX_WIDTH / 2)
#define BALL_RESET_Y (MATRIX_HEIGHT / 2)
#define PADDLE_LENGTH 3
#define INITIAL_BALL_DELAY 200
#define MAX_POINTS 9
#define START_TIMER 3
#define FIRST_START_BALL_DELAY 500
+74
View File
@@ -0,0 +1,74 @@
#include "engine.h"
bool Engine::_check_pad_ball_collision(Paddle &p) {
uint8_t ppos= p.get_position();
for (int p= ppos; p < ppos + PADDLE_LENGTH; p++) {
if (_ball.get_y() == p) {
return true;
}
}
return false;
}
void Engine::_print_score() {
Serial.print("P1: ");
Serial.print(_p1.get_score());
Serial.print(" - ");
Serial.print("P2: ");
Serial.print(_p2.get_score());
Serial.println();
}
void Engine::run() {
_event= NONE;
_ball.move();
uint8_t bx= _ball.get_x();
uint8_t by= _ball.get_y();
// pad is 1 pixel far from the edge, so i need to calc this delta
if (bx <= 1) {
// score the point only if ball reached the edge
if (this -> _check_pad_ball_collision(_p1) && bx == 1) {
_ball.bounce_on_pad();
_event= P2_COLLISION;
}
else if (bx <= 0) {
// p2 scores
_p2.increase_score();
Serial.println("Player 2 Scores");
this -> _print_score();
_event= P2SCORE;
return;
}
}
else if (bx >= MATRIX_WIDTH-2) {
// score the point only if ball reached the edge
if (this -> _check_pad_ball_collision(_p2) && bx == MATRIX_WIDTH-2) {
_ball.bounce_on_pad();
_event= P1_COLLISION;
}
else if (bx >= MATRIX_WIDTH-1) {
// p1 scores
_p1.increase_score();
Serial.println("Player 1 Scores");
this -> _print_score();
_event= P1SCORE;
return;
}
}
if (by == 0 || by == MATRIX_HEIGHT-1) {
_ball.bounce_on_sides();
_event= WALL_COLLISION;
}
}
EngineEvents Engine::get_event() {
return _event;
}
void Engine::reset() {
_p1.reset();
_p2.reset();
_ball.reset_position();
}
+32
View File
@@ -0,0 +1,32 @@
#ifndef ENGINE_H
#define ENGINE_H
#include <Arduino.h>
#include "ball.h"
#include "paddle.h"
#include "config.h"
enum EngineEvents : uint8_t {NONE, P1SCORE, P2SCORE, P1_COLLISION, P2_COLLISION, WALL_COLLISION};
class Engine {
private:
Paddle& _p1;
Paddle& _p2;
Ball& _ball;
EngineEvents _event= NONE;
bool _check_pad_ball_collision(Paddle &p);
void _print_score();
public:
// inizialize Engine constructor, linking all args with private args
Engine(Paddle &p_one, Paddle &p_two, Ball &ball)
: _p1(p_one), _p2(p_two), _ball(ball) {}
void run();
EngineEvents get_event();
void reset();
};
#endif
+184
View File
@@ -0,0 +1,184 @@
#ifndef FONT_H
#define FONT_H
#include <Arduino.h>
const uint32_t pone_wins[][4] = {
{
0x78,
0xc4847844,
0x440e000,
500
},
{
0x11,
0x1101501,
0x501f0000,
500
},
{
0xe,
0x400400,
0x400e0000,
500
},
{
0x9,
0xd00b00,
0x90090000,
500
},
{
0xf,
0x800f00,
0x100f0000,
500
}
};
const uint32_t ptwo_wins[][4] = {
{
0x79,
0xe48279e4,
0x1041e000,
500
},
{
0x11,
0x1101501,
0x501f0000,
500
},
{
0xe,
0x400400,
0x400e0000,
500
},
{
0x9,
0xd00b00,
0x90090000,
500
},
{
0xf,
0x800f00,
0x100f0000,
500
}
};
const byte font_pong[10][8][3] = {
// Number 0
{
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 1, 1, 1 },
{ 1, 0, 1 },
{ 1, 0, 1 },
{ 1, 0, 1 },
{ 1, 1, 1 },
{ 0, 0, 0 }
},
// Number 1
{
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 1, 1, 0 },
{ 0, 1, 0 },
{ 0, 1, 0 },
{ 0, 1, 0 },
{ 1, 1, 1 },
{ 0, 0, 0 }
},
// Number 2
{
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 1, 1, 1 },
{ 0, 0, 1 },
{ 1, 1, 1 },
{ 1, 0, 0 },
{ 1, 1, 1 },
{ 0, 0, 0 }
},
// Number 3
{
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 1, 1, 1 },
{ 0, 0, 1 },
{ 1, 1, 1 },
{ 0, 0, 1 },
{ 1, 1, 1 },
{ 0, 0, 0 }
},
// Number 4
{
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 1, 0, 1 },
{ 1, 0, 1 },
{ 1, 1, 1 },
{ 0, 0, 1 },
{ 0, 0, 1 },
{ 0, 0, 0 }
},
// Number 5
{
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 1, 1, 1 },
{ 1, 0, 0 },
{ 1, 1, 1 },
{ 0, 0, 1 },
{ 1, 1, 1 },
{ 0, 0, 0 }
},
// Number 6
{
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 1, 0, 0 },
{ 1, 0, 0 },
{ 1, 1, 1 },
{ 1, 0, 1 },
{ 1, 1, 1 },
{ 0, 0, 0 }
},
// Number 7
{
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 1, 1, 1 },
{ 0, 0, 1 },
{ 0, 0, 1 },
{ 0, 0, 1 },
{ 0, 0, 1 },
{ 0, 0, 0 }
},
// Number 8
{
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 1, 1, 1 },
{ 1, 0, 1 },
{ 1, 1, 1 },
{ 1, 0, 1 },
{ 1, 1, 1 },
{ 0, 0, 0 }
},
// Number 9
{
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 1, 1, 1 },
{ 1, 0, 1 },
{ 1, 1, 1 },
{ 0, 0, 1 },
{ 0, 0, 1 },
{ 0, 0, 0 }
},
};
#endif
+54
View File
@@ -0,0 +1,54 @@
#include "paddle.h"
void Paddle::move_pad_up() {
if (_position > 0) {
_position -= 1;
}
}
void Paddle::move_pad_down() {
if (_position + _height < MATRIX_HEIGHT) {
_position += 1;
}
}
uint8_t Paddle::get_position() {
return _position;
}
bool Paddle::is_human() {
return _human;
}
void Paddle::increase_score() {
if (_score <= 9) _score += 1;
}
uint8_t Paddle::get_score() {
return _score;
}
void Paddle::reset() {
_score= 0;
}
bool check_paddle_movements(Paddle &p1, Paddle &p2) {
bool need_refresh= false;
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;
}
return need_refresh;
}
+29
View File
@@ -0,0 +1,29 @@
#ifndef PADDLE_H
#define PADDLE_H
#include <Arduino.h>
#include "config.h"
class Paddle {
private:
// define player coordinates
uint8_t _position;
uint8_t _height= PADDLE_LENGTH;
uint8_t _score= 0;
bool _human= true;
public:
Paddle (uint8_t _position) : _position(_position) {}
void move_pad_up();
void move_pad_down();
uint8_t get_position();
bool is_human();
void increase_score();
uint8_t get_score();
void reset();
};
bool check_paddle_movements(Paddle &p1, Paddle &p2);
#endif
+72
View File
@@ -0,0 +1,72 @@
#include "renderer.h"
void Renderer::_clear_matrix() {
for (int x=0; x < MATRIX_WIDTH; x++) {
for (int y=0; y < MATRIX_HEIGHT; y++) {
_frame[y][x]= 0;
}
}
}
void Renderer::render_timer(uint8_t seconds) {
this -> _clear_matrix();
for (int h=0; h < 8; h++) {
for (int w=0; w < 3; w++) {
_frame[h][w+5]= font_pong[seconds][h][w];
}
}
_matrix.renderBitmap(_frame, MATRIX_HEIGHT, MATRIX_WIDTH);
}
void Renderer::render_matrix() {
this -> _clear_matrix();
uint8_t p1pos= _p1.get_position();
uint8_t p2pos= _p2.get_position();
// players coords
for (int i= p1pos; i < p1pos+PADDLE_LENGTH; i++) {
_frame[i][0]= 1;
}
for (int i= p2pos; i < p2pos+PADDLE_LENGTH; i++) {
_frame[i][MATRIX_WIDTH-1]= 1;
}
// ball coords
uint8_t bx= _ball.get_x();
uint8_t by= _ball.get_y();
_frame[by][bx]= 1;
_matrix.renderBitmap(_frame, MATRIX_HEIGHT, MATRIX_WIDTH);
}
void Renderer::render_score() {
this -> _clear_matrix();
_frame[4][5]= 1;
_frame[4][6]= 1;
for (int h=0; h < 8; h++) {
for (int w=0; w < 3; w++) {
_frame[h][w+1]= font_pong[_p1.get_score()][h][w];
}
}
for (int h=0; h < 8; h++) {
for (int w=0; w < 3; w++) {
_frame[h][w+8]= font_pong[_p2.get_score()][h][w];
}
}
_matrix.renderBitmap(_frame, MATRIX_HEIGHT, MATRIX_WIDTH);
}
void Renderer::render_winner() {
this -> _clear_matrix();
// check winner
if (_p1.get_score() > _p2.get_score()) {
Serial.println("Player 1 wins!!!");
_matrix.loadSequence(pone_wins);
}
else {
Serial.println("Player 2 wins!!!");
_matrix.loadSequence(ptwo_wins);
}
_matrix.play(true);
}
+33
View File
@@ -0,0 +1,33 @@
#ifndef RENDERER_H
#define RENDERER_H
#include <Arduino.h>
#include "Arduino_LED_Matrix.h"
#include "config.h"
#include "font.h"
#include "paddle.h"
#include "ball.h"
class Renderer {
private:
// define player coordinates
Paddle& _p1;
Paddle& _p2;
Ball& _ball;
byte (&_frame)[MATRIX_HEIGHT][MATRIX_WIDTH];
ArduinoLEDMatrix& _matrix;
void _clear_matrix();
public:
Renderer (Paddle &p1, Paddle &p2, Ball &ball, byte (&frame)[MATRIX_HEIGHT][MATRIX_WIDTH], ArduinoLEDMatrix &matrix)
: _p1(p1), _p2(p2), _ball(ball), _frame(frame), _matrix(matrix) {}
void render_timer(uint8_t seconds);
void render_matrix();
void render_score();
void render_winner();
};
#endif