Genius comentado
Tempos atrás eu fiz um Genius (game dos anos 80, vc pode conferir o bicho funcionando aqui embaixo):
Fazer games tem os seus desafios: tem que levar em conta a ergonomia, quer dizer, montar o circuito de maneira que o jogador consiga ter acesso aos comandos. Depois, o programa tem que ser rápido e consistente, de maneira a fazer o jogador ter uma experiência adequada. Acho que ficou legal.
Vc pode ver no vídeo o "meu" Genius funcionando:
Abaixo, como prometido, o código comentado:
A ideia é repetir uma sequência de sons e cores criadas aleatoriamente pelo jogo. Como ele tem muitas coisas interessantes em termos de software, vou fazer um post mais detalhado aqui
Esse é o circuito montado. Usei um tweeter velho desses de carro para fazer o som, ficou legal, bem alto. Um LED de cada cor, um botão correspondente a cada cor e som.
Aqui mais de perto:
E o esquema no Fritzing:
Fazer games tem os seus desafios: tem que levar em conta a ergonomia, quer dizer, montar o circuito de maneira que o jogador consiga ter acesso aos comandos. Depois, o programa tem que ser rápido e consistente, de maneira a fazer o jogador ter uma experiência adequada. Acho que ficou legal.
Vc pode ver no vídeo o "meu" Genius funcionando:
Abaixo, como prometido, o código comentado:
// biblioteca que define as frequências das notas musicais
#include <Piches.h>
// pino onde está conectado o buzzer (ou auto-falante)
#define buzzer 3
// o programa foi feito como uma máquina de estados, estes são os estados possíveis
#define waitingStart 0 // esperando o jogo começar
#define playingSeq 1 // tocando a sequencia pro usuário repetir
#define userTyping 3 // lendo a sequencia que o cara tá teclando
#define validatingSeq 4 // validando
// pinos onde estáo ligadas as teclas. Devem ser em sequencia, a menor o vermelho.
#define kred 11
#define kyellow 10
#define kgreen 9
#define kwhite 8
//pinos onde estão ligados os LEDs. Devem ser em sequencia, o menor o vermelho.
#define lred 7
#define lyellow 6
#define lgreen 5
#define lwhite 4
// define modo debug (=1)
#define debugging 0
// duração da nota
int interval = 500;
// intervalo entre as notas
int noSound = 200;
// guarda a sequência atual
int seq[50];
// indexador da sequência tocada
int posSeq = 0;
// indexador da sequência digitada
int posType = 0;
// estado corrente
int state = waitingStart;
// tecla pressionada
int key = 0;
void setup()
{
// seta modo dos pinos
pinMode(lred, OUTPUT);
pinMode(lyellow, OUTPUT);
pinMode(lgreen, OUTPUT);
pinMode(lwhite, OUTPUT);
pinMode(kred, INPUT);
pinMode(kyellow, INPUT);
pinMode(kgreen, INPUT);
pinMode(kwhite, INPUT);
noSound = 0;
// inicializa gerador de números aleatórios do Arduino:
// eu uso o valor lido de uma porta analógica desconectada,
// que tem sempre algum valor devido à alta impedância dessas
// portas
randomSeed(analogRead(0));
// faz uma "gracinha"
demo();
noSound = 50;
Serial.begin(9600);
// cria a prmeira sequência
generateSeq();
}
void loop() {
// máquina de estados: processa os diferentes estados do programa
switch(state)
{
case waitingStart:
// reseta o intervalo
interval = 500;
if (debugging)
Serial.println("waitingStart");
// espera o usuário digitar algo
key = readKey(false);
// quando isso ocorre, muda o estado para o próximo
state = playingSeq;
return;
case playingSeq:
if (debugging)
Serial.println("playingSeq");
// toca a sequência e seta o próximo estado
playSeq();
posType = 0;
state = userTyping;
return;
case userTyping:
if (debugging)
Serial.println("userTyping");
key = 1;
int ok = true;
// enquanto o usuário estiver digitando certo, fica nesse estado
while(ok)
{
key = readKey(true);
// se o usuário não digitou nada, dançou
if (key == 0)
break;
// toca a nota digitada pelo usuário
play(key-(lred-kred));
// valida a tecla digitada
ok = validateSeq(key);
if (debugging)
{
Serial.print("ok=");
Serial.println(ok);
}
// se ok...
if (ok)
{
// se o usuário terminou a sequência...
if (posType == posSeq)
{
// dá um intervalo de um segundo...
delay(1000);
// aumenta o tamanho da próxima sequência
posSeq++;
// agora o intervalo é 5% menor
interval = interval * 0.95;
// volta o estado para playingSeq
state = playingSeq;
return;
}
else
{
// usuário ainda não terminou.
posType++;
}
}
}
// se chegou aqui, o usuário teclou errado.
playWrong();
Serial.print("Voce fez ");
Serial.println(posSeq);
// gera nova sequência
generateSeq();
// volta o estado para o inicial
state = waitingStart;
return;
}
}
int validateSeq(int key)
{
return (key-(lred-kred)) == seq[posType]; // (key-3) = key to LED
}
// espera e lê a tecla digitada pelo usuário. Se vallidateMilis = 1,
// retorna 0 após 3 segundos
int readKey(int validateMilis)
{
unsigned long ms = millis();
int value = LOW;
while(value == LOW)
{
for (int i = kred; i >= kwhite; i--)
{
if (validateMilis)
if ((millis() - ms) > 3000)
{
if (debugging)
Serial.println("Timeout");
return 0;
}
value = digitalRead(i);
if (value == HIGH)
{
return i;
}
}
}
}
// toca uma determinada nota (pitch), com uma determinada duração (duration)
void playPich(int pich, int duration)
{
tone(buzzer, pich);
delay(duration);
noTone(buzzer);
}
// toca a Imperial March (tema do Darth Vader no StarWars)
void playWrong()
{
int ritym = 500;
for(int i = 0; i < 2; i++)
{
digitalWrite(lred, HIGH);
digitalWrite(lyellow, HIGH);
digitalWrite(lgreen, HIGH);
digitalWrite(lwhite, HIGH);
playPich(NOTE_A3, ritym);
playPich(NOTE_A3, ritym);
playPich(NOTE_A3, ritym);
playPich(NOTE_F3, ritym * 3 / 4);
playPich(NOTE_C4, ritym * 1 / 4);
playPich(NOTE_A3, ritym);
playPich(NOTE_F3, ritym * 3 / 4);
playPich(NOTE_C4, ritym * 1 / 4);
playPich(NOTE_A3, ritym * 2);
playPich(NOTE_E4, ritym);
playPich(NOTE_E4, ritym);
playPich(NOTE_E4, ritym);
playPich(NOTE_F4, ritym * 3 / 4);
playPich(NOTE_C4, ritym * 1 / 4);
playPich(NOTE_GS3, ritym);
playPich(NOTE_F3, ritym * 3 / 4);
playPich(NOTE_C4, ritym * 1 / 4);
playPich(NOTE_A3, ritym * 2);
digitalWrite(lred, LOW);
digitalWrite(lyellow, LOW);
digitalWrite(lgreen, LOW);
digitalWrite(lwhite, LOW);
noTone(buzzer);
delay(500);
}
}
// toca a demo
void demo()
{
interval = 500;
while(interval > 5)
{
play(lred);
play(lyellow);
play(lgreen);
play(lwhite);
interval = interval / 1.5;
}
}
// toca uma nota, pisca o LED correspondente
void blink(int led, int pich)
{
tone(buzzer,pich);
digitalWrite(led, HIGH);
delay(interval);
digitalWrite(led, LOW);
noTone(buzzer);
delay(noSound);
}
// toca uma nota
void play(int pich)
{
switch(pich)
{
case lred:
blink(lred,NOTE_C4);
break;
case lyellow:
blink(lyellow,NOTE_E4);
break;
case lgreen:
blink(lgreen,NOTE_G4);
break;
case lwhite:
blink(lwhite,NOTE_AS4);
break;
}
}
// gera a sequência de notas, aleatória
void generateSeq()
{
posSeq = 0;
if (debugging)
Serial.println("generateSeq");
int note;
for (int i = 0; i < 50; i++)
{
seq[i] = random(4) + 4;
if (debugging)
Serial.println(seq[i]);
}
}
// toca a sequência
void playSeq()
{
for (int i = 0; i <= posSeq; i++)
{
play(seq[i]);
}
}

Cara fiz a montagem como você mostrou mas os botões não estão funcionando
ResponderExcluir