/** ############################################################################
* ### BOMBA DE AIRSOFT - C.A.T. CERBERUS AIRSOFT TEAM ###
* ############################################################################
* ## Desenvolvida por: Operador 04 - Eduardo Leite Ranzzani ##
* ## Destinada ao uso recreativo em partidas de airsoft ##
* ############################################################################
* ##### INSTRUÇÃO DE USO #####
* ### ###
* ## 1. A bomba ficará posicionada em um local estratégico do mapa e cabe ##
* ## às equipes tomar o local e fazer o acionamento, ou tomar o local ##
* ## defender o perímetro evitando que a outra equipe acione. ##
* ## ##
* ## 2. Será distribuida uma lista de senhas válidas para os operadores ##
* ## dos dois times, onde o time de ataque poderá utilizar uma delas ##
* ## para acionar a bomba e dar início ao timer. ##
* ## ##
* ## 3. Caso acionada o time de ataque precisa fazer a proteção da bomba ##
* ## para tentar evitar que a defesa faça o desarme, e a defesa precisa ##
* ## tentar tomar o local para desarmar e vencer o jogo. ##
* ## ##
* ## 4. Caso consiga dominar o perímetro a equipe de defesa precisa tentar ##
* ## descobrir qual foi a senha utilizada pelos atacantes na hora que ##
* ## foi feito o acionamento. Cada tentativa errada, diminui 10s do ##
* ## tempo restante para a explosão. ##
* ## ##
* ## 5. Por padrão está definido um tempo de 300s (5min) para o desarme ##
* ## após o acionamento. Se a equipe atacante conseguir fazer a ##
* ## proteção por esse tempo, será a vencedora. ##
* ### ###
* ##### #####
* ############################################################################
*/
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <string.h>
#define redLed 12 // Pino que o led vermelho está conectado
#define greenLed 13 // Pino que o led verde está conectado
#define soundTime 10 // Duração o buzz
String passwordDefuse = "0000000"; // Senha escolhida pelo operador para ser a master
String senhaValida01 = "7355608"; // Senha válida para utilização em jogo
String senhaValida02 = "1940781"; // Senha válida para utilização em jogo
String senhaValida03 = "0000000"; // Senha válida para utilização em jogo
String senhaValida04 = "1111111"; // Senha válida para utilização em jogo
String senhaValida05 = "2222222"; // Senha válida para utilização em jogo
String password = ""; // Senha digitada pelo operador
int tempoAcionada = 1800; // Definição de quanto tempo vai demorar para a bomba explodir;
int previousMillis = 0; // Variável que salva os millisegundos
int frequencia = 2000; // Definição da frequencia do buzzer
int duracaoBip = 120; // Duração do BIP
int interval = 1000; // Intervalo entre os bips do buzzer
int ledState = LOW; // Estado de ativação do LED
int speaker = 10; // Definição de qual pino o buzzer está ligado
bool jogoIniciado = false; // Indicador de início de jogo
bool senhaErrada = false; // Verificador se senha foi errada para decrementar 10s no tempo
const byte ROWS = 4; // Número de linhas do teclado
const byte COLS = 4; // Número de colunas do teclado
char keymap[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'},
};
byte rowPins[ROWS] = {9, 8, 7, 6}; // Pinos de conexão das linhas do keypad
byte colPins[COLS] = {5, 4, 3, 2}; // Pinos de conexão das colunas do keypad
Keypad keypad = Keypad(makeKeymap(keymap), rowPins, colPins, ROWS, COLS); // Instanciando o keypad
LiquidCrystal_I2C lcd(0x27, 20, 4); // Define o endereço do LCD para 0x27 para um display de 20 colunas e 4 linhas
/**
* Método default do arduino que inicia a aplicação
*/
void setup() {
lcd.begin(20, 4);
lcd.backlight();
pinMode(redLed, OUTPUT);
pinMode(greenLed, OUTPUT);
Serial.begin(9600);
// Mensagem de boas vindas
lcd.setCursor(0, 0);
lcd.print("********************");
lcd.setCursor(0, 1);
lcd.print("* CERBERUS *");
lcd.setCursor(0, 2);
lcd.print("* BOMBA C.A.T. *");
lcd.setCursor(0, 3);
lcd.print("********************");
// Aguarda 2 segundos para chamar a tela inicial da bomba
delay(2000);
menuInicial();
}
/**
* Método que exibe o "menu principal" de informe a senha
*/
void menuInicial() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Insira a senha: ");
lcd.setCursor(0, 1);
lcd.print("#######");
delay(100);
}
/**
* Método default do arduino que executa as ações em loop
*/
void loop() {
password = readKeypad();
lcd.setCursor(0, 1);
lcd.print(password);
if (password.length() == 7) {
if ((password == senhaValida01)
|| (password == senhaValida02)
|| (password == senhaValida03)
|| (password == senhaValida04)
|| (password == senhaValida05)) {
passwordDefuse = password;
} else {
senhaInvalida();
}
}
if (password == passwordDefuse) {
// Se a senha digitada no menu inicial for igual a senha de acionamento da bomba, inicia o jogo
password = "";
actionDefuse();
} else if (password.length() == 7){
// Caso contrário limpa o que foi escrito e informa que a senha está incorreta
senhaIncorreta();
}
}
/**
* Método que informa que a senha escolhida pelo operador é inválida para o jogo
*/
void senhaInvalida() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Senha Invalida!! ");
lcd.setCursor(0, 1);
lcd.print(" Por favor, utilize ");
lcd.setCursor(0, 2);
lcd.print(" uma das senhas dis-");
lcd.setCursor(0, 3);
lcd.print(" ponibilizadas. ");
password = "";
delay(10000);
menuInicial();
}
/**
* Método de início de jogo
*/
void actionDefuse() {
// Informa ao operador que a bomba foi armada e retorna para a tela de digitar a senha de desarme
int initialTime = (millis() / 1000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("** BOMBA ARMADA!! **");
delay(800);
menuInicial();
jogoIniciado = true;
// Inicia contagem regressiva para o desarme da bomba
int count = tempoAcionada;
while(count > 0) {
password = readKeypad();
lcd.setCursor(0, 1);
lcd.print(password);
// Caso a senha já possua os 7 caracteres digitados, chama o método de validação
if (password.length() == 7) {
validaGame();
}
// Caso a senha tenha sido digitada errada, retira 10 segundos do tempo total para o desarme
if (senhaErrada) {
tempoAcionada = tempoAcionada / 2;
senhaErrada = false;
}
// Instrução que informa o tempo restante na tela
int timeLeft = tempoAcionada - (millis() / 1000 - initialTime);
if (timeLeft < 10) {
lcd.setCursor(0, 3);
lcd.print(" T. Restante: 00");
} else if (timeLeft < 99) {
lcd.setCursor(0, 3);
lcd.print(" T. Restante: 0");
} else {
lcd.setCursor(0, 3);
lcd.print(" T. Restante: ");
}
lcd.print(timeLeft);
lcd.print("s ");
// Rotinas para mudança da velocidade do bip sonoro e led da contagem regressiva (ainda não funcional)
if (timeLeft <= 3) {
interval = 250;
} else if (timeLeft <= 5) {
interval = 400;
} else if (timeLeft <= 10) {
interval = 500;
} else if (timeLeft <= 15) {
interval = 600;
} else if (timeLeft <= 25){
interval = 700;
} else {
interval = 1000;
}
int currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
ledState = (ledState == LOW) ? HIGH : LOW;
digitalWrite(redLed, ledState);
digitalWrite(greenLed, !ledState);
tone(speaker, frequencia, duracaoBip);
}
// Caso a contagem chegue a zero informa na tela que o time Atacante venceu e dispara som da explosão
if (timeLeft <= 0) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("* BOMBA DETONADA!! *");
lcd.setCursor(0, 2);
lcd.print(" Vitoria do Ataque! ");
digitalWrite(redLed, HIGH);
digitalWrite(greenLed, LOW);
buzz();
while(1);
}
}
return;
}
/**
* Método que faz a leitura do teclado
*/
String readKeypad() {
char keyPressed = keypad.getKey();
String tecla = "";
if (keyPressed != '*' && keyPressed != '#') {
tecla = String(keyPressed);
}
password += tecla;
if (keyPressed != NO_KEY) {
if (keyPressed == '1') {
tone(speaker, frequencia * 1.25, duracaoBip);
} else if (keyPressed == '2') {
tone(speaker, frequencia * 1.25, duracaoBip);
} else if (keyPressed == '3') {
tone(speaker, frequencia * 1.25, duracaoBip);
} else if (keyPressed == '4') {
tone(speaker, frequencia * 1.25, duracaoBip);
} else if (keyPressed == '5') {
tone(speaker, frequencia * 1.25, duracaoBip);
} else if (keyPressed == '6') {
tone(speaker, frequencia * 1.25, duracaoBip);
} else if (keyPressed == '7') {
tone(speaker, frequencia * 1.25, duracaoBip);
} else if (keyPressed == '8') {
tone(speaker, frequencia * 1.25, duracaoBip);
} else if (keyPressed == '9') {
tone(speaker, frequencia * 1.25, duracaoBip);
} else if (keyPressed == '*') {
tone(speaker, frequencia * 1.25, duracaoBip);
clearConsole();
} else if (keyPressed == '0') {
tone(speaker, frequencia * 1.25, duracaoBip);
} else if (keyPressed == '#') {
tone(speaker, frequencia * 1.25, duracaoBip);
validaGame();
} else if (keyPressed == 'A') {
tone(speaker, frequencia * 1.25, duracaoBip);
} else if (keyPressed == 'B') {
tone(speaker, frequencia * 1.25, duracaoBip);
} else if (keyPressed == 'C') {
tone(speaker, frequencia * 1.25, duracaoBip);
} else if (keyPressed == 'D') {
tone(speaker, frequencia * 1.25, duracaoBip);
}
}
return password;
}
/**
* Validação de fim de jogo
*/
void validaGame() {
if (password == passwordDefuse) {
// Caso a senha informada esteja correta, dispara mensagem de fim de jogo
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("* BOMBA DESARMADA! *");
lcd.setCursor(0, 2);
lcd.print(" Vitoria da Defesa! ");
digitalWrite(greenLed, HIGH);
digitalWrite(redLed, LOW);
// Instrução para deixar a aplicação travada sem entrar em loop
while(1);
} else if ((password.length() == 7) && (password != passwordDefuse)) {
// Caso a senha informada esteja incorreta, chama método que informa que a senha foi digitada incorretamente
senhaIncorreta();
} else {
// Caso o método tenha sido chamado pelo # com a senha menor que 7, somente limpa o que foi digitado
clearConsole();
}
}
/**
* Método que informa que a senha digitada está incorreta
*/
void senhaIncorreta() {
if (jogoIniciado) {
senhaErrada = true;
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("* Senha Incorreta! *");
password = "";
delay(800);
menuInicial();
}
/**
* Som para quando finaliza o contador
*/
// void buzz() {
// for (frequencia = 2800; frequencia > 150; frequencia -= 1) {
// tone(speaker, frequencia, soundTime);
// // delay(1);
// }
// buzz();
// }
void buzz() {
for (frequencia = 150; frequencia < 1800; frequencia += 1) {
tone(speaker, frequencia, soundTime);
delay(1);
}
for (frequencia = 1800; frequencia > 150; frequencia -= 1) {
tone(speaker, frequencia, soundTime);
delay(1);
}
buzz();
}
/**
* Método que faz a limpeza de tudo que foi digitado
*/
void clearConsole() {
password = "";
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Limpando Console!");
delay(800);
lcd.clear();
menuInicial();
}