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
This commit is contained in:
@@ -21,8 +21,8 @@ byte frame[MATRIX_HEIGHT][MATRIX_WIDTH] = {
|
||||
};
|
||||
|
||||
// players coordinates
|
||||
int p1_start= 1;
|
||||
int p2_start= 4;
|
||||
int players_coords[2]= {1, 4};
|
||||
int players_scores[2]= {0, 0};
|
||||
|
||||
// initials balls coordinates
|
||||
int ball_x= BALL_RESET_X;
|
||||
@@ -32,6 +32,9 @@ int need_refresh= 1;
|
||||
|
||||
int ball_delay= INITIAL_BALL_DELAY;
|
||||
|
||||
bool game_over= false;
|
||||
bool go= true;
|
||||
|
||||
long exec_t2= millis();
|
||||
|
||||
|
||||
@@ -39,6 +42,7 @@ 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);
|
||||
@@ -48,17 +52,56 @@ void setup() {
|
||||
}
|
||||
|
||||
void loop() {
|
||||
long exec_t1= millis();
|
||||
pong_move_p1(p1_start, need_refresh);
|
||||
pong_move_p2(p2_start, need_refresh);
|
||||
if (exec_t1 - exec_t2 > ball_delay) {
|
||||
move_ball(ball_x, ball_y, ball_delay, p1_start, p2_start, need_refresh);
|
||||
exec_t2= exec_t1;
|
||||
for (int i = START_TIMER; i >= 0; i--) {
|
||||
render_timer(frame, i);
|
||||
delay(1000);
|
||||
matrix.renderBitmap(frame, MATRIX_HEIGHT, MATRIX_WIDTH);
|
||||
}
|
||||
|
||||
game_over= false;
|
||||
go= true;
|
||||
|
||||
// delay the first ball movement
|
||||
exec_t2= millis() + FIRST_START_BALL_DELAY;
|
||||
|
||||
while (go) {
|
||||
long exec_t1= millis();
|
||||
pong_move_p1(players_coords[0], need_refresh);
|
||||
pong_move_p2(players_coords[1], need_refresh);
|
||||
if (exec_t1 - exec_t2 > ball_delay) {
|
||||
bool scored= move_ball(ball_x, ball_y, ball_delay, players_coords, players_scores, need_refresh);
|
||||
if (scored) {
|
||||
render_score(frame, players_scores);
|
||||
matrix.renderBitmap(frame, MATRIX_HEIGHT, MATRIX_WIDTH);
|
||||
delay(1000);
|
||||
if (players_scores[0] >= MAX_POINTS || players_scores[1] >= MAX_POINTS) {
|
||||
render_winner(frame, matrix, players_scores);
|
||||
need_refresh= 0;
|
||||
game_over= true;
|
||||
}
|
||||
// delay the ball movement after score
|
||||
exec_t2= millis() + FIRST_START_BALL_DELAY;
|
||||
} else exec_t2= exec_t1;
|
||||
}
|
||||
|
||||
// rerender matrix only if something is changed
|
||||
if (need_refresh) {
|
||||
render_matrix(frame, p1_start, p2_start, ball_x, ball_y);
|
||||
render_matrix(frame, players_coords, ball_x, ball_y);
|
||||
matrix.renderBitmap(frame, MATRIX_HEIGHT, MATRIX_WIDTH);
|
||||
need_refresh= 0;
|
||||
}
|
||||
delay(50);
|
||||
if (!game_over) delay(50);
|
||||
|
||||
// keep showing the winner waiting for a restart
|
||||
while (game_over) {
|
||||
// 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) {
|
||||
go= false;
|
||||
game_over= false;
|
||||
players_scores[0]= 0;
|
||||
players_scores[1]= 0;
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,3 +9,7 @@
|
||||
#define BALL_RESET_Y (MATRIX_HEIGHT / 2)
|
||||
#define BAR_LENGTH 3
|
||||
#define INITIAL_BALL_DELAY 200
|
||||
|
||||
#define MAX_POINTS 9
|
||||
#define START_TIMER 3
|
||||
#define FIRST_START_BALL_DELAY 500
|
||||
|
||||
184
src/font.h
Normal file
184
src/font.h
Normal 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
|
||||
@@ -5,54 +5,61 @@
|
||||
// used to increase speed when game is too easy
|
||||
int hits= 0;
|
||||
|
||||
int p1_score= 0;
|
||||
int p2_score= 0;
|
||||
|
||||
// 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;
|
||||
|
||||
void point_scored(int &ball_x, int &ball_y, int &ball_delay) {
|
||||
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;
|
||||
ball_delay= INITIAL_BALL_DELAY;
|
||||
}
|
||||
|
||||
void move_ball(int &ball_x, int &ball_y, int &ball_delay, int p1_start, int p2_start, int &need_refresh) {
|
||||
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
|
||||
void random_ball_movement(int &ball_move_x, int &ball_move_y) {
|
||||
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;
|
||||
}
|
||||
|
||||
void point_scored(int &ball_x, int &ball_y, int &ball_delay, int players_scores[2], int &ball_move_x, int &ball_move_y) {
|
||||
ball_x= BALL_RESET_X;
|
||||
ball_y= BALL_RESET_Y;
|
||||
random_ball_movement(ball_move_x, ball_move_y);
|
||||
|
||||
Serial.print("P1: ");
|
||||
Serial.print(players_scores[0]);
|
||||
Serial.print(" - ");
|
||||
Serial.print("P2: ");
|
||||
Serial.print(players_scores[1]);
|
||||
Serial.println();
|
||||
|
||||
hits= 0;
|
||||
ball_delay= INITIAL_BALL_DELAY;
|
||||
}
|
||||
|
||||
bool move_ball(int &ball_x, int &ball_y, int &ball_delay, int players_coords[2], int players_scores[2], int &need_refresh) {
|
||||
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 false;
|
||||
}
|
||||
|
||||
need_refresh= 1;
|
||||
bool scored= false;
|
||||
|
||||
// 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
|
||||
random_ball_movement(ball_move_x, ball_move_y);
|
||||
}
|
||||
|
||||
else if (ball_x == 0) {
|
||||
// if p1 collision: reverse x, go left
|
||||
if (!ball_player_collision(p1_start, ball_y)) {
|
||||
if (!ball_player_collision(players_coords[0], ball_y)) {
|
||||
// else p2 score, reset board
|
||||
p2_score += 1;
|
||||
players_scores[1] += 1;
|
||||
scored= true;
|
||||
Serial.println("Player 2 Scores");
|
||||
point_scored(ball_x, ball_y, ball_delay);
|
||||
point_scored(ball_x, ball_y, ball_delay, players_scores, ball_move_x, ball_move_y);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
hits += 1;
|
||||
@@ -60,11 +67,13 @@ void move_ball(int &ball_x, int &ball_y, int &ball_delay, int p1_start, int p2_s
|
||||
}
|
||||
}
|
||||
else if (ball_x == MATRIX_WIDTH-1) {
|
||||
if (!ball_player_collision(p2_start, ball_y)) {
|
||||
if (!ball_player_collision(players_coords[1], ball_y)) {
|
||||
// else p1 score, reset board
|
||||
p1_score += 1;
|
||||
players_scores[0] += 1;
|
||||
scored= true;
|
||||
Serial.println("Player 1 Scores");
|
||||
point_scored(ball_x, ball_y, ball_delay);
|
||||
point_scored(ball_x, ball_y, ball_delay, players_scores, ball_move_x, ball_move_y);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
hits += 1;
|
||||
@@ -85,4 +94,5 @@ void move_ball(int &ball_x, int &ball_y, int &ball_delay, int p1_start, int p2_s
|
||||
|
||||
ball_x+= ball_move_x;
|
||||
ball_y+= ball_move_y;
|
||||
return scored;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#ifndef PONG_BALL_H
|
||||
#define PONG_BALL_H
|
||||
|
||||
void point_scored();
|
||||
void move_ball(int &ball_x, int &ball_y, int &loop_delay, int p1_start, int p2_start, int &need_refresh);
|
||||
bool move_ball(int &ball_x, int &ball_y, int &loop_delay, int players_coords[2], int players_scores[2], int &need_refresh);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,22 +1,75 @@
|
||||
#include <Arduino.h>
|
||||
#include "Arduino_LED_Matrix.h"
|
||||
#include "config.h"
|
||||
#include "font.h"
|
||||
|
||||
void render_matrix(byte frame[MATRIX_HEIGHT][MATRIX_WIDTH], int p1_start, int p2_start, int ball_x, int ball_y) {
|
||||
// clear
|
||||
void clear_matrix(byte frame[MATRIX_HEIGHT][MATRIX_WIDTH]) {
|
||||
for (int x=0; x < MATRIX_WIDTH; x++) {
|
||||
for (int y=0; y < MATRIX_HEIGHT; y++) {
|
||||
frame[y][x]= 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void render_matrix(byte frame[MATRIX_HEIGHT][MATRIX_WIDTH], int players_coords[2], int ball_x, int ball_y) {
|
||||
clear_matrix(frame);
|
||||
int player_one= players_coords[0];
|
||||
int player_two= players_coords[1];
|
||||
// players coords
|
||||
for (int i= p1_start; i < p1_start+BAR_LENGTH; i++) {
|
||||
for (int i= player_one; i < player_one+BAR_LENGTH; i++) {
|
||||
frame[i][0]= 1;
|
||||
}
|
||||
for (int i= p2_start; i < p2_start+BAR_LENGTH; i++) {
|
||||
for (int i= player_two; i < player_two+BAR_LENGTH; i++) {
|
||||
frame[i][MATRIX_WIDTH-1]= 1;
|
||||
}
|
||||
|
||||
// ball coords
|
||||
frame[ball_y][ball_x]= 1;
|
||||
}
|
||||
|
||||
void render_score(byte frame[MATRIX_HEIGHT][MATRIX_WIDTH], int players_scores[2]) {
|
||||
clear_matrix(frame);
|
||||
int player_one= players_scores[0];
|
||||
int player_two= players_scores[1];
|
||||
if (player_one > 9) player_one = 9;
|
||||
if (player_two > 9) player_two = 9;
|
||||
|
||||
// player score separator (-)
|
||||
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[player_one][h][w];
|
||||
}
|
||||
}
|
||||
for (int h=0; h < 8; h++) {
|
||||
for (int w=0; w < 3; w++) {
|
||||
frame[h][w+8]= font_pong[player_two][h][w];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void render_timer(byte frame[MATRIX_HEIGHT][MATRIX_WIDTH], int seconds) {
|
||||
clear_matrix(frame);
|
||||
|
||||
for (int h=0; h < 8; h++) {
|
||||
for (int w=0; w < 3; w++) {
|
||||
frame[h][w+5]= font_pong[seconds][h][w];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void render_winner(byte frame[MATRIX_HEIGHT][MATRIX_WIDTH], ArduinoLEDMatrix &matrix, int players_scores[2]) {
|
||||
clear_matrix(frame);
|
||||
// check winner
|
||||
if (players_scores[0] > players_scores[1]) {
|
||||
Serial.println("Player 1 wins!!!");
|
||||
matrix.loadSequence(pone_wins);
|
||||
}
|
||||
else {
|
||||
Serial.println("Player 2 wins!!!");
|
||||
matrix.loadSequence(ptwo_wins);
|
||||
}
|
||||
matrix.play(true);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "Arduino_LED_Matrix.h"
|
||||
#include "config.h"
|
||||
|
||||
void render_matrix(byte frame[MATRIX_HEIGHT][MATRIX_WIDTH], int p1_start, int p2_start, int ball_x, int ball_y);
|
||||
void render_matrix(byte frame[MATRIX_HEIGHT][MATRIX_WIDTH], int players_coords[2], int ball_x, int ball_y);
|
||||
void render_score(byte frame[MATRIX_HEIGHT][MATRIX_WIDTH], int players_scores[2]);
|
||||
void render_timer(byte frame[MATRIX_HEIGHT][MATRIX_WIDTH], int seconds);
|
||||
void render_winner(byte frame[MATRIX_HEIGHT][MATRIX_WIDTH], ArduinoLEDMatrix &matrix, int players_scores[2]);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user