#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
// Configuração do LCD I2C
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Pinos dos botões
const int pinAcelera = 2;
const int pinFreio = 3;
const int pinEsquerda = 4;
const int pinDireita = 5;
const int buzzerPin = 6;
int velocidade = 0;
int posicaoCarro = 10; // Posição inicial na "pista"
int distanciaPercorrida = 0;
int nivel = 1;
int velocidadeMax = 10;
int vidas = 3;
bool jogoAtivo = true;
// Pista com obstáculos
char pista[4][20] = {
"####################",
"# #",
"# #",
"####################"
};
//* Modos de jogo
enum Modo { FACIL, MEDIO, DIFICIL };
Modo modoAtual = MEDIO;
void setup() {
pinMode(pinAcelera, INPUT_PULLUP);
pinMode(pinFreio, INPUT_PULLUP);
pinMode(pinEsquerda, INPUT_PULLUP);
pinMode(pinDireita, INPUT_PULLUP);
pinMode(buzzerPin, OUTPUT);
lcd.init();
lcd.backlight();
selecionarModo();
lcd.setCursor(0, 0);
lcd.print("Jogo de Corrida");
delay(2000);
lcd.clear();
}
void loop() {
if (jogoAtivo) {
// Verificar botões
if (digitalRead(pinAcelera) == LOW) {
if (velocidade < velocidadeMax) velocidade++;
}
if (digitalRead(pinFreio) == LOW) {
if (velocidade > 0) velocidade--;
}
if (digitalRead(pinEsquerda) == LOW) {
if (posicaoCarro > 1) posicaoCarro--;
}
if (digitalRead(pinDireita) == LOW) {
if (posicaoCarro < 18) posicaoCarro++;
}
// Adicionar obstáculos e atualizar pista
adicionarObstaculos();
atualizarPista();
// Verificar colisão
if (pista[2][posicaoCarro] == 'X') {
tocarBuzzer();
perderVida();
if (vidas == 0) {
fimDeJogo();
} else {
resetarJogo();
}
}
// Atualizar LCD
lcd.setCursor(0, 0);
lcd.print("Distancia: ");
lcd.print(distanciaPercorrida);
lcd.setCursor(0, 1);
lcd.print("Velocidade: ");
lcd.print(velocidade);
lcd.setCursor(0, 2);
lcd.print("Nivel: ");
lcd.print(nivel);
lcd.setCursor(14, 2);
lcd.print("Vidas: ");
lcd.print(vidas);
for (int i = 1; i <= 3; i++) {
lcd.setCursor(0, i);
lcd.print(pista[i - 1]);
}
// Incrementar distância e ajustar dificuldade
distanciaPercorrida++;
ajustarDificuldade();
delay(200 - (velocidade * 15));
}
}
void adicionarObstaculos() {
for (int i = 1; i < 3; i++) {
if (random(0, 10) < (modoAtual == FACIL ? 2 : (modoAtual == MEDIO ? 3 : 4))) {
int posObstaculo = random(1, 19);
pista[i][posObstaculo] = 'X';
}
}
}
void atualizarPista() {
for (int i = 3; i > 1; i--) {
for (int j = 1; j < 19; j++) {
pista[i][j] = pista[i - 1][j];
}
}
for (int j = 1; j < 19; j++) {
pista[1][j] = ' ';
}
pista[2][posicaoCarro] = 'C';
}
void ajustarDificuldade() {
if (distanciaPercorrida % 50 == 0) {
nivel++;
velocidadeMax += 2;
if (nivel % 2 == 0) {
for (int i = 1; i < 3; i++) {
pista[i][1] = '#';
pista[i][18] = '#';
}
}
}
}
void tocarBuzzer() {
tone(buzzerPin, 1000, 500);
}
void perderVida() {
vidas--;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Colisao!");
lcd.setCursor(0, 1);
lcd.print("Vidas restantes: ");
lcd.print(vidas);
delay(2000);
}
void fimDeJogo() {
jogoAtivo = false;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Game Over!");
lcd.setCursor(0, 1);
lcd.print("Distancia: ");
lcd.print(distanciaPercorrida);
while (true);
}
void resetarJogo() {
posicaoCarro = 10;
velocidade = 0;
lcd.clear();
}
void selecionarModo() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Selecione o Modo:");
lcd.setCursor(0, 1);
lcd.print("A:FACIL B:MEDIO C:DIFICIL");
while (true) {
if (digitalRead(pinAcelera) == LOW) {
modoAtual = FACIL;
vidas = 5;
break;
} else if (digitalRead(pinFreio) == LOW) {
modoAtual = MEDIO;
vidas = 3;
break;
} else if (digitalRead(pinEsquerda) == LOW) {
modoAtual = DIFICIL;
vidas = 2;
break;
}
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Modo Selecionado: ");
if (modoAtual == FACIL) lcd.print("FACIL");
else if (modoAtual == MEDIO) lcd.print("MEDIO");
else lcd.print("DIFICIL");
delay(2000);
lcd.clear();
}