Pouso Lunar foi um dos mais populares jogos em BASIC para microcomputadores (você pode ver uma versão clássica aqui). Esta versão do Pouso Lunar no Arduino, em tempo real, utiliza o Shield Arduino Multifunções Nível Intermediário para a interface com o operador.
O Jogo
Quando o jogo começa, você está no módulo lunar, a 1000 metros da superfície da Lua, caindo com uma velocidade de 50 m/s e uma aceleração de 5m/s2 (a gravidade da Lua simulada). Para pousar suavemente você precisa acionar o seu retrofoguete, tomando o cuidado para não ficar sem combustível (você tem inicialmente 150 unidades de combustível).
O display do shield apresenta alternadamente a distância e a velocidade do módulo Lunar. Os quatro LEDs do shield indicam quanto combustível você tem. Para acionar o retrofoguete você precisa apertar um dos três botões do shield, a quantidade de combustível queimada (e a freagem obtida) é crescente da esquerda para a direita:
- Botão S1 queima 7 unidades de combustível
- Botão S2 queima 14 unidades de combustível
- Botão S3 queima 21 unidades de combustível
Ao acabar o combustível os botões deixarão de fazer efeito e o módulo descera em queda livre. O jogo termina quando o módulo chegar à superfície da Lua, a velocidade do impacto fica piscando no display. Para iniciar um novo jogo pressione o botão de reset.
Material Necessário
Preparação
A montagem consiste apenas de encaixar o shield Multifunções no Arduino. Para evitar o risco dos pinos do display no shield encostarem no conector USB do Arduino recomendamos colar uma fita isolante no shield (embaixo do display).
O código utiliza a biblioteca <MultiFuncShield.h>, descrita no post “Projetos com o Shield Arduino Multifunções Nível Intermediário“. Para instalá-la, baixe o zip do link e o expanda no diretório “libraries” da pasta onde a IDE armazena os sketches:
Código
#include <TimerOne.h> #include <Wire.h> #include <MultiFuncShield.h> // Vamos tratar nós mesmos os botões const int pinBotao1 = A1; const int pinBotao2 = A2; const int pinBotao3 = A3; // Parâmetros da nossa simulação const float distanciaInicial = 1000.0; const int velocidadeInicial = 50.0; const int combustivelInicial = 150; const int gravidadeLunar = 5; // Variáveis da nossa simulação float distancia; int velocidade; int combustivel; // Iniciacao do programa void setup() { // Iniciações para o Shield Timer1.initialize(); MFS.initialize(&Timer1); // Descomente a linha abaixo se o buzzer do seu shield // tocar continuamente //digitalWrite(BEEPER_PIN, LOW); // Situacao inicial da simulação distancia = distanciaInicial; velocidade = velocidadeInicial; combustivel = combustivelInicial; // Indica tanque cheio MFS.writeLeds(LED_ALL, ON); } // Laco principal // Cada passada corresponde a 1 segundo de simulação void loop() { if (distancia <= 0) { // Chegou a superficie // Mostrar a velocidade piscando MFS.write(velocidade); MFS.blinkDisplay (DIGIT_1 | DIGIT_2 | DIGIT_3 | DIGIT_4, ON); // Aguardar reset for (;;) delay(100); } else { // Atualiza indicação do combustivel if (combustivel < 3*combustivelInicial/4) { MFS.writeLeds(LED_1, OFF); } if (combustivel < combustivelInicial/2) { MFS.writeLeds(LED_2, OFF); } if (combustivel < combustivelInicial/4) { MFS.writeLeds(LED_3, OFF); } if (combustivel <= 0) { MFS.writeLeds(LED_4, OFF); } // Mostra distancia e velocidade MFS.write((int) distancia); delay(500); MFS.write(velocidade); delay(500); // Determina a aceleração int acel = gravidadeLunar; int queima = 0; if (digitalRead(pinBotao3) == LOW) { queima = 21; } else if (digitalRead(pinBotao2) == LOW) { queima = 14; } else if (digitalRead(pinBotao1) == LOW) { queima = 7; } if (queima > combustivel) { queima = combustivel; } combustivel = combustivel - queima; acel = acel - queima; // Calcula a velocidade final no período int velocidadeFinal = velocidade + acel; if (velocidadeFinal < 0) { velocidadeFinal = 0; } // Atualiza distância distancia -= (velocidade + velocidadeFinal)/2; if (distancia < 0) { distancia = 0; } // Atualiza velocidade velocidade = velocidadeFinal; } }
Distância e velocidade são atualizados incrementalmente em intervalos de 1 segundo:
- A aceleração do módulo é a gravidade menos a queima do retrofoguete (aceleração negativa faz a velocidade diminuir)
- A velocidade ao final do intervalo é igual à velocidade inicial mais a aceleração
- A distância final é igual à distância inicial menos a média entre a velocidade inicial e a final
O código é uma adaptação de uma demonstração da linguagem Eleven.
Conclusão
Neste jogo temos uma simulação (bem simplificada) de um sistema real. Algumas sugestões de melhorias:
- Apresentar o combustível restante no display (você pode usar os LEDs para indicar qual valor está sendo mostrado)
- Permitir velocidade negativa (isto é, com o módulo se afastando da Lua)
- Considerar que o módulo fica mais leve à medida que o combustível é queimado
- Acrescentar efeitos sonoros usando o buzzer do shield
Gostou de ver o Pouso Lunar no Arduino? Ajude-nos a melhorar o blog comentando abaixo sobre este tutorial.