Índice:
Vídeo: Jogo Arduino OLED Snake: 3 etapas
2024 Autor: John Day | [email protected]. Última modificação: 2024-01-30 11:37
Olá e bem-vindo, às nossas instruções sobre como fazer um jogo OLED arduino, este projeto surgiu quando estávamos tentando fazer nosso primeiro jogo com um arduino, muuuuito, pensamos em onde melhor começar do que o clássico do nokia Snake (bem em pelo menos um clone de cobra:)).
O que você vai precisar
Suprimentos
Arduino UNO ou clone
Display OLED
4 diodos
Resistor 500-1k
4 botões de controle
Campainha Piezo passiva
opcional
Pão sem solda
Observe que esses links são apenas para exemplo
Etapa 1: O circuito
Na imagem acima você pode ver nosso circuito, usamos o pino d3 no arduino como um pino de solicitação de interrupção para que o arduino dê prioridade à leitura das entradas do controlador que são d4 d5 d6 d7. O básico do circuito é que um botão de direção é pressionado que vai alto 5v, isso ativa o pino de solicitação de interrupção (fio roxo d3) e um pino de direção correspondente, a função de interrupção chama uma função de atualização de direção e esse código move a cobra de acordo. O pino 9 é usado como o pino de som, pois é um PWM (modulação de largura de pulso ~) que é conectado diretamente a um piezo de 5v no pino + e - volta para 0v / terra.
(Para sua informação no arduino uno e clones apenas d2 e d3 podem atuar como pinos de solicitação de interrupção).
Alfinetes de direção:
d4 Up LARANJA
d5 Down PINK
d6 Esquerdo AZUL
d7 MARROM DIREITO
d9 som CINZA
Cada botão tem uma entrada de conexão em 5v e uma saída que é conectada primeiro à sua respectiva entrada digital no Arduino, esta mesma saída de cada botão é então conectada ao seu próprio diodo, usamos os diodos para parar a alimentação de tensão de volta para o outros botões e ativando-os. Na extremidade do cátodo (-) de todos os 4 diodos, nós os juntamos para criar uma junção de saída que se conecta a d3 e, em seguida, através de um resistor a 0v / terra para puxar os pinos do arduino para baixo de modo a não deixar os pinos flutuantes quando não estiverem ativado.
(Para sua informação, um pino flutuante pode receber tensão fantasma e causar um comportamento incomum)
2 pinos analógicos são usados para conduzir a tela, estes são os pinos i2c do hardware do Arduino.
A5 está conectado a SCL AMARELO
A4 está conectado a SDA GREEN
A saída de + 5v e 0v (terra) do arduino é usada como fonte de energia para todo o circuito, que pode ser alimentado por USB ou carregador de telefone.
Etapa 2: O Código
// ------------------------ Jogos ANJAWARE SNAKE Com a ajuda dos povos da Internet --------------- -------
#incluir
#include // https://github.com/adafruit/Adafruit-GFX-Library #include // https://github.com/adafruit/Adafruit-GFX-Library // conjunto de exibição (largura, altura) exibição Adafruit_SSD1306 (128, 64); // define os pinos de entrada, esses são os pinos no arduino, eles nunca mudam, então #define #define INTPIN 3 // apenas os pinos 2 e 3 podem ser pinos de interrupção em UNO #define UPPIN 4 // esses são pinos conectados ao switch relevante #define DWNPIN 5 #define LFTPIN 6 #define RHTPIN 7 #define SND 9 // define direções #define DIRUP 1 // esses valores é o que a "cobra" olha para decidir- #define DIRDOWN 2 // a direção em que a cobra vai viajar # definir DIRLEFT 3 #define DIRRIGHT 4
// definir variáveis de botão
// volitile porque precisamos atualizar com a interrupção, então pode ser qualquer bit de valor de ciclo
// nunca é maior que 4, portanto, só precisa de 8 bits int para economizar recursos volatile uint8_t buttonpressed = 0; bool butup = 0; bool butdown = 0; // usamos isso para definir true para "detectar" em qual direção pressionado bool butleft = 0; bool butright = 0;
// snake ints
byte snakePosX [30]; // array para criar o corpo do byte snake snakePosY [30];
int snakeX = 30; // posição da cabeça da cobra
int snakeY = 30; int snakeSize = 1; // contagem do tamanho da cobra limitada ao tamanho da matriz
// world ints
uint8_t worldMinX = 0; // estes definem os limites da área de jogo
uint8_t worldMaxX = 128; uint8_t worldMinY = 10; uint8_t worldMaxY = 63;
// coleta o scran (alimento) e a posição do scran
bool scranAte = 0; uint8_t scranPosX = 0; uint8_t scranPosY = 0;
// pontua variáveis
pontuação longa = 0; recorde longo = 30; // defina a pontuação mais alta para 3 coletar como ponto de partida
// --------------------------- isto é o que a interrupção executa no aumento de tensão ------------ -------------
vazio interrompido () {atraso (150); // pequeno atraso para proteção de "salto" adicionada updatedirection (); } // ------------------ atualiza o valor de direção ao pressionar o botão ----------------- void updatedirection () { // Serial.println ("updatesdirection"); butup = digitalRead (UPPIN); // verificar qual entrada foi alta e definir relevante bool true butdown = digitalRead (DWNPIN); butleft = digitalRead (LFTPIN); butright = digitalRead (RHTPIN); // estes if statemeents olham para qual input foi alto e insere o valor relevante na variável "buttonpressed" //, esta variável dita a direção do movimento if (butup == true) {buttonpressed = DIRUP; // Serial.println ("UP pressionado"); // Serial.println (buttonpressed); butup = falso; tom (SND, 1500, 10); } if (butdown == true) {buttonpressed = DIRDOWN; // Serial.println ("pressionado para BAIXO"); // Serial.println (buttonpressed); butdown = false; tom (SND, 1500, 10); }
if (butleft == true)
{buttonpressed = DIRLEFT; // Serial.println ("LEFT pressionado"); // Serial.println (buttonpressed); butleft = false; tom (SND, 1500, 10); } if (butright == true) {buttonpressed = DIRRIGHT; // Serial.println ("RIGHT pressionado"); // Serial.println (buttonpressed); butright = false; tom (SND, 1500, 10); }}
// -------------------------- desenha as rotinas de exibição ------------------ -----------------
void updateDisplay () // desenha pontuações e contornos
{// Serial.println ("Atualizar exibição");
display.fillRect (0, 0, display.width () - 1, 8, PRETO);
display.setTextSize (0); display.setTextColor (WHITE); // desenha as pontuações display.setCursor (2, 1); display.print ("Pontuação:"); display.print (String (playcore, DEC)); display.setCursor (66, 1); display.print ("Alto:"); display.print (String (highscore, DEC)); // desenha a área de jogo // pos 1x, 1y, 2x, 2y, color display.drawLine (0, 0, 127, 0, WHITE); // borda superior display.drawLine (63, 0, 63, 9, WHITE); // separador de pontuação display.drawLine (0, 9, 127, 9, WHITE); // abaixo da borda do texto display.drawLine (0, 63, 127, 63, WHITE); // borda inferior display.drawLine (0, 0, 0, 63, WHITE); // borda esquerda display.drawLine (127, 0, 127, 63, WHITE); // borda direita
}
// ----------------------------------- atualizar área de jogo ---------- --------------------
void updateGame () // atualiza a exibição da área de jogo
{display.clearDisplay ();
display.drawPixel (scranPosX, scranPosY, WHITE);
scranAte = scranFood ();
// verificar as rotinas da cobra
if (outOfArea () || selfCollision ())
{ fim de jogo(); }
// exibir cobra
para (int i = 0; i0; i--) {snakePosX = snakePosX [i-1]; snakePosY = snakePosY [i-1]; } // adiciona um pixel extra à cobra if (scranAte) {snakeSize + = 1; snakePosX [snakeSize-1] = snakeX; snakePosY [snakeSize-1] = snakeY; }
switch (buttonpressed) // era snakeDirection
{caso DIRUP: cobraY- = 1; pausa; caso DIRDOWN: snakeY + = 1; pausa; caso DIRLEFT: snakeX- = 1; pausa; caso DIRRIGHT: snakeX + = 1; pausa; } snakePosX [0] = snakeX; snakePosY [0] = snakeY; updateDisplay (); display.display (); // --------------------- coloque o scran -------------------
void placeScran ()
{scranPosX = aleatório (worldMinX + 1, worldMaxX-1); scranPosY = aleatório (worldMinY + 1, worldMaxY-1); } // ------------------------ SCRAN ATE POINT UP ---------------- bool scranFood () {if (snakeX == scranPosX && snakeY == scranPosY) {playcore = playscore + 10; tom (SND, 2000, 10); updateDisplay (); placeScran (); return 1; } else {return 0; } } //--------------------- fora da área---------------------- bool outOfArea () {return snakeX = worldMaxX || snakeY = worldMaxY; } //---------------------- fim de jogo----------------------- --- void gameOver () {uint8_t rectX1, rectY1, rectX2, rectY2; rectX1 = 38; rectY1 = 28; rectX2 = 58; rectY2 = 12; display.clearDisplay (); display.setCursor (40, 30); display.setTextSize (1); tom (SND, 2000, 50); display.print ("GAME"); tom (SND, 1000, 50); display.print ("OVER"); if (playscore> = playscore) // verifique se a pontuação é maior que a pontuação alta {highscore = playscore; // única instrução if para atualizar a pontuação mais alta} para (int i = 0; i <= 16; i ++) // isso é para desenhar retângulos em torno do jogo em {display.drawRect (rectX1, rectY1, rectX2, rectY2, WHITE); Serial.println ("se loop"); display.display (); rectX1- = 2; // desloca em 2 pixels rectY1- = 2; rectX2 + = 4; // desloca mais de 2 pixels do último ponto rectY2 + = 4; tom (SND, i * 200, 3); } display.display (); // Tela Wipe após fama sobre rectX1 = 0; // define a posição inicial da linha rectY1 = 0; rectX2 = 0; rectY2 = 63; para (int i = 0; i <= 127; i ++) {uint8_t cnt = 0; display.drawLine (rectX1, rectY1, rectX2, rectY2, BLACK); rectX1 ++; rectX2 ++; display.display (); } display.clearDisplay (); playcore = 0; // redefine os detalhes da cobra e do jogador snakeSize = 1; snakeX = display.width () / 2; cobraY = display.height () / 2; waitForPress (); // aguarde o jogador iniciar o jogo} // ------------------------- aguarde o loop de pressionamentos ---------- --------------- vazio waitForPress () {bool esperando = 0; // o loop termina quando isso é verdadeiro display.clearDisplay (); enquanto (esperando == 0) {drawALineForMe (WHITE); // desenha uma linha branca aleatória drawALineForMe (BLACK); // desenha uma linha preta aleatória para que a tela não preencha completamente o branco display.fillRect (19, 20, 90, 32, BLACK); // fundo em branco para texto display.setTextColor (WHITE); display.setCursor (35, 25); display.setTextSize (2); // fonte maior display.println ("SNAKE"); // x y w h r col display.drawRoundRect (33, 22, 62, 20, 4, WHITE); // border Snake display.drawRect (19, 20, 90, 32, WHITE); // caixa de borda - 3 display.setCursor (28, 42); display.setTextSize (0); // fonte de volta ao normal display.println ("pressione qualquer tecla"); display.display (); esperando = digitalRead (INTPIN); // verifique se a tecla em espera pressionada mudará para 1 terminando enquanto buttonpressed = 0; // botão de reset pressionado}} // -------------------- DESENHE uma cor de entrada de linha aleatória uint8_t -------------- ----- vazio drawALineForMe (uint8_t clr) {uint8_t linha1X, linha1Y, linha2X, linha2Y = 0; // definir coordenadas aleatórias para uma linha e então desenhá-la // variável nem menos nem mais line1X = random (worldMinX + 1, worldMaxX-1); linha1Y = aleatório (worldMinY + 1, worldMaxY-1); line2X = aleatório (worldMinX + 1, worldMaxX-1); linha2Y = aleatório (worldMinY + 1, worldMaxY-1); display.drawLine (linha1X, linha1Y, linha2X, linha2Y, clr); } // ------------------------------------- detecção de colisão -------- -----------------------
for (byte i = 4; i <snakeSize; i ++) {if (snakeX == snakePosX && snakeY == snakePosy ) {return 1; tom (SND, 2000, 20); tom (SND, 1000, 20); } return 0; }
//-------------------------------- CONFIGURAR--------------- -------------------------------
configuração vazia () {atraso (100); // apenas dê ao material uma chance de "inicializar" // Serial.begin (9600); // desmarque se quiser ver as saídas seriais display.begin (SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay (); // começa com uma exibição limpa display.setTextColor (WHITE); // configura o tamanho da rotação da cor do texto etc display.setRotation (0); display.setTextWrap (false); display.dim (0); // define o brilho do display pinMode (INTPIN, INPUT); // define as portas corretas para entradas pinMode (UPPIN, INPUT); pinMode (DWNPIN, INPUT); pinMode (LFTPIN, INPUT); pinMode (RHTPIN, INPUT); // este é o comando de interrupção que "pára" o arduino para ler as entradas // comando-função-pino-função para executar a condição no pino attachInterrupt (digitalPinToInterrupt (INTPIN), interrompido, RISING); // Serial.println ("Configuração aprovada"); waitForPress (); // exibe a tela de inicialização do snake placeScran (); // coloque o primeiro pedaço de comida} // --------------------- MAIN LOOP ----------------- ---------------------- void loop () {updateGame (); // esta função é o que carrega o código principal}
Etapa 3:
Recomendado:
Jogo eletrônico do jogo da velha em uma caixa de madeira: 5 etapas
Jogo eletrônico do jogo da velha em uma caixa de madeira: Olá, eu apresento o jogo engraçado do jogo da velha em uma nova edição. Pesquisei na web por projetos semelhantes, mas a ideia aqui é única. ESPERO:) Então, vamos começar agora
Jogo Aruduino LED Jogo de dois jogadores com cliques rápidos: 8 etapas
Aruduino LED Game Jogo de dois jogadores com cliques rápidos: Este projeto é inspirado em @HassonAlkeim. Se você estiver disposto a dar uma olhada profunda, aqui está um link que você pode verificar https://www.instructables.com/id/Arduino-Two-Player-Fast-Button-Clicking-Game/. Este jogo é uma versão melhorada do Alkeim. É um
Controlador de jogo DIY baseado em Arduino - Controlador de jogo Arduino PS2 - Jogando Tekken com gamepad Arduino DIY: 7 etapas
Controlador de jogo DIY baseado em Arduino | Controlador de jogo Arduino PS2 | Jogando Tekken com DIY Arduino Gamepad: Olá pessoal, jogar é sempre divertido, mas jogar com seu próprio controlador de jogo DIY personalizado é mais divertido. Portanto, faremos um controlador de jogo usando arduino pro micro neste instructables
Controlador de jogo Arduino com luzes que respondem ao seu jogo Unity :: 24 etapas
Controlador de jogo Arduino com luzes que respondem ao seu jogo Unity :: Primeiro, escrevi isso em palavras. Esta é a primeira vez que uso instructable so sempre que digo: escreva código assim, saiba que estou me referindo à imagem no topo dessa etapa. Neste projeto eu uso 2 arduino ’ s para executar 2 bits separados
Como verificar se um jogo será executado em seu computador antes de comprar o jogo .: 4 etapas
Como verificar se um jogo pode rodar no seu computador antes de comprá-lo .: Adquiri recentemente o Call of Duty 4 de um amigo (de graça, devo acrescentar) porque não rodava no computador dele. Bem, o computador dele é relativamente novo e fiquei perplexo porque não funcionava. Depois de algumas horas de pesquisa na Internet, descobri