Este é um projeto do clássico jogo Pong no Arduino, que mostra uma pontuação com rolagem horizontal ao terminar a partida.
O display de LEDs 8×8
Este projeto deve ser feito com uma matriz de LEDs 8×8, esta matrix possui 16 entradas. Com este componente é possível fazer desenhos, animações simples, escrever letras, números e criar jogos.
Para usar a matriz de LEDs deve-se usar a multiplexação. Este conceito será explicado em um futuro post.
O módulo MAX7219
Este módulo foi criado para facilitar a montagem de projetos com display de LEDs, só precisa ligar 5 fios ao Arduino: 2 de alimentação (Vcc e GND) e os outros 3 terminais que são:
- DIN: entrada de dados.
- CLK: clock.
- CS: pino que transfere os dados para o display.
Sem este módulo, seriam necessários muitos fios para a ligação. O funcionamento do circuito integrado MAX7219 será explicado em um outro post. O foco aqui é como montar o projeto Pong.
O jogo Pong
Os materiais necessários para montar o projeto são: um Arduino Uno, um módulo MAX7219 e 1 potenciômetro de 10 kΩ.
O jogador controla a raquete com o potenciômetro. O código é baseado no projeto 22, do capítulo 7, do livro Arduino Básico, de Michael McRoberts.
A diferença é que o projeto apresentado neste post tem uma mensagem de rolagem horizontal, indicando quantos pontos fez o jogador ao terminar a partida. Segue o código abaixo, para baixar a biblioteca “LedControl.h”, clique aqui.
#include "LedControl.h"//Inclui biblioteca para//controle da matriz com //MAX7219.
LedControl myMatrix = LedControl(2, 4, 3, 1);//Cria uma instância de uma //matriz.
/* DIN -> Arduino Digital 2
CS -> Arduino Digital 3
CLK -> Arduino Digital 4
O quarto dígito indica que estou usando apenas um módulo MAX7219.
*/
// 1.Variáveis Globais ---
int column = 1, row = random(8)+1; //Decide em que ponto a bola deve //começar.
int directionX = 1, directionY = 1; //Certifica-se de que a bola vai //primeiro da esquerda para a direita.
int paddle1 = 5, paddle1Val; //Pino e valor do potenciômetro.
int velocidade = 300; //Velocidade inicial da bola.
int counter = 0, mult = 10;
char score[4]; // Variável para converte o int counter em char.
// fim 1. ---
//2.Configurações Iniciais ----
// Variáveis usadas para rolagem da pontuação, ambas começam em 0.
int index = 0; // Caractere atual a ser mostrado.
int shift = 0; // Quantidade de colunas de deslocamento.
// Array para armazenar o mapa de bists a ser mostrado .
int bitsMap[] = {0,0,0,0,0,0,0,0};
// Vetor contendo a potência de 2 para calcular o que mostrar.
const int twoPowers[] = {1,2,4,8,16,32,64,128};
int charachter;
#define displayspeed 7 //Velocidade da exibição da pontuação menos é mais //rápido.
//Fim 2. ----
//Como os números devem aparecer no display.
const int zero[]={B00111100,
B01000010,
B01000010,
B01000010,
B01000010,
B01000010,
B00111100,
B00000000};
const int one[]={B00001000,
B00011000,
B00101000,
B00001000,
B00001000,
B00001000,
B00111110,
B00000000};
const int two[]={B00011000,
B00100100,
B00100100,
B00001000,
B00010000,
B00100000,
B00111100,
B00000000};
const int three[]={B00111100,
B01000010,
B00000010,
B00111100,
B00000010,
B01000010,
B00111100,
B00000000};
const int four[]={B00000100,
B00001100,
B00010100,
B00100100,
B01111111,
B00000100,
B00000100,
B00000000};
const int five[]={B01111110,
B01000000,
B01111000,
B00000100,
B00000010,
B00000010,
B01111100,
B00000000};
const int six[]={B00111100,
B01000000,
B01000000,
B01111100,
B01000010,
B01000010,
B00111100,
B00000000};
const int seven[]={B01111100,
B00000100,
B00000100,
B00011111,
B00000100,
B00000100,
B00000100,
B00000000};
const int eight[]={B00111100,
B01000010,
B01000010,
B00111100,
B01000010,
B01000010,
B00111100,
B00000000};
const int nine[]={B00111100,
B01000010,
B01000010,
B00111110,
B00000010,
B00000010,
B01111100,
B00000000};
void setup()
{
myMatrix.shutdown(0, false); //Habilita o display.
myMatrix.setIntensity(0, 8); //Define o brilho como //médio.
myMatrix.clearDisplay(0); //Limpa o display.
randomSeed(analogRead(0)); //Cria uma semente //genuinamente aleatória.
Serial.begin(9600); //Para a pontuação aparecer //na tela serial.
}
void loop()
{
paddle1Val = analogRead(paddle1);
paddle1Val = map(paddle1Val, 200, 1024, 1, 6);
column += directionX;
row += directionY;
if(column == 6 && directionX == 1 && (paddle1Val == row || paddle1Val+1 == row || paddle1Val+2 == row)) directionX = -1;
if(column == 0 && directionX == -1) directionX = 1;
if(row == 7 && directionY == 1 ) directionY = -1;
if(row == 0 && directionY == -1) directionY = 1;
if(column == 7){
oops();
}
myMatrix.clearDisplay(0); //Limpa tela para o próximo //quadro de animação.
myMatrix.setLed(0, column, row, HIGH);
myMatrix.setLed(0, 7, paddle1Val, HIGH);
myMatrix.setLed(0, 7, paddle1Val+1, HIGH);
myMatrix.setLed(0, 7, paddle1Val+2, HIGH);
if(!(counter % mult)) {velocidade -= 5; mult*mult;}
delay(velocidade);
counter++;
}
void oops() //Função de fim de jogo.
{
delay(1000);
if(counter<100){//Se a pontuação for menor que 100.
for(int y=0; y<40; y++)
{
loadMatrix2();
drawScreen(bitsMap);
//O que a tela serial deve exibir.
Serial.println("Game Over");
Serial.print(counter);
Serial.println("\n");
Serial.println("Score:");
Serial.print(score);
Serial.println("\n");
}
}else{ //Se a pontuação for maior que 100.
for(int y=0; y<40; y++)
{
loadMatrix();
drawScreen(bitsMap);
//O que a tela serial deve exibir.
Serial.println("Game Over");
Serial.print(counter);
Serial.println("\n");
Serial.println("Score:");
Serial.print(score);
Serial.println("\n");
}
}
delay(1000);
counter = 0; //Reinicia todos os valores.
velocidade = 300;
column = 1;
row = random(8)+1;
}
void loadMatrix(){ //Carregar matriz para mostrar 3 algarismos.
itoa(counter,score,10); //Função que converte inteiros em string de //caracteres de base 10, para serem mostrados no display.
getChar(score[index]); // Lê o caracter corrente da frase.
int currentChar = charachter;
getChar(score[index+1]); // Lê o próximo caractere.
int nextChar = charachter;
executeMatrix(currentChar, nextChar);
}
void loadMatrix2(){//Carregar matriz para mostrar 1 ou 2 algarismos.
itoa(counter,score,10);
getChar(score[0]); // Lê o caracter corrente da frase.
int currentChar = charachter;
getChar(score[1]); // Lê o próximo caractere.
int nextChar = charachter;
executeMatrix(currentChar, nextChar);
}
// Monta o mapa de bits da matriz
void executeMatrix(int currentBuffer[], int nextBuffer[]) {
for(int r=0; r < 8; r++){ // Incrementa r para r de 0 a 7 (row - linha).
bitsMap[r] = 0; // Resetar a linha.
for(int c=0; c < 8; c++){ // Incrementa c para c de 0 a 7 (column - //coluna).
bitsMap[r] = bitsMap[r] + ((twoPowers[c] & (currentBuffer[r] << shift))); // Carrega o caractere atual compensado pelo deslocamento.
bitsMap[r] = bitsMap[r] + (twoPowers[c] & (nextBuffer[r] >> (8 - shift) )); // Carrega o próximo caractere compensado pelo deslocamento.
}
}
shift++; // Incrementa a variável shift responsável pelo deslocamento de //uma linha.
if(shift==8){
shift = 0;
index++;
//if(index == sizeof(texto)-2){
if(index == sizeof(score)-2){
index=0;
}
} // Se shift for igual a 8, carraga o próximo par de //carcateres (currentChar e nextCahr).
}
void drawScreen(int buffer[]) {
for (int v = 0; v < displayspeed; v++) {
for (int i = 0; i < 8; i++) { // linhas
for (int j = 0; j < 8; j++) { // colunas
myMatrix.setLed(0, i, j, bitRead(buffer[i], 7 - j));
//usando bitRead()
}
}
}
}
void getChar(char msgChar) {
switch(msgChar){
case '0': charachter = zero; break;
case '1': charachter = one; break;
case '2': charachter = two; break;
case '3': charachter = three; break;
case '4': charachter = four; break;
case '5': charachter = five; break;
case '6': charachter = six; break;
case '7': charachter = seven; break;
case '8': charachter = eight; break;
case '9': charachter = nine; break;
}
}