#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//configurar pinos dos botoes
const int botao_esquerdo_cima = 16; //botao para mover raquete esquerda para cima
const int botao_esquerdo_baixo = 17; //botao para mover raquete esquerda para baixo
const int botao_direito_cima = 18; //botao para mover raquete direita para cima
const int botao_direito_baixo = 19; //botao para mover raquete direita para baixo
//configurar o display
#define largura_tela 128
#define altura_tela 64
#define resetar_oled -1
//configuracoes do quadro do jogo
#define margem_superior 12 //margem superior para exibicao de pontuacao
#define margem_inferior 63 //parte inferior da tela
#define margem_esquerda 0 //borda esquerda da tela
#define margem_direita 127 //borda direita da tela
Adafruit_SSD1306 tela(largura_tela, altura_tela, &Wire, resetar_oled);
//variaveis do jogo
int altura_raquete = 10;
int largura_raquete = 3;
int raquete1_y = (margem_inferior + margem_superior - altura_raquete) / 2;
int raquete2_y = (margem_inferior + margem_superior - altura_raquete) / 2;
int bola_x = largura_tela / 2;
int bola_y = (margem_inferior + margem_superior) / 2;
int velocidade_bola_x = 2;
int velocidade_bola_y = 2;
//variaveis de pontuacao
int pontos_esquerda = 0;
int pontos_direita = 0;
//variaveis de tratamento de ruido
unsigned long ultimo_tempo = 0;
unsigned long atraso_ruido = 50;
bool jogo_iniciado = false; //controla se o jogo comecou
void configurar_botoes() {
//configurar pinos dos botoes
pinMode(botao_esquerdo_cima, INPUT_PULLUP);
pinMode(botao_esquerdo_baixo, INPUT_PULLUP);
pinMode(botao_direito_cima, INPUT_PULLUP);
pinMode(botao_direito_baixo, INPUT_PULLUP);
}
void verificar_botoes() {
//verificar se passou tempo suficiente desde o ultimo ruido
if ((millis() - ultimo_tempo) > atraso_ruido) {
//verificar botoes do jogador esquerdo
if (digitalRead(botao_esquerdo_cima) == LOW && raquete1_y > margem_superior) {
raquete1_y -= 5;
ultimo_tempo = millis();
}
if (digitalRead(botao_esquerdo_baixo) == LOW && raquete1_y < margem_inferior - altura_raquete) {
raquete1_y += 5;
ultimo_tempo = millis();
}
//verificar botoes do jogador direito
if (digitalRead(botao_direito_cima) == LOW && raquete2_y > margem_superior) {
raquete2_y -= 5;
ultimo_tempo = millis();
}
if (digitalRead(botao_direito_baixo) == LOW && raquete2_y < margem_inferior - altura_raquete) {
raquete2_y += 5;
ultimo_tempo = millis();
}
}
if (!jogo_iniciado) {
if (digitalRead(botao_esquerdo_cima) == LOW ||
digitalRead(botao_esquerdo_baixo) == LOW ||
digitalRead(botao_direito_cima) == LOW ||
digitalRead(botao_direito_baixo) == LOW) {
jogo_iniciado = true;
delay(200); //delay para verificar se o jogo iniciou
return;
}
}
}
void setup() {
Serial.begin(115200);
//inicializar o display
if (!tela.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("Falha na alocacao do SSD1306"));
for (;;);
}
tela.clearDisplay();
//definir o tamanho e a cor do texto para a exibicao
tela.setTextSize(1);
tela.setTextColor(SSD1306_WHITE);
configurar_botoes();
}
void atualizar_jogo() {
//mover a bola
bola_x += velocidade_bola_x;
bola_y += velocidade_bola_y;
//colisao da bola com o quadro
if (bola_y <= margem_superior || bola_y >= margem_inferior - 1) {
velocidade_bola_y = -velocidade_bola_y;
bola_y = constrain(bola_y, margem_superior + 1, margem_inferior - 2);
}
//colisao da bola com a raquete
if ((bola_x <= margem_esquerda + largura_raquete && bola_y >= raquete1_y && bola_y <= raquete1_y + altura_raquete) ||
(bola_x >= margem_direita - largura_raquete - 1 && bola_y >= raquete2_y && bola_y <= raquete2_y + altura_raquete)) {
velocidade_bola_x = -velocidade_bola_x;
}
//pontuacao e reinicio da bola
if (bola_x <= margem_esquerda) {
//ponto direita
pontos_direita++;
bola_x = largura_tela / 2;
bola_y = (margem_inferior + margem_superior) / 2;
velocidade_bola_x = abs(velocidade_bola_x); //mover a bola para direita
} else if (bola_x >= margem_direita) {
//ponto esquerda
pontos_esquerda++;
bola_x = largura_tela / 2;
bola_y = (margem_inferior + margem_superior) / 2;
velocidade_bola_x = -abs(velocidade_bola_x); //mover a bola para esquerda
}
}
void desenhar_jogo() {
tela.clearDisplay();
//desenhar quadro
tela.drawRect(margem_esquerda, margem_superior, largura_tela, margem_inferior - margem_superior, SSD1306_WHITE);
//jogador esquerda informacoes
tela.setCursor(0, 0);
tela.print("Esq.:");
tela.print(pontos_esquerda);
//jogador direita informacoes
tela.setCursor(largura_tela - 45, 0);
tela.print("Dir.:");
tela.print(pontos_direita);
//linha para dividir o quadro do jogo
for (int i = margem_superior; i < margem_inferior; i += 4) {
tela.drawPixel(largura_tela/2, i, SSD1306_WHITE);
}
//desenhar as raquetes dos jogadores
tela.fillRect(margem_esquerda, raquete1_y, largura_raquete, altura_raquete, SSD1306_WHITE);
tela.fillRect(margem_direita - largura_raquete, raquete2_y, largura_raquete, altura_raquete, SSD1306_WHITE);
//desenhar a bola
tela.fillRect(bola_x, bola_y, 2, 2, SSD1306_WHITE);
tela.display();
}
void desenhar_tela_inicial() {
tela.clearDisplay();
//titulo
tela.setTextSize(2);
tela.setTextColor(SSD1306_WHITE);
tela.setCursor((largura_tela - 12*8)/2, 10);
tela.print("PONG GAME");
tela.setTextSize(1);
tela.setCursor(35, 30);
tela.print("2 jogadores");
tela.setTextSize(1);
tela.setCursor(2, 40);
tela.print("Pressione um botao para comecar");
tela.display();
}
void loop() {
if (!jogo_iniciado) {
desenhar_tela_inicial();
verificar_botoes();
return;
}
verificar_botoes(); //verificar estado dos botoes
atualizar_jogo();
desenhar_jogo();
delay(30); //controla a velocidade do jogo
}