Proxecto: xogo de reflexos
Agora imos dar un salto substancial, e imos cargar xa un código con certa complexidade. Non é o obxectivo que entendas perfectamente todo o programa, senón que te acostumes a hackear códigos alleos para obter os resultados que ti desexes, así que o único que tes que facer agora é cargar o programa no Arduino e comprobar o seu funcionamento. Repara que a montaxe é a mesma que o anterior exercicio.
/*Xogo de reflexos, debes pulsar o botón cando se acenda o led do medio, se acertas subirás un nivel, se fallas perderás. Podes comprobar o teu nivel polo monitor serie*/
//definimos os pines onde van os leds e o boton
int led1=8;
int led2=9;
int led3=10;
int boton=11;
//definimos as variables que necesitaremos para ter conta do tempo
long tempoActual=0;
long tempoAceso=1200;
//definimos unha variable que almacenara o numero aleatorio que fai que
//se encenda un led determinado
long numeroChou;
//led2Aceso nos indicara se o led numero 2, ao que temos que reaccionar
// estara ou non aceso. Por iso e "boolean" que so admite "true" o "false"
boolean led2Aceso;
//estas duas variables nos serviran para ter conta das pulsacions do boton
int botonAntes=0;
int botonAgora;
//esta variable nos servira para ter conta do nivel ao que chegamos
int nivel=0;
void setup() {
//iniciamos a comunicacion serie e informamos do comezo
Serial.begin(9600);
Serial.println("Comezas no nivel 0!...");
delay(1000);
Serial.println("Adiante!");
//definimos os pines dos leds como saidas e o boton coma entrada
pinMode(led1,OUTPUT);
pinMode(led2,OUTPUT);
pinMode(led3,OUTPUT);
pinMode(boton,INPUT);
}
void loop(){
//chamamos a funcion de encendido
encendeLeds();
//leremos o boton e comparamos
compara();
}
//funcion de encendido de Leds
void encendeLeds() {
//comproba se xa pasou o intervalo de tempo que definimos como tempoAceso
if ((millis()-tempoActual)>tempoAceso){
//Escollemos un numero ao chou que pode ser 1,2 ou 3
numeroChou=random(1,4);
//segundo o numero que saia, encendemos un led ou outro e definimos se led2Aceso
//e "true" o "false"
switch (numeroChou) {
case 1:
digitalWrite (led1,HIGH);
digitalWrite (led2,LOW);
digitalWrite (led3,LOW);
led2Aceso=false;
break;
case 2:
digitalWrite (led1,LOW);
digitalWrite (led2,HIGH);
digitalWrite (led3,LOW);
led2Aceso=true;
break;
case 3:
digitalWrite (led1,LOW);
digitalWrite (led2,LOW);
digitalWrite (led3,HIGH);
led2Aceso=false;
break;
}
//con esta liña "reseteamos" o tempoActual
tempoActual=millis();
}
}
//funcion que le o boton e comproba se acertamos
void compara() {
//Leo o boton
botonAgora=digitalRead(boton);
//Comparo se o boton cambiou de estado
//Se cambiou de estado e, ademais, vale 1
if (botonAgora!=botonAntes && botonAgora==1){
//Se o que estaba aceso non era o led 2 e chamo a funcion "perdiches()"
if (led2Aceso==false) {
perdiches();
}
//en caso contrario sera que o fixen ben e chamo a funcion "acertas()"
else {
acertas();
}
}
//Se non cambiou de estado, transformo o estado actual en estado anterior
else {
botonAntes=botonAgora;
}
}
//Funcion en caso de perder
void perdiches(){
//Encendo e apago os tres leds durante 0,3 seg, cinco veces
for (int i=0;i<5;i++){
digitalWrite (led1,HIGH);
digitalWrite (led2,HIGH);
digitalWrite (led3,HIGH);
delay(300);
digitalWrite (led1,LOW);
digitalWrite (led2,LOW);
digitalWrite (led3,LOW);
delay(300);
}
//imprimo o nivel a que cheguei e que volto comezar
Serial.print("Chegaches ao nivel ");
Serial.println(nivel);
Serial.println("Comezas no nivel 0!...");
delay(1000);
Serial.println("Adiante!");
//reinicio o nivel no que comezo
nivel=0;
//reinicio a variable de tempo de transicion do led
tempoAceso=1200;
}
//Funcion en caso de acertar
void acertas() {
//Gardo o estado en que estou coma estado anterior
botonAntes=digitalRead(boton);
//subo un nivel
nivel++;
//Encendo os tres leds durante 0,6 seg e os apago durante 0,4
digitalWrite (led1,HIGH);
digitalWrite (led2,HIGH);
digitalWrite (led3,HIGH);
delay(600);
digitalWrite (led1,LOW);
digitalWrite (led2,LOW);
digitalWrite (led3,LOW);
delay(400);
//imprimo a que nivel subin
Serial.print("Nivel ");
Serial.println(nivel);
//fago que o tempo de transicion sexa o 90% do anterior
tempoAceso=tempoAceso*0.9;
}
Unha vez subido o código, comproba que todo funciona correctamente. Comproba o teu nivel de reflexos, compara cos teus compañeiros e... imos a polos retos!
Retos:
Cambiando tempos:
Imos empezar por xogar cos tempos que hai no programa, e imos tunealos un pouco. Tenta a:
- Cambiar os tempos durante os que se acenden e apagan os leds cando acerto ou perdo. Fai que o parpadeo de perdiches() sexa máis lento e que cando acerto a luz se encenda durante 1 seg.
- Cambia o tempo inicial de encendido sexa menor... por exemplo dun segundo.
- Fai que en cada ronda que acerto o tempo de encendido baixe máis bruscamente, por exemplo que sexa o 80% do anterior. Proba tamén a facelo cunha operación de resta p.ex:
tempoAceso=tempoAceso-100;
Que diferenzas haberá na experiencia de xogo?
Cambiando textos:
Imos hackear tamén as mensaxes que recibimos, a ver se es capaz de:
- Persoaliza ao teu gusto as mensaxes do programa.
- Poderías inserirlle unha liña na que che dixera que tempo de transición había cando remata o xogo?
- Inserta unha mensaxe de parabéns que apareza cando o xogo remata e che di o nivel.
- Poderías facer que esa mensaxe cambiara segundo rematas por riba do nivel 10 ou por baixo? poderías facer unha mensaxe personalizada adaptada a cada nivel ou grupo de niveis? (p.ex: de nivel 1 a nivel 4: "es ben lento!"; de nivel 5 a nivel 8 "téñoos visto máis rápidos", de nivel 9 a nivel 12 "es áxil coma un esquío!" e por riba do nivel 12 "carai! es máis rápido que a luz!")
Cambiando luces:
- Fai que a secuencia de luces de perder sexa diferente, por exemplo que se acendan alternativamente os dous leds dos extremos e o do medio.
- Como poderías facer que o led no que temos que pulsar fose outro? PISTA: Hai dúas solucións, cambiando o programa ou... cambiando o circuito!
-Reto de Diego Fidalgo: Este é para tramposos impenitentes... Podes facer que sempre acertes, sexa cal sexa o botón que pulsas?
Gran reto final!
- Isto xa sería para enxeñeiros e enxeñeiras avanzadas, pero seguro que ti es capaz cun pouco de empeño. Serías capaz de engadir un novo led no xogo e adaptar o programa a esa modificación? Se o consigues, terás demostrado ser unha fiera da programación!