Aprenda a recriar um dos jogos mais icônicos do início da era dos celulares com o seu Arduino! Neste projeto DIY, você montará o clássico Jogo da Cobrinha com Arduino, utilizando poucos componentes e muito entretenimento garantido.
O Jogo da Cobrinha é atemporal e pode ser a porta de entrada para o universo Maker. Portanto, com criatividade e vontade de colocar a mão na massa, é possível construir esse projeto com facilidade e diversão. Além disso, você pode personalizar o funcionamento do jogo, tornando a experiência ainda mais interessante.
Equipamentos Necessários
Como Funciona o Jogo da Cobrinha
O funcionamento do Jogo da Cobrinha com Arduino é simples e divertido. Os botões, configurados com resistores pull-up internos no Arduino, detectam o clique ao serem pressionados, mudando o estado para LOW. Portanto, a matriz de LED 8×8 exibe a cobrinha e os alimentos para que ela cresça. Além disso, o jogo inclui condições de vitória e derrota, aumentando o desafio.
Você pode personalizar as seguintes configurações do jogo:
- Comprimento máximo da cobrinha: Ajuste a variável
max_len
para alterar o número máximo de segmentos. - Velocidade do jogo: Modifique o delay no final do
void loop
para acelerar ou desacelerar. - Tela de vitória: Customize a animação em
win_scene
.
Portanto, com essas opções, o projeto fica ainda mais flexível e criativo. Além disso, você poderá adicionar desafios e melhorias à estrutura do jogo.
Programando o Jogo da Cobrinha
// O MAX7219 utiliza o protocolo de comunicação SPI... Portanto, importe a biblioteca SPI.h
#include <SPI.h>
// O pino de seleção do chip
#define CS 10
// Alguns registradores necessários para configurar o chip MAX7219
#define DECODE_MODE 9
#define INTENSITY 0x0A
#define SCAN_LIMIT 0x0B
#define SHUTDOWN 0x0C
#define DISPLAY_TEST 0x0F
// Botões usados para controlar a cobra
#define left_button 2
#define right_button 3
volatile byte move_left = 0;
volatile byte move_right = 0;
// Variáveis para a cobra
int snake_l = 2;
const int max_len = 30;
int snake[max_len][2];
byte cur_heading = 0;
// Variável para o alimento da cobra
int blob[2] = { 0, 0 };
int is_eaten = 1;
// A cena do jogo
byte scene[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
// Função geral para enviar dados ao MAX7219
void SendData(uint8_t address, uint8_t value) {
digitalWrite(CS, LOW);
SPI.transfer(address); // Enviar o endereço.
SPI.transfer(value); // Enviar o valor.
digitalWrite(CS, HIGH); // Finalizar a transferência.
}
// Função para inicializar as variáveis do jogo
void init_game() {
is_eaten = 1;
move_left = 0;
move_right = 0;
cur_heading = 0;
snake_l = 2;
for (int i = 0; i < max_len; i++)
for (int j = 0; j < 2; j++)
snake[i][j] = 0;
snake[max_len - 1][0] = 2;
snake[max_len - 1][1] = 5;
snake[max_len - 2][0] = 1;
snake[max_len - 2][1] = 5;
refresh_scene();
while ((move_left || move_right) == 0)
;
move_left = 0;
move_right = 0;
}
// Função para desenhar a cobra na cena do jogo
void spawn_snake() {
// Se a cobra sair da cena, ela entra pelo outro lado
for (int j = max_len - snake_l; j < max_len; j++) {
if (snake[j][0] <= 0)
snake[j][0] = 8 + snake[j][0];
else if (snake[j][0] >= 9)
snake[j][0] = snake[j][0] - 8;
if (snake[j][1] <= 0)
snake[j][1] = 8 + snake[j][1];
else if (snake[j][1] >= 9)
snake[j][1] = snake[j][1] - 8;
// Desenhar a cobra na matriz de LED
scene[snake[j][0] - 1] |= (1 << (snake[j][1] - 1));
}
}
// Função para atualizar a posição e o tamanho da cobra
void snake_move() {
// Se a cobra comer o alimento, aumenta de tamanho
if (snake[max_len - 1][0] == blob[0] && snake[max_len - 1][1] == blob[1]) {
is_eaten = 1;
snake_l += 1;
}
// Mover cada segmento da cobra para frente
for (int i = snake_l - 1; i >= 1; i--) {
snake[max_len - 1 - i][0] = snake[max_len - i][0];
snake[max_len - 1 - i][1] = snake[max_len - i][1];
}
// Mover a cabeça da cobra com base nos botões
if (move_left == 1) {
if (cur_heading == 0) {
cur_heading = 1;
snake[max_len - 1][1] -= 1;
} else if (cur_heading == 1) {
cur_heading = 2;
snake[max_len - 1][0] -= 1;
} else if (cur_heading == 2) {
cur_heading = 3;
snake[max_len - 1][1] += 1;
} else if (cur_heading == 3) {
cur_heading = 0;
snake[max_len - 1][0] += 1;
}
move_left = 0;
} else if (move_right == 1) {
if (cur_heading == 0) {
cur_heading = 3;
snake[max_len - 1][1] += 1;
} else if (cur_heading == 1) {
cur_heading = 0;
snake[max_len - 1][0] += 1;
} else if (cur_heading == 2) {
cur_heading = 1;
snake[max_len - 1][1] -= 1;
} else if (cur_heading == 3) {
cur_heading = 2;
snake[max_len - 1][0] -= 1;
}
move_right = 0;
} else {
if (cur_heading == 0) {
snake[max_len - 1][0] += 1;
} else if (cur_heading == 1) {
snake[max_len - 1][1] -= 1;
} else if (cur_heading == 2) {
snake[max_len - 1][0] -= 1;
} else if (cur_heading == 3) {
snake[max_len - 1][1] += 1;
}
}
}
// Função para gerar um alimento e desenhá-lo na cena do jogo
void blob_generator() {
// Se o alimento for comido pela cobra, gera um novo
if (is_eaten) {
blob[0] = random(1, 9);
blob[1] = random(1, 9);
}
// Desenhar o alimento na cena do jogo
scene[blob[0] - 1] |= (1 << (blob[1] - 1));
is_eaten = 0;
}
// Função para atualizar a cena do jogo na matriz de LED com as variáveis atualizadas
void refresh_scene() {
for (int i = 0; i < 8; i++)
scene[i] = 0x00;
snake_move();
spawn_snake();
blob_generator();
for (int i = 1; i < 9; i++)
SendData(i, scene[i - 1]);
}
// Callback para interrupção do botão esquerdo
void update_left() {
move_left = 1;
}
// Callback para interrupção do botão direito
void update_right() {
move_right = 1;
}
// Função de configuração
void setup() {
// Configuração dos pinos
pinMode(left_button, INPUT_PULLUP);
pinMode(right_button, INPUT_PULLUP);
pinMode(CS, OUTPUT);
// Configuração do SPI
SPI.setBitOrder(MSBFIRST); // Enviar o bit mais significativo primeiro
SPI.begin(); // Iniciar SPI
SendData(DISPLAY_TEST, 0x00); // Sair do modo de teste
SendData(DECODE_MODE, 0x00); // Desativar o modo BCD
SendData(INTENSITY, 0x0F); // Usar a intensidade máxima (F = 15)
SendData(SCAN_LIMIT, 0x0f); // Escanear todos os dígitos
SendData(SHUTDOWN, 0x01); // Ligar o chip
// Gerar uma semente aleatória... Utiliza o ruído no canal analógico 0
randomSeed(analogRead(0));
// Associar interrupções aos botões
attachInterrupt(digitalPinToInterrupt(left_button), update_left, FALLING);
attachInterrupt(digitalPinToInterrupt(right_button), update_right, FALLING);
// Habilitar interrupções
sei();
// Iniciar o jogo
init_game();
}
void loop() {
// Verificar se a cobra atingiu o tamanho máximo
if (snake_l == max_len) {
// Se sim, exibe a mensagem de vitória e reinicia
byte win_scene[8] = { B11100011, B00100100, B01000010, B11100100, B00000011, 0, B00011100, 0 };
for (int i = 1; i < 9; i++)
SendData(i, win_scene[i - 1]);
delay(5000);
init_game();
}
// Verificar se a cobra colidiu consigo mesma
for (int i = 0; i < max_len - 1; i++) {
if (snake[i][0] == snake[max_len - 1][0] && snake[i][1] == snake[max_len - 1][1]) {
// Se sim, pisca todos os LEDs e reinicia o jogo
delay(1000);
for (int j = 0; j < 4; j++) {
SendData(DISPLAY_TEST, 0x01);
delay(500);
SendData(DISPLAY_TEST, 0x00);
delay(500);
}
init_game();
break;
}
}
// Continuar atualizando a matriz com dados atualizados...
refresh_scene();
// ...A cada 0,5 segundos
delay(250);
}
Passo a Passo para Construção do Jogo da Cobrinha
- Conecte a matriz de LED ao módulo MAX7219 e depois ao Arduino, respeitando as conexões do protocolo SPI.
- Instale os botões na protoboard e conecte-os aos pinos configurados no código, usando resistores pull-up internos.
- Suba o código no Arduino usando a IDE apropriada.
- Teste o jogo, ajustando as configurações de velocidade e comprimento, caso deseje.
Considerações Finais
O Jogo da Cobrinha com Arduino em sua versão DIY é um projeto divertido, educativo e personalizável. Ele demonstra a facilidade de criar jogos eletrônicos utilizando Arduino e componentes simples. Portanto, continue acompanhando o Prototipando para descobrir mais projetos, aprender novas técnicas e explorar o mundo Maker com criatividade. Além disso, não perca as dicas e as tendências que compartilhamos regularmente!