Componentes eletrônicos, Hobby, Microcontroladores, Projetos, Tutorial

Pong com Arduino

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

matriz de LEDs

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.

diagrama do display de LEDs 8x8
Display anodo comum à esquerda e catodo comum à direita. Fonte: Embarcados.

Para usar a matriz de LEDs deve-se usar a multiplexação. Este conceito será explicado em um futuro post.

O módulo MAX7219

módulo MAX7219 para o Pong

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Ω.

Esquemático do Pong
O esquemático mostra como devem ser feitas as ligações entre os componentes.

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 &amp; (currentBuffer[r] << shift))); // Carrega o caractere atual compensado pelo deslocamento.
     bitsMap[r] = bitsMap[r] + (twoPowers &amp; (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; 
  }
}
Demonstração do jogo Pong.
Liked it? Take a second to support Electrical e-Library on Patreon!

About Pedro Ney Stroski

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *