sexta-feira, 15 de julho de 2016

Construindo Game Pong com Arduino


INTRODUÇÃO

          No post anterior, introduzimos uma ideia de como usar a biblioteca TVout com o arduino. Agora, vamos criar algo mais interessante, o "velho" Game Pong.


DESCRIÇÃO

          Este jogo foi criado do zero de forma simples e objetiva, para que os iniciantes em desenvolvimento de jogos ou mesmo iniciantes com arduino, possam ter uma visão ampla e mínima necessária do processo de criação e funcionamento de um jogo.

          O mesmo pode ser melhorado e algum eventual bug corrigido mas, deixei como está, para que o código ficasse o mais "limpo" possível e o leitor possa ter uma melhor compreensão.


MONTAGEM

A imagem abaixo ilustra a montagem dos joysticks:


Mesmo que na imagem tenhamos um arduino uno, isso não quer dizer que seja exclusividade dele, qualquer placa pode ser usada desde que, seja observado a compatibilidade entre o arduino usado e a biblioteca para geração de imagem no televisor.
  1. Os potenciômetros usados foram de 50 kΩ
  2. Os capacitores eletrolíticos são de 2,2 µF por 16 v
Obs.: Os capacitores foram adicionados ao projeto porque ocorre uma instabilidade nas entradas analógica da placa arduino, provocando uma variação constante da tensão e com isso as barras que representam os players 1 e 2 ficaram "vibrando" constantemente.

A instabilidade ocorre em qualquer tipo de projeto que faça uso das entradas analógicas (continuo pesquisando para entender porque isso acontece), normalmente os desenvolvedores resolvem o problema via software, utilizando filtros ou calculando uma média das medições em um dado intervalo.

Para que nosso código continuasse simples e pequeno, resolvi o problema inicialmente adicionando dois capacitores eletrolítico de 2,2 µF. Caso o leitor não fique satisfeito, substitua os capacitores por outros de 4,7 µF. A tensão de trabalho da placa é de 5 volts então, qualquer capacitor de 10 volts ou mais servirá normalmente.



          O esquema de ligação da placa arduino no televisor segue conforme descrito no post anterior e imagens abaixo para arduino UNO ou MEGA respectivamente:




A seguinte tabela mostra os pinos que serão usados de acordo com o arduino escolhido.
 ARDUINO
SINCRONISMO 
VIDEO 
AUDIO 
 UNO
 9
11 
 MEGA
11 
29 
10 

A imagem abaixo ilustra o diagrama de ligação entre o arduino e o televisor.






Segue o código do nosso game pong :
/*
 * 
 * Arduinovaçao 15/07/16
 * 
 * http://arduinovacao.blogspot.com.br/
 * 
 * Diego Santos
 * 
 */
 
#include <TVout.h>
#include <fontALL.h>

#define LARGURA_TELA 120
#define ALTURA_TELA 96
#define LIMITE_SUP 9
#define LIMITE_INF 86

TVout TV;

// CONFIGURAÇOES
int velocidadeJogo = 25;
int velocidadeBolaX = 1;
int velocidadeBolaY = -1;
int entradaJoystickPlayer1 = A0;
int entradaJoystickPlayer2 = A1;
boolean startGame = false;
boolean donoDaBola = true;

// COORDENADAS DOS PLAYERS
int posicaoPlayer1X = 5;
int posicaoPlayer1Y;
int posicaoPlayer2X = 114;
int posicaoPlayer2Y;
int sentidoPlayer1;
int sentidoPlayer2;

// COORDENADA DA BOLA
int posicaoBolaX = 7;
int posicaoBolaY;

// PONTUAÇAO DOS PLAYERS
int pontosPlayer1 = 0;
int pontosPlayer2 = 0;

void setup() {
    TV.begin(_PAL, LARGURA_TELA, ALTURA_TELA);

    posicaoPlayer1Y = map(analogRead(entradaJoystickPlayer1), 0, 1023, 16, 79);
    posicaoPlayer2Y = map(analogRead(entradaJoystickPlayer2), 0, 1023, 16, 79);

    sentidoPlayer1 = posicaoPlayer1Y;
    sentidoPlayer2 = posicaoPlayer2Y;

    posicaoBolaY = posicaoPlayer1Y;
}

void loop() {
    TV.clear_screen();
    TV.select_font(font6x8);
    TV.print(44, 0, pontosPlayer1);
    TV.print(70, 0, pontosPlayer2);
    TV.select_font(font4x6);
    TV.print(35, 90, "Arduinovacao");

    desenhaCenario();

    verificaMovimentoPlayers();

    movimentaBola();
    
    delay(velocidadeJogo);
    
    if(pontosPlayer1 == 5) {
        gameOver(1);
    } else if(pontosPlayer2 == 5) {
        gameOver(2);
    }
}

void desenhaCenario() {
    // DESENHA QUADRA RETANGULAR
    TV.draw_rect(0, 8, LARGURA_TELA - 1, ALTURA_TELA - 17, WHITE);
    
    // DESENHA COLUNA CENTRAL DA QUADRA
    for(int i = 9; i <= 85; i = i + 5) {
        TV.draw_column((LARGURA_TELA / 2) - 1, i, i + 2, WHITE);
    }

    // DESENHA PLAYER 1
    TV.draw_column(posicaoPlayer1X, (posicaoPlayer1Y - 7), (posicaoPlayer1Y + 7), WHITE);

    // DESENHA PLAYER 2
    TV.draw_column(posicaoPlayer2X, (posicaoPlayer2Y - 7), (posicaoPlayer2Y + 7), WHITE);

    // DESENHA BOLA
    TV.set_pixel(posicaoBolaX, posicaoBolaY, WHITE);
}

void verificaMovimentoPlayers() {
    posicaoPlayer1Y = map(analogRead(entradaJoystickPlayer1), 0, 1023, 16, 79);
    if(sentidoPlayer1 < posicaoPlayer1Y) {
        if(!startGame && donoDaBola) {
            velocidadeBolaY = 1;
            startGame = true;
        }        
    } else if(sentidoPlayer1 > posicaoPlayer1Y) {
        if(!startGame && donoDaBola) {
            velocidadeBolaY = -1;
            startGame = true;
        }        
    }

    posicaoPlayer2Y = map(analogRead(entradaJoystickPlayer2), 0, 1023, 16, 79);
    if(sentidoPlayer2 < posicaoPlayer2Y) {
        if(!startGame && !donoDaBola) {
            velocidadeBolaY = 1;
            startGame = true;
        }
    } else if(sentidoPlayer2 > posicaoPlayer2Y) {
        if(!startGame && !donoDaBola) {
            velocidadeBolaY = -1;
            startGame = true;
        }
    }
    
    sentidoPlayer1 = posicaoPlayer1Y;
    sentidoPlayer2 = posicaoPlayer2Y;
}

void movimentaBola() {
    int bolaX = posicaoBolaX;
    int bolaY = posicaoBolaY;
  
    if(startGame) {
        bolaX = posicaoBolaX + velocidadeBolaX;
        bolaY = posicaoBolaY + velocidadeBolaY;      
    }
    
    // VERIFICA COLISOES SUPERIOR E INFERIOR DA BOLA COM A QUADRA
    if(bolaY == LIMITE_SUP) {
        velocidadeBolaY = 1;
        sonsDoJogo(440, 20); // SONORO QUANDO A BOLA BATE NA PARTE SUPERIOR
    }
    else if(bolaY == LIMITE_INF) {
        velocidadeBolaY = -1;
        sonsDoJogo(440, 20); // SONORO QUANDO A BOLA BATE NA PARTE INFERIOR
    }

    // VERIFICA COLISOES DA BOLA COM OS PLAYERS
    // PLAYER 1
    if(bolaX == 7) {
        if(posicaoBolaY < posicaoPlayer1Y + 8 && posicaoBolaY > posicaoPlayer1Y - 8) {
            velocidadeBolaX = 1;            
            if(startGame) {
                sonsDoJogo(220, 20); // SONORO QUANDO PLAYER 1 BATE NA BOLA
            }            
        }
    }else if(bolaX == 0) {
        startGame = false;
        donoDaBola = false;
        bolaX = 112;
        bolaY = posicaoPlayer2Y;
        pontosPlayer2++;
        sonsDoJogo(100, 300); // SONORO QUANDO PLAYER 2 FAZ PONTO
    }
    // PLAYER 2
    if(bolaX == 112) {
        if(posicaoBolaY < posicaoPlayer2Y + 8 && posicaoBolaY > posicaoPlayer2Y - 8) {
            velocidadeBolaX = -1;
            if(startGame) {
                sonsDoJogo(220, 20); // SONORO QUANDO PLAYER 2 BATE NA BOLA
            }            
        }
    }else if(bolaX == LARGURA_TELA) {
        startGame = false;
        donoDaBola = true;
        bolaX = 7;
        bolaY = posicaoPlayer1Y;
        pontosPlayer1++;
        sonsDoJogo(100, 300); // SONORO QUANDO PLAYER 1 FAZ PONTO
    }
        
    posicaoBolaX = bolaX;
    posicaoBolaY = bolaY;
}

void sonsDoJogo(int frequencia, int duracao) {
    TV.tone(frequencia, duracao);
}

void gameOver(int vencedor) {
    startGame = false;
    pontosPlayer1 = 0;
    pontosPlayer2 = 0;
    TV.clear_screen();
    TV.select_font(font8x8);
    sonsDoJogo(520, 500); // SONORO QUANDO PLAYER 1 OU PLAYER 2 VENCE O JOGO

    if(vencedor == 1) {
        TV.println(27, 40, "Vencedor");
        TV.println(27, 50, "PLAYER 1");
        donoDaBola = true;
        delay(5000);
    }else if(vencedor == 2) {
        TV.println(27, 40, "Vencedor");
        TV.println(27, 50, "PLAYER 2");
        donoDaBola = false;
        delay(6000);
    }
}


CÓDIGO FONTE

Game Pong  https://www.dropbox.com/s/4lu8zk0bni7vx5c/Game_Pong_Arduino.ino?dl=0

9 comentários:

  1. Muuuuuito bom. Vou indicar o blog na comunidade de automação. Parabens 👍👍👍

    ResponderExcluir
  2. Há uns 5 anos fiz alguns projetos com PIC (já tinha ouvido falar do arduino, mas na época só se achava em sites estrangeiros e era caro). Aí pensei em voltar a programar pra microcontroladores... achei este blog e decidi: PIC->R.I.P.

    ResponderExcluir
  3. para mim apareceu o seguinte erro:
    Arduino: 1.8.5 (Windows Store 1.8.10.0) (Windows 10), Placa:"Arduino/Genuino Uno"

    C:\Users\Breno\Downloads\Game_Pong_Arduino\Game_Pong_Arduino.ino:12:21: fatal error: fontALL.h: No such file or directory

    #include

    ^

    compilation terminated.

    exit status 1
    Erro compilando para a placa Arduino/Genuino Uno

    Este relatório teria mais informações com
    "Mostrar a saida detalhada durante a compilação"
    opção pode ser ativada em "Arquivo -> Preferências"

    ResponderExcluir
  4. Olá! Fiz o projeto porém não consigo mudar a velocidade do jogo, ao mudar as variaveis velocidade o jogo não funciona, oq deve ser feito?

    ResponderExcluir

Postagem mais recente Postagem mais antiga Página inicial