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!