#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//configurar pinos dos botoes
const int botao_esquerdo_cima = 19; //botao para mover raquete esquerda para cima
const int botao_esquerdo_baixo = 18; //botao para mover raquete esquerda para baixo
const int botao_direito_cima = 16; //botao para mover raquete direita para cima
const int botao_direito_baixo = 17; //botao para mover raquete direita para baixo
//configurar wifi
const char* ssid = "";
const char* password = "";
//configurar MQTT broker
const char* mqtt_broker = "broker.mqtt-dashboard.com";
const int mqtt_port = 1883;
const char* esquerda_up_topic = "pong/esquerda/up";
const char* esquerda_down_topic = "pong/esquerda/down";
const char* direita_up_topic = "pong/direita/up";
const char* direita_down_topic = "pong/direita/down";
//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_ruido = 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);
}
WiFiClient espClient;
PubSubClient client(espClient);
void callback(char* topic, byte* payload, unsigned int length) {
String message;
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
//atualizar posições
if (String(topic) == esquerda_up_topic && raquete1_y > margem_superior) {
raquete1_y -= 5;
} else if (String(topic) == esquerda_down_topic && raquete1_y < margem_inferior - altura_raquete) {
raquete1_y += 5;
} else if (String(topic) == direita_up_topic && raquete2_y > margem_superior) {
raquete2_y -= 5;
} else if (String(topic) == direita_down_topic && raquete2_y < margem_inferior - altura_raquete) {
raquete2_y += 5;
}
}
void setup_wifi() {
delay(10);
Serial.println("Connecting to WiFi...");
WiFi.begin((char*)ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void setup_mqtt() {
client.setServer(mqtt_broker, mqtt_port);
client.setCallback(callback);
while (!client.connected()) {
Serial.println("Connecting to MQTT broker...");
if (client.connect("ESP32-Pong")) {
Serial.println("Connected to MQTT broker");
client.subscribe(esquerda_up_topic);
client.subscribe(esquerda_down_topic);
client.subscribe(direita_up_topic);
client.subscribe(direita_down_topic);
} else {
Serial.print("Failed to connect to MQTT broker, rc=");
Serial.println(client.state());
delay(2000);
}
}
}
void verificar_botoes() {
//verificar se passou tempo suficiente desde o ultimo ruido
if ((millis() - ultimo_tempo_ruido) > atraso_ruido) {
//verificar botoes do jogador esquerdo
if (digitalRead(botao_esquerdo_cima) == LOW && raquete1_y > margem_superior) {
raquete1_y -= 5;
ultimo_tempo_ruido = millis();
}
if (digitalRead(botao_esquerdo_baixo) == LOW && raquete1_y < margem_inferior - altura_raquete) {
raquete1_y += 5;
ultimo_tempo_ruido = millis();
}
//verificar botoes do jogador direito
if (digitalRead(botao_direito_cima) == LOW && raquete2_y > margem_superior) {
raquete2_y -= 5;
ultimo_tempo_ruido = millis();
}
if (digitalRead(botao_direito_baixo) == LOW && raquete2_y < margem_inferior - altura_raquete) {
raquete2_y += 5;
ultimo_tempo_ruido = millis();
}
}
}
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();
setup_wifi();
setup_mqtt();
}
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 (!client.connected()) {
setup_mqtt();
}
client.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
}